blob: b8283124075994a9b7be9ff8868e4cbd98fd8b89 [file] [log] [blame]
/*-
* Copyright (C) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
*
* This file was distributed by Oracle as part of a version of Oracle Berkeley
* DB Java Edition made available at:
*
* http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index.html
*
* Please see the LICENSE file included in the top-level directory of the
* appropriate version of Oracle Berkeley DB Java Edition for a copy of the
* license and additional information.
*/
package com.sleepycat.je;
/**
* Specifies the attributes of database cursor. An instance created with the
* default constructor is initialized with the system's default settings.
*/
public class CursorConfig implements Cloneable {
/**
* Default configuration used if null is passed to methods that create a
* cursor.
*/
public static final CursorConfig DEFAULT = new CursorConfig();
/**
* A convenience instance to configure read operations performed by the
* cursor to return modified but not yet committed data.
*/
public static final CursorConfig READ_UNCOMMITTED = new CursorConfig();
/**
* A convenience instance to configure a cursor for read committed
* isolation.
*
* This ensures the stability of the current data item read by the cursor
* but permits data read by this cursor to be modified or deleted prior to
* the commit of the transaction.
*/
public static final CursorConfig READ_COMMITTED = new CursorConfig();
static {
READ_UNCOMMITTED.setReadUncommitted(true);
READ_COMMITTED.setReadCommitted(true);
}
private boolean readUncommitted = false;
private boolean readCommitted = false;
private boolean nonSticky = false;
/**
* An instance created using the default constructor is initialized with
* the system's default settings.
*/
public CursorConfig() {
}
/**
* Configures read operations performed by the cursor to return modified
* but not yet committed data.
*
* @param readUncommitted If true, configure read operations performed by
* the cursor to return modified but not yet committed data.
*
* @see LockMode#READ_UNCOMMITTED
*
* @return this
*/
public CursorConfig setReadUncommitted(boolean readUncommitted) {
setReadUncommittedVoid(readUncommitted);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setReadUncommittedVoid(boolean readUncommitted) {
this.readUncommitted = readUncommitted;
}
/**
* Returns true if read operations performed by the cursor are configured
* to return modified but not yet committed data.
*
* @return true if read operations performed by the cursor are configured
* to return modified but not yet committed data.
*
* @see LockMode#READ_UNCOMMITTED
*/
public boolean getReadUncommitted() {
return readUncommitted;
}
/**
* Configures read operations performed by the cursor to obey read
* committed isolation. Read committed isolation provides for cursor
* stability but not repeatable reads. Data items which have been
* previously read by this transaction may be deleted or modified by other
* transactions before the cursor is closed or the transaction completes.
*
* @param readCommitted If true, configure read operations performed by
* the cursor to obey read committed isolation.
*
* @see LockMode#READ_COMMITTED
*
* @return this
*/
public CursorConfig setReadCommitted(boolean readCommitted) {
setReadCommittedVoid(readCommitted);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setReadCommittedVoid(boolean readCommitted) {
this.readCommitted = readCommitted;
}
/**
* Returns true if read operations performed by the cursor are configured
* to obey read committed isolation.
*
* @return true if read operations performed by the cursor are configured
* to obey read committed isolation.
*
* @see LockMode#READ_COMMITTED
*/
public boolean getReadCommitted() {
return readCommitted;
}
/**
* Configures the behavior of the cursor when a cursor movement operation
* returns {@link OperationStatus#NOTFOUND}.
*
* By default, a cursor is "sticky", meaning that the prior position is
* maintained by cursor movement operations, and the cursor stays at the
* prior position when the operation does not succeed. For example, if
* {@link Cursor#getFirst} is called successfully, and then
* {@link Cursor#getNext} is called, if {@code getNext} returns
* {@code NOTFOUND} the cursor will remain positioned on the first record.
* <p>
* Also, as part of maintaining the prior position, the lock on the record
* at the current position will be held (at least) until after a cursor
* movement operation succeeds and acquires a lock on the record at the new
* position. In the example above, a lock on the first record will still
* be held after {@code getNext} returns {@code NOTFOUND}.
* <p>
* If the cursor is configured to be non-sticky, the prior position is
* not maintained, and this has certain performance advantages:
* <ul>
* <li>
* Some processing is avoided because the prior position is not
* maintained.
* </li>
* <li>
* The lock on the record at the prior position is released before
* acquiring the lock on the record at the new position (when the
* cursor movement operation succeeds.) This can help to prevent
* deadlocks in certain situations. Namely, if the cursor's isolation
* mode allows locks to be released when moving to a new position, then
* only one lock at a time will be held by the cursor. Holding multiple
* locks at a time can cause deadlocks, when locks are acquired in
* different orders by different threads, for example, when one cursor
* is scanning forward and another cursor is scanning backward. Note
* that this optimization does not apply to repeatable-read or
* serializable isolation, since these modes require that locks are
* not released by cursor movement operations.
* </li>
* </ul>
* <p>
* However, when the cursor is configured as non-sticky and {@code getNext}
* returns {@code NOTFOUND} in the example above, the cursor position will
* be uninitialized, as if it had just been opened. Also, the lock on the
* first record will have been released (except when repeatable-read or
* serializable isolation is configured.) To move to the first record (and
* lock it), {@code getFirst} must be called again.
* <p>
* Also note that in certain circumstances, internal algorithms require
* that the prior position is retained, and the operation will behave as if
* the cursor is sticky. Specifically, these are only the following
* methods, and only when called on a database with duplicates configured:
* <ul>
* <li>{@link Cursor#putNoOverwrite}</li>
* <li>{@link Cursor#getNextDup}}</li>
* <li>{@link Cursor#getPrevDup}}</li>
* <li>{@link Cursor#getNextNoDup}}</li>
* <li>{@link Cursor#getPrevNoDup}}</li>
* </ul>
*
* @param nonSticky if false (the default), the prior position is
* maintained by cursor movement operations, and the cursor stays at the
* prior position when {@code NOTFOUND} is returned. If true, the prior
* position is not maintained, and the cursor is reinitialized when
* {@code NOTFOUND} is returned.
*
* @return this
*/
public CursorConfig setNonSticky(boolean nonSticky) {
setNonStickyVoid(nonSticky);
return this;
}
/**
* @hidden
* The void return setter for use by Bean editors.
*/
public void setNonStickyVoid(boolean nonSticky) {
this.nonSticky = nonSticky;
}
/**
* Returns the non-sticky setting.
*
* @see #setNonSticky
*/
public boolean getNonSticky() {
return nonSticky;
}
/**
* Returns a copy of this configuration object.
*/
@Override
public CursorConfig clone() {
try {
return (CursorConfig) super.clone();
} catch (CloneNotSupportedException willNeverOccur) {
return null;
}
}
/**
* Returns the values for each configuration attribute.
*
* @return the values for each configuration attribute.
*/
@Override
public String toString() {
return "readUncommitted=" + readUncommitted +
"\nreadCommitted=" + readCommitted +
"\n";
}
}