All Downloads are FREE. Search and download functionalities are using the official Maven repository.

oracle.kv.impl.api.ops.PutIfPresentHandler Maven / Gradle / Ivy

Go to download

NoSQL Database Server - supplies build and runtime support for the server (store) side of the Oracle NoSQL Database.

The newest version!
/*-
 * Copyright (C) 2011, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This file was distributed by Oracle as part of a version of Oracle NoSQL
 * Database made available at:
 *
 * http://www.oracle.com/technetwork/database/database-technologies/nosqldb/downloads/index.html
 *
 * Please see the LICENSE file included in the top-level directory of the
 * appropriate version of Oracle NoSQL Database for a copy of the license and
 * additional information.
 */

package oracle.kv.impl.api.ops;

import static oracle.kv.impl.api.ops.OperationHandler.CURSOR_DEFAULT;

import com.sleepycat.je.Cursor;
import com.sleepycat.je.Database;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Get;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationResult;
import com.sleepycat.je.Put;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.WriteOptions;

import oracle.kv.ReturnValueVersion.Choice;
import oracle.kv.Version;
import oracle.kv.impl.api.ops.InternalOperation.OpCode;
import oracle.kv.impl.rep.migration.MigrationStreamHandle;
import oracle.kv.impl.topo.PartitionId;
import oracle.kv.impl.util.TxnUtil;

/**
 * Server handler for {@link PutIfPresent}.
 *
 * Throughput calculation
 * +---------------------------------------------------------------------------+
 * |    Op         | Choice | # |          Read        |       Write           |
 * |---------------+--------+---+----------------------+-----------------------|
 * |               |        | P |        MIN_READ      |    new record size +  |
 * |               |        |   |                      |    old record size    |
 * |               |  NONE  |---+----------------------+-----------------------|
 * |               |        | A |        MIN_READ      |           0           |
 * |               +--------+---+----------------------+-----------------------|
 * |               |        | P |        MIN_READ      |    new record size +  |
 * |               |        |   |                      |    old record size    |
 * | PutIfPresent  | VERSION|---+----------------------+-----------------------|
 * |               |        | A |        MIN_READ      |           0           |
 * |               +--------+---+----------------------+-----------------------|
 * |               |        | P |    old record size   |    new record size +  |
 * |               |        |   |                      |    old record size    |
 * |               |  VALUE |---+----------------------+-----------------------|
 * |               |        | A |        MIN_READ      |           0           |
 * +---------------------------------------------------------------------------+
 *      # = Target record is present (P) or absent (A)
 */
class PutIfPresentHandler extends BasicPutHandler {

    PutIfPresentHandler(OperationHandler handler) {
        super(handler, OpCode.PUT_IF_PRESENT, PutIfPresent.class);
    }

    @Override
    Result execute(PutIfPresent op, Transaction txn, PartitionId partitionId) {

        verifyDataAccess(op);

        ResultValueVersion prevVal = null;
        long expTime = 0L;
        Version version = null;
        boolean wasUpdate;

        byte[] keyBytes = op.getKeyBytes();
        byte[] valueBytes = op.getValueBytes();

        assert (keyBytes != null) && (valueBytes != null);

        final DatabaseEntry keyEntry = new DatabaseEntry(keyBytes);
        final DatabaseEntry dataEntry = valueDatabaseEntry(valueBytes);

        OperationResult opres;
        WriteOptions jeOptions = makeOption(op.getTTL(), op.getUpdateTTL());

        final Database db = getRepNode().getPartitionDB(partitionId);

        final Cursor cursor = db.openCursor(txn, CURSOR_DEFAULT);

        try {
            final Choice choice = op.getReturnValueVersionChoice();

            final DatabaseEntry prevData =
                (choice.needValue() ? new DatabaseEntry() : NO_DATA);

            opres = cursor.get(keyEntry, prevData, Get.SEARCH,
                               LockMode.RMW.toReadOptions());

            if (opres == null) {
                op.addReadBytes(MIN_READ);
                wasUpdate = false;

            } else {
                prevVal = getBeforeUpdateInfo(choice, cursor, prevData, opres);

                op.addWriteBytes(getStorageSize(cursor), 0); /* Old value */

                if (choice.needValue()) {
                    op.addReadBytes(getStorageSize(cursor));
                } else {
                    op.addReadBytes(MIN_READ);
                }

                opres = putEntry(cursor, null, dataEntry,
                                 Put.CURRENT, jeOptions);

                op.addWriteBytes(getStorageSize(cursor),
                                 getNIndexWrites(cursor));

                expTime = opres.getExpirationTime();
                version = getVersion(cursor);
                wasUpdate = true;

                reserializeResultValue(op, prevVal);

                MigrationStreamHandle.get().addPut(keyEntry,
                                                   dataEntry,
                                                   version.getVLSN(),
                                                   expTime);
            }

            return new Result.PutResult(getOpCode(),
                                        op.getReadKB(),
                                        op.getWriteKB(),
                                        prevVal,
                                        version,
                                        expTime,
                                        wasUpdate);
        } finally {
            TxnUtil.close(cursor);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy