Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*-
    * See the file LICENSE for redistribution information.
    *
    * Copyright (c) 2002, 2013 Oracle and/or its affiliates.  All rights reserved.
    *
    */
   
   package com.sleepycat.je;
   
  import java.io.Closeable;
  import java.util.List;
  
A database handle.

Database attributes are specified in the DatabaseConfig class. Database handles are free-threaded and may be used concurrently by multiple threads.

To open an existing database with default attributes:

     Environment env = new Environment(home, null);
     Database myDatabase = env.openDatabase(null, "mydatabase", null);
 

To create a transactional database that supports duplicates:

     DatabaseConfig dbConfig = new DatabaseConfig();
     dbConfig.setTransactional(true);
     dbConfig.setAllowCreate(true);
     dbConfig.setSortedDuplicates(true);
     Database db = env.openDatabase(txn, "mydatabase", dbConfig);
 
  
  public class Database implements Closeable {
  
      /*
       * DbState embodies the Database handle state.
       */
      enum DbState {
          OPEN, CLOSED, INVALID, PREEMPTED
      }
  
      /* The current state of the handle. */
      private volatile DbState state;
      /* The DatabasePreemptedException cause when state == PREEMPTED. */
  
      /* Handles onto the owning environment and the databaseImpl object. */
      Environment envHandle;            // used by subclasses
      private DatabaseImpl databaseImpl;
  
      /*
       * Used to store per-Database handle properties: allow create,
       * exclusive create, read only and use existing config. Other Database-wide
       * properties are stored in DatabaseImpl.
       */
  
      /* True if this handle permits write operations; */
      private boolean isWritable;
  
      /* Record how many open cursors on this database. */
      private final AtomicInteger openCursors = new AtomicInteger();
  
      /* Locker that owns the NameLN lock held while the Database is open. */
      private HandleLocker handleLocker;
  
      /*
       * DatabaseTrigger list.  The list is null if empty, and is checked for
       * null to avoiding read locking overhead when no triggers are present.
       * Access to this list is protected by the shared trigger latch in
       * EnvironmentImpl.
       */
      private List<DatabaseTriggertriggerList;
  
      protected final Logger logger;

    
Creates a database but does not open or fully initialize it. Is protected for use in compat package.

Parameters:
env
 
     protected Database(final Environment env) {
         this. = env;
          = null;
          = .getEnvironmentImpl().getLogger();
     }

    
Creates a database, called by Environment.
 
     DatabaseImpl initNew(final Environment env,
                          final Locker locker,
                          final String databaseName,
                          final DatabaseConfig dbConfig)
         throws DatabaseException {
 
         dbConfig.validateForNewDb();
 
         init(envdbConfig);
 
         /* Make the databaseImpl. */
         EnvironmentImpl environmentImpl =
             DbInternal.getEnvironmentImpl();
          = environmentImpl.getDbTree().createDb
             (lockerdatabaseNamedbConfig);
         .addReferringHandle(this);
         return ;
     }

    
Opens a database, called by Environment.
 
     void initExisting(final Environment env,
                       final Locker locker,
                       final DatabaseImpl dbImpl,
                       final String databaseName,
                       final DatabaseConfig dbConfig)
         throws DatabaseException {
 
         /*
          * Make sure the configuration used for the open is compatible with the
          * existing databaseImpl.
          */
         validateConfigAgainstExistingDb(lockerdatabaseNamedbConfig,
                                         dbImpl);
 
         init(envdbConfig);
         this. = dbImpl;
         dbImpl.addReferringHandle(this);
     }
 
     private void init(final Environment envfinal DatabaseConfig config) {
         assert  != null;
          = env;
          = config.cloneConfig();
          = !.getReadOnly();
          = .;
     }

    
Sees if this new handle's configuration is compatible with the pre-existing database.
 
     private void validateConfigAgainstExistingDb(Locker locker,
                                                  final String databaseName,
                                                  final DatabaseConfig config,
                                                  final DatabaseImpl dbImpl)
         throws DatabaseException {
 
         /*
          * The sortedDuplicates, temporary, and replicated properties are
          * persistent and immutable.  But they do not need to be specified if
          * the useExistingConfig property is set.
          */
         if (!config.getUseExistingConfig()) {
             validatePropertyMatches
                 ("sortedDuplicates"dbImpl.getSortedDuplicates(),
                  config.getSortedDuplicates());
             validatePropertyMatches
                 ("temporary"dbImpl.isTemporary(),
                  config.getTemporary());
             /* Only check replicated if the environment is replicated. */
             if (.getEnvironmentImpl().isReplicated()) {
                 validatePropertyMatches
                     ("replicated"dbImpl.isReplicated(),
                      DbInternal.getReplicated(config));
             }
         }
 
         /*
          * The transactional and deferredWrite properties are kept constant
          * while any handles are open, and set when the first handle is opened.
          * But if an existing handle is open and the useExistingConfig property
          * is set, then they do not need to be specified.
          */
         if (dbImpl.hasOpenHandles()) {
             if (!config.getUseExistingConfig()) {
                 validatePropertyMatches
                     ("transactional"dbImpl.isTransactional(),
                      config.getTransactional());
                 validatePropertyMatches
                     ("deferredWrite"dbImpl.isDurableDeferredWrite(),
                      config.getDeferredWrite());
             }
         } else {
             dbImpl.setTransactional(config.getTransactional());
             dbImpl.setDeferredWrite(config.getDeferredWrite());
         }
 
         /*
          * If this database handle uses the existing config, we shouldn't
          * search for and write any changed attributes to the log.
          */
         if (config.getUseExistingConfig()) {
             return;
         }
 
         /* Write any changed, persistent attributes to the log. */
         boolean dbImplModified = false;
 
         /* Only re-set the comparators if the override is allowed. */
         if (config.getOverrideBtreeComparator()) {
             dbImplModified |= dbImpl.setBtreeComparator
                 (config.getBtreeComparator(),
                  config.getBtreeComparatorByClassName());
         }
 
         if (config.getOverrideDuplicateComparator()) {
             dbImplModified |= dbImpl.setDuplicateComparator
                 (config.getDuplicateComparator(),
                  config.getDuplicateComparatorByClassName());
         }
 
         dbImplModified |= dbImpl.setTriggers(locker,
                                              databaseName,
                                              config.getTriggers(),
                                              config.getOverrideTriggers());
 
         /* Check if KeyPrefixing property is updated. */
         boolean newKeyPrefixing = config.getKeyPrefixing();
         if (newKeyPrefixing != dbImpl.getKeyPrefixing()) {
             dbImplModified = true;
             if (newKeyPrefixing) {
                 dbImpl.setKeyPrefixing();
             } else {
                 dbImpl.clearKeyPrefixing();
             }
         }
 
         /*
          * Check if NodeMaxEntries properties are updated.
          */
         int newNodeMaxEntries = config.getNodeMaxEntries();
         if (newNodeMaxEntries != 0 &&
             newNodeMaxEntries != dbImpl.getNodeMaxTreeEntries()) {
             dbImplModified = true;
             dbImpl.setNodeMaxTreeEntries(newNodeMaxEntries);
         }
 
         /* Do not write LNs in a read-only environment.  Also see [#15743]. */
         EnvironmentImpl envImpl = .getEnvironmentImpl();
         if (dbImplModified && !envImpl.isReadOnly()) {
 
             /* Write a new NameLN to the log. */
             try {
                 envImpl.getDbTree().updateNameLN
                     (lockerdbImpl.getName(), null);
             } catch (LockConflictException e) {
                 throw new IllegalStateException
                     ("DatabaseConfig properties may not be updated when the " +
                      "database is already open; first close other open " +
                      "handles for this database."e);
             }
 
             /* Dirty the root. */
             envImpl.getDbTree().modifyDbRoot(dbImpl);
         }
 
         /*
          * CacheMode and Strategy are changed for all handles, but are not
          * persistent.
          */
         dbImpl.setCacheMode(config.getCacheMode());
         dbImpl.setCacheModeStrategy(config.getCacheModeStrategy());
     }

    

Throws:
java.lang.IllegalArgumentException via Environment.openDatabase and openSecondaryDatabase.
 
     private void validatePropertyMatches(final String propName,
                                          final boolean existingValue,
                                          final boolean newValue)
         throws IllegalArgumentException {
 
         if (newValue != existingValue) {
             throw new IllegalArgumentException
                 ("You can't open a Database with a " + propName +
                  " configuration of " + newValue +
                  " if the underlying database was created with a " +
                  propName + " setting of " + existingValue + '.');
         }
     }

    
Discards the database handle.

When closing the last open handle for a deferred-write database, any cached database information is flushed to disk as if sync() were called.

The database handle should not be closed while any other handle that refers to it is not yet closed; for example, database handles should not be closed while cursor handles into the database remain open, or transactions that include operations on the database have not yet been committed or aborted. Specifically, this includes Cursor and Transaction handles.

When multiple threads are using the Database handle concurrently, only a single thread may call this method.

When called on a database that is the primary database for a secondary index, the primary database should be closed only after all secondary indices which reference it have been closed.

The database handle may not be accessed again after this method is called, regardless of the method's success or failure, with one exception: the close method itself may be called any number of times.

WARNING: To guard against memory leaks, the application should discard all references to the closed handle. While BDB makes an effort to discard references from closed objects to the allocated memory for an environment, this behavior is not guaranteed. The safe course of action for an application is to discard all references to closed BDB objects.

Throws:
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if cursors associated with this database are still open.
See also:
DatabaseConfig.setDeferredWrite(boolean) DatabaseConfig.setDeferredWrite
 
     public void close()
         throws DatabaseException {
 
         try {
             closeInternal(true /*doSyncDw*/true /*deleteTempDb*/,
                           .null /*preemptedException*/);
         } catch (Error E) {
             DbInternal.getEnvironmentImpl().invalidate(E);
             throw E;
         }
     }
 
     /*
      * This method is private for now because it is incomplete.  To fully
      * implement it we must clear all dirty nodes for the database that is
      * closed, since otherwise they will be flushed during the next checkpoint.
      */
     @SuppressWarnings("unused")
     private void closeNoSync()
         throws DatabaseException {
 
         try {
             closeInternal(false /*doSyncDw*/true /*deleteTempDb*/,
                           .null /*preemptedException*/);
         } catch (Error E) {
             DbInternal.getEnvironmentImpl().invalidate(E);
             throw E;
         }
     }

    
Marks the handle as preempted when the handle lock is stolen by the HA replayer, during replay of a naming operation (remove, truncate or rename). This causes DatabasePreemtpedException to be thrown on all subsequent use of the handle or cursors opened on this handle. [#17015]
 
     synchronized void setPreempted(final String dbNamefinal String msg) {
         OperationFailureException preemptedException =
                 (msgdbNamethis);
         closeInternal(false /*doSyncDw*/false /*deleteTempDb*/,
                       .preemptedException);
     }

    
Invalidates the handle when the transaction used to open the database is aborted. Note that this method (unlike close) does not perform sync and removal of DW DBs. A DW DB cannot be transactional.
 
     synchronized void invalidate() {
         closeInternal(false /*doSyncDw*/false /*deleteTempDb*/,
                       .null /*preemptedException*/);
     }
 
     private void
         closeInternal(final boolean doSyncDw,
                       final boolean deleteTempDb,
                       final DbState newState,
                       final OperationFailureException preemptedException)
         throws DatabaseException {
 
         StringBuilder errors = null;
         DatabaseImpl dbClosed = null;
 
         synchronized (this) {
 
             /* Do nothing if handle was previously closed. */
             if ( != .) {
                 return;
             }
 
             /*
              * Check env only after checking for closed db, to mimic close()
              * behavior for Cursors, etc, and avoid unnecessary exception
              * handling.  [#21264]
              */
             checkEnv();
 
             /*
              * The state should be changed ASAP during close, so that
              * addCursor and removeCursor will see the updated state ASAP.
              */
              = newState;
              = preemptedException;
 
             /*
              * Throw a DatabaseException if there are open cursors while
              * closing a Database.
              */
             if (newState == . &&
                 .get() != 0) {
                 errors = new StringBuilder();
                 errors.append("Database still has " + .get() +
                               " open cursors while trying to close.");
             }
 
             trace(."Database.close: "nullnull);
 
             /* Disassociate triggers before closing. */
             removeAllTriggers();
 
             .removeReferringHandle(this);
 
             if ( != null) {
                 dbClosed = ;
                 .removeReferringHandle(this);
                 .getEnvironmentImpl().
                     getDbTree().releaseDb();
 
                 /*
                  * Database.close may be called after an abort.  By setting the
                  * databaseImpl field to null we ensure that close won't call
                  * releaseDb or endOperation. [#13415]
                  */
                  = null;
 
                 if ( != null) {
 
                     /*
                      * If the handle was preempted, we mark the locker as
                      * only-abortable with the DatabasePreemptedException.  If
                      * the handle locker is a user txn, this causes the
                      * DatabasePreemptedException to be thrown if the user
                      * attempts to commit, or continue to use, the txn, rather
                      * than throwing a LockConflictException.  [#17015]
                      */
                     if (newState == .) {
                         .setOnlyAbortable(preemptedException);
                     }
 
                     /*
                      * Tell our protecting txn that we're closing. If this type
                      * of transaction doesn't live beyond the life of the
                      * handle, it will release the db handle lock.
                      */
                     if (newState == .) {
                         if (isWritable() &&
                             (dbClosed.noteWriteHandleClose() == 0)) {
                             TriggerManager.runCloseTriggers(,
                                                             dbClosed);
                         }
                         .operationEnd(true);
                     } else {
                         .operationEnd(false);
                     }
 
                     /* Null-out indirect reference to environment. */
                      = null;
                 }
             }
         }
 
         /*
          * Notify the database when a handle is closed.  This should not be
          * done while synchronized since it may perform database removal or
          * sync.  Statements above are synchronized but this section must not
          * be.
          */
         if (dbClosed != null) {
             dbClosed.handleClosed(doSyncDwdeleteTempDb);
         }
 
         if (errors != null) {
             throw new IllegalStateException(errors.toString());
         }
     }

    
Flushes any cached information for this database to disk; only applicable for deferred-write databases.

Note that deferred-write databases are automatically flushed to disk when the close() method is called.

Throws:
com.sleepycat.je.rep.DatabasePreemptedException in a replicated environment if the master has truncated, removed or renamed the database.
OperationFailureException if this exception occurred earlier and caused the transaction to be invalidated.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.UnsupportedOperationException if this is not a deferred-write database, or this database is read-only.
java.lang.IllegalStateException if the database has been closed.
See also:
DatabaseConfig.setDeferredWrite(boolean) DatabaseConfig.setDeferredWrite
 
     public void sync()
 
         checkEnv();
         checkOpen("Can't call Database.sync:");
         checkWritable("sync");
         trace(."Database.sync"nullnullnullnull);
 
         .sync(true);
     }

    
Opens a sequence in the database.

Parameters:
txn For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
key The key DatabaseEntry of the sequence.
config The sequence attributes. If null, default attributes are used.
Returns:
a new Sequence handle.
Throws:
SequenceExistsException if the sequence record already exists and the SequenceConfig ExclusiveCreate parameter is true.
SequenceNotFoundException if the sequence record does not exist and the SequenceConfig AllowCreate parameter is false.
OperationFailureException if one of the Read Operation Failures occurs. If the sequence does not exist and the SequenceConfig.setAllowCreate(boolean) parameter is true, then one of the Write Operation Failures may also occur.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.UnsupportedOperationException if this database is read-only, or this database is configured for duplicates.
java.lang.IllegalStateException if the Sequence record is deleted by another thread during this method invocation, or the database has been closed.
java.lang.IllegalArgumentException if an invalid parameter is specified, for example, an invalid SequenceConfig parameter.
 
     public Sequence openSequence(final Transaction txn,
                                  final DatabaseEntry key,
                                  final SequenceConfig config)
 
         try {
             checkEnv();
             DatabaseUtil.checkForNullDbt(key"key"true);
             checkOpen("Can't call Database.openSequence:");
             checkWritable("openSequence");
             trace(."Database.openSequence"txnkeynullnull);
 
             return new Sequence(thistxnkeyconfig);
         } catch (Error E) {
             DbInternal.getEnvironmentImpl().invalidate(E);
             throw E;
         }
     }

    
Removes the sequence from the database. This method should not be called if there are open handles on this sequence.

Parameters:
txn For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
key The key DatabaseEntry of the sequence.
Throws:
OperationFailureException if one of the Write Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.UnsupportedOperationException if this database is read-only.
 
     public void removeSequence(final Transaction txnfinal DatabaseEntry key)
         throws DatabaseException {
 
         try {
             delete(txnkey);
         } catch (Error E) {
             DbInternal.getEnvironmentImpl().invalidate(E);
             throw E;
         }
     }

    
Returns a cursor into the database.

Parameters:
txn the transaction used to protect all operations performed with the cursor, or null if the operations should not be transaction protected. If the database is non-transactional, null must be specified. For a transactional database, the transaction is optional for read-only access and required for read-write access.
cursorConfig The cursor attributes. If null, default attributes are used.
Returns:
A database cursor.
Throws:
com.sleepycat.je.rep.DatabasePreemptedException in a replicated environment if the master has truncated, removed or renamed the database.
OperationFailureException if this exception occurred earlier and caused the transaction to be invalidated.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
java.lang.IllegalArgumentException if an invalid parameter is specified, for example, an invalid CursorConfig parameter.
 
     public Cursor openCursor(final Transaction txn,
                              final CursorConfig cursorConfig)
         throws DatabaseExceptionIllegalArgumentException {
 
         try {
             checkEnv();
             checkOpen("Can't open a cursor");
             CursorConfig useConfig =
                 (cursorConfig == null) ? . : cursorConfig;
 
             if (useConfig.getReadUncommitted() &&
                 useConfig.getReadCommitted()) {
                 throw new IllegalArgumentException
                     ("Only one may be specified: " +
                      "ReadCommitted or ReadUncommitted");
             }
 
             trace(."Database.openCursor"txncursorConfig);
             Cursor ret = newDbcInstance(txnuseConfig);
 
             return ret;
         } catch (Error E) {
             DbInternal.getEnvironmentImpl().invalidate(E);
             throw E;
         }
     }

    
Create a DiskOrderedCursor to iterate over the records in 'this' Database. Because the retrieval is based on Log Sequence Number (LSN) order rather than key order, records are returned in unsorted order in exchange for generally faster retrieval. LSN order approximates disk sector order.

See DiskOrderedCursor for more details and a description of the consistency guarantees provided by the scan.

WARNING: After calling this method, deletion of log files by the JE log cleaner will be disabled until DiskOrderedCursor.close() is called. To prevent unbounded growth of disk usage, be sure to call DiskOrderedCursor.close() to re-enable log file deletion.

 
     public DiskOrderedCursor
         openCursor(final DiskOrderedCursorConfig cursorConfig)
         throws DatabaseExceptionIllegalArgumentException {
 
         try {
             checkEnv();
             checkOpen("Can't open a cursor");
             DiskOrderedCursorConfig useConfig =
                 (cursorConfig == null) ?
                 . :
                 cursorConfig;
 
             trace(."Database.openForwardCursor",
                   nullcursorConfig);
             DiskOrderedCursor ret = new DiskOrderedCursor(thisuseConfig);
 
             return ret;
         } catch (Error E) {
             DbInternal.getEnvironmentImpl().invalidate(E);
             throw E;
         }
     }

    
Is overridden by SecondaryDatabase.
 
     Cursor newDbcInstance(final Transaction txn,
                           final CursorConfig cursorConfig)
         throws DatabaseException {
 
         return new Cursor(thistxncursorConfig);
     }

    
Removes key/data pairs from the database.

The key/data pair associated with the specified key is discarded from the database. In the presence of duplicate key values, all records associated with the designated key will be discarded.

The key/data pair is also deleted from any associated secondary databases.

Parameters:
txn For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
key the key DatabaseEntry operated on.
Returns:
The method will return OperationStatus.NOTFOUND if the specified key is not found in the database; otherwise the method will return OperationStatus.SUCCESS.
Throws:
OperationFailureException if one of the Write Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.UnsupportedOperationException if this database is read-only.
java.lang.IllegalStateException if the database has been closed.
java.lang.IllegalArgumentException if an invalid parameter is specified.
 
     public OperationStatus delete(final Transaction txn,
                                   final DatabaseEntry key)
         throws DeleteConstraintException,
                LockConflictException,
                DatabaseException,
                UnsupportedOperationException,
                IllegalArgumentException {
 
         try {
             checkEnv();
             DatabaseUtil.checkForNullDbt(key"key"true);
             checkOpen("Can't call Database.delete:");
             checkWritable("delete");
             trace(."Database.delete"txnkeynullnull);
 
             OperationStatus commitStatus = .;
             Locker locker = null;
             try {
                 locker = LockerFactory.getWritableLocker
                     (txn,
                      .isInternalDb(),
                      isTransactional(),
                      .isReplicated()); // autoTxnIsReplicated
                 commitStatus = deleteInternal(lockerkeynull);
                 return commitStatus;
             } finally {
                 if (locker != null) {
                     locker.operationEnd(commitStatus);
                 }
             }
         } catch (Error E) {
             DbInternal.getEnvironmentImpl().invalidate(E);
             throw E;
         }
     }
 
     /*
      * This is commented out until we agree on whether this should even be in
      * the API.  See [14264].
     private OperationStatus delete(Transaction txn,
                                    DatabaseEntry key,
                                    DatabaseEntry data)
         throws DatabaseException {
 
         try {
             checkEnv();
             DatabaseUtil.checkForNullDbt(key, "key", true);
             DatabaseUtil.checkForNullDbt(data, "data", true);
             // FUTURE: Ensure data is not partial
             checkOpen("Can't call Database.delete:");
             checkWritable("delete");
             trace(Level.FINEST, "Database.delete", txn, key, data, null);
 
             OperationStatus commitStatus = OperationStatus.NOTFOUND;
             Locker locker = null;
             try {
                 locker = LockerFactory.getWritableLocker
                     (envHandle, txn, isTransactional());
                 commitStatus = deleteInternal(locker, key, data);
                 return commitStatus;
             } finally {
                 if (locker != null) {
                     locker.operationEnd(commitStatus);
                 }
             }
         } catch (Error E) {
             DbInternal.getEnvironmentImpl(envHandle).invalidate(E);
             throw E;
         }
     }
     */

    
Internal version of delete() that does no parameter checking. Notify triggers. Deletes all duplicates.
 
     OperationStatus deleteInternal(final Locker locker,
                                    final DatabaseEntry key,
                                    final DatabaseEntry data)
         throws DatabaseException {
 
         Cursor cursor = null;
         try {
             cursor = new Cursor(thislockernull);
             cursor.setNonCloning(true);
             OperationStatus commitStatus = .;
 
             final boolean doNotifyTriggers = hasTriggers();
             final boolean hasUserTriggers = .getTriggers() != null;
 
             /* Position a cursor at the specified data record. */
             DatabaseEntry oldData;
             OperationStatus searchStatus;
             if (data == null) {
                 oldData = new DatabaseEntry();
                 /* Fetch old data with RMW to avoid lock upgrades. */
                 LockMode lockMode = .;
                 /* Do not fetch old data unless needed for triggers. */
                 if (!doNotifyTriggers && !hasUserTriggers) {
                     oldData.setPartial(0, 0, true);
 
                     /*
                      * If we don't need the data, use dirty read to enable the
                      * uncontended lock optimization.
                      */
                     lockMode = .;
                 }
                 searchStatus =
                     cursor.search(keyoldDatalockMode.);
             } else {
                 oldData = data;
                 searchStatus =
                     cursor.search(keyoldData..);
             }
 
             /* Delete all records with that key. */
             if (searchStatus == .) {
                 do {
 
                     /*
                      * Notify triggers before the actual deletion so that a
                      * primary record never exists while secondary keys refer
                      * to it.  This is relied on by secondary read-uncommitted.
                      */
                     if (doNotifyTriggers) {
                         notifyTriggers(lockerkeyoldDatanull);
                     }
 
                     /* The actual deletion. */
                     commitStatus =
                         cursor.deleteNoNotify(.getRepContext());
                     if (commitStatus != .) {
                         return commitStatus;
                     }
 
                     if (hasUserTriggers) {
                         // TODO: Mark, do we need "pre" triggers for our
                         // indexes as above?
                         TriggerManager.runDeleteTriggers(locker,
                                                          keyoldData);
                     }
 
                     if (data != null) {
                         /* delete(key, data) called so only delete one item. */
                         break;
                     }
 
                     /* Get another duplicate. */
                     if (.getSortedDuplicates()) {
                         searchStatus =
                             cursor.retrieveNext(keyoldData,
                                                 .,
                                                 .);
                     } else {
                         searchStatus = .;
                     }
                 } while (searchStatus == .);
                 commitStatus = .;
             }
             return commitStatus;
         } finally {
             if (cursor != null) {
                 cursor.close();
             }
         }
     }

    
Retrieves the key/data pair with the given key. If the matching key has duplicate values, the first data item in the set of duplicates is returned. Retrieval of duplicates requires the use of Cursor operations.

Parameters:
txn For a transactional database, an explicit transaction may be specified to transaction-protect the operation, or null may be specified to perform the operation without transaction protection. For a non-transactional database, null must be specified.
key the key used as input. It must be initialized with a non-null byte array by the caller.
data the data returned as output. Its byte array does not need to be initialized by the caller. A partial data item may be specified to optimize for key only or partial data retrieval.
lockMode the locking attributes; if null, default attributes are used.
Returns:
OperationStatus.NOTFOUND if no matching key/data pair is found; otherwise, OperationStatus.SUCCESS.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
java.lang.IllegalArgumentException if an invalid parameter is specified.
 
     public OperationStatus get(final Transaction txn,
                                final DatabaseEntry key,
                                final DatabaseEntry data,
                                LockMode lockMode)
         throws LockConflictException,
                DatabaseException,
                IllegalArgumentException {
 
         try {
             checkEnv();
             DatabaseUtil.checkForNullDbt(key"key"true);
             DatabaseUtil.checkForNullDbt(data"data"false);
            checkOpen("Can't call Database.get:");
            trace(."Database.get"txnkeynulllockMode);
            CursorConfig cursorConfig = .;
            if (lockMode == .) {
                cursorConfig = .;
                lockMode = null;
            }
            checkLockModeWithoutTxn(txnlockMode);
            Locker locker = null;
            Cursor cursor = null;
            OperationStatus commitStatus = null;
            try {
                locker = LockerFactory.getReadableLocker
                    (txnisTransactional(),
                     cursorConfig.getReadCommitted());
                cursor = new Cursor(thislockercursorConfig);
                cursor.setNonCloning(true);
                commitStatus =
                    cursor.search(keydatalockMode.);
                return commitStatus;
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
                if (locker != null) {
                    locker.operationEnd(commitStatus);
                }
            }
        } catch (Error E) {
            DbInternal.getEnvironmentImpl().invalidate(E);
            throw E;
        }
    }

    
Retrieves the key/data pair with the given key and data value, that is, both the key and data items must match.

Parameters:
txn For a transactional database, an explicit transaction may be specified to transaction-protect the operation, or null may be specified to perform the operation without transaction protection. For a non-transactional database, null must be specified.
key the key used as input. It must be initialized with a non-null byte array by the caller.
data the data used as input. It must be initialized with a non-null byte array by the caller.
lockMode the locking attributes; if null, default attributes are used.
Returns:
OperationStatus.NOTFOUND if no matching key/data pair is found; otherwise, OperationStatus.SUCCESS.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
java.lang.IllegalArgumentException if an invalid parameter is specified.
    public OperationStatus getSearchBoth(final Transaction txn,
                                         final DatabaseEntry key,
                                         final DatabaseEntry data,
                                         LockMode lockMode)
        throws LockConflictException,
               DatabaseException,
               IllegalArgumentException {
        try {
            checkEnv();
            DatabaseUtil.checkForNullDbt(key"key"true);
            DatabaseUtil.checkForNullDbt(data"data"true);
            checkOpen("Can't call Database.getSearchBoth:");
            trace(."Database.getSearchBoth"txnkeydata,
                  lockMode);
            CursorConfig cursorConfig = .;
            if (lockMode == .) {
                cursorConfig = .;
                lockMode = null;
            }
            checkLockModeWithoutTxn(txnlockMode);
            Locker locker = null;
            Cursor cursor = null;
            OperationStatus commitStatus = null;
            try {
                locker = LockerFactory.getReadableLocker
                    (txnisTransactional(),
                     cursorConfig.getReadCommitted());
                cursor = new Cursor(thislockercursorConfig);
                cursor.setNonCloning(true);
                commitStatus =
                    cursor.search(keydatalockMode.);
                return commitStatus;
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
                if (locker != null) {
                    locker.operationEnd(commitStatus);
                }
            }
        } catch (Error E) {
            DbInternal.getEnvironmentImpl().invalidate(E);
            throw E;
        }
    }

    
Stores the key/data pair into the database.

If the key already appears in the database and duplicates are not configured, the data associated with the key will be replaced. If the key already appears in the database and sorted duplicates are configured, the new data value is inserted at the correct sorted location.

Parameters:
txn For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
key the key DatabaseEntry operated on.
data the data DatabaseEntry stored.
Returns:
OperationStatus.SUCCESS if the operation succeeds.
Throws:
OperationFailureException if one of the Write Operation Failures occurs.
OperationFailureException if this exception occurred earlier and caused the transaction to be invalidated.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.UnsupportedOperationException if this database is read-only.
java.lang.IllegalStateException if the database has been closed.
    public OperationStatus put(final Transaction txn,
                               final DatabaseEntry key,
                               final DatabaseEntry data)
        throws DatabaseException {
        checkEnv();
        DatabaseUtil.checkForNullDbt(key"key"true);
        DatabaseUtil.checkForNullDbt(data"data"true);
        DatabaseUtil.checkForPartialKey(key);
        checkOpen("Can't call Database.put");
        checkWritable("put");
        trace(."Database.put"txnkeydatanull);
        return putInternal(txnkeydata.);
    }

    
Stores the key/data pair into the database if the key does not already appear in the database.

This method will return OperationStatus.KEYEXIST if the key already exists in the database, even if the database supports duplicates.

Parameters:
txn For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
key the key DatabaseEntry operated on.
data the data DatabaseEntry stored.
Returns:
OperationStatus.KEYEXIST if the key already appears in the database, else OperationStatus.SUCCESS
Throws:
OperationFailureException if one of the Write Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.UnsupportedOperationException if this database is read-only.
java.lang.IllegalStateException if the database has been closed.
    public OperationStatus putNoOverwrite(final Transaction txn,
                                          final DatabaseEntry key,
                                          final DatabaseEntry data)
        throws DatabaseException {
        checkEnv();
        DatabaseUtil.checkForNullDbt(key"key"true);
        DatabaseUtil.checkForNullDbt(data"data"true);
        DatabaseUtil.checkForPartialKey(key);
        checkOpen("Can't call Database.putNoOverWrite");
        checkWritable("putNoOverwrite");
        trace(."Database.putNoOverwrite"txnkeydatanull);
        return putInternal(txnkeydata.);
    }

    
Stores the key/data pair into the database if it does not already appear in the database.

This method may only be called if the underlying database has been configured to support sorted duplicates.

Parameters:
txn For a transactional database, an explicit transaction may be specified, or null may be specified to use auto-commit. For a non-transactional database, null must be specified.
key the key DatabaseEntry operated on.
data the data DatabaseEntry stored.
Returns:
OperationStatus.KEYEXIST if the key/data pair already appears in the database, else OperationStatus.SUCCESS
Throws:
OperationFailureException if one of the Write Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.UnsupportedOperationException if this database is not configured for duplicates, or this database is read-only.
java.lang.IllegalStateException if the database has been closed.
    public OperationStatus putNoDupData(final Transaction txn,
                                        final DatabaseEntry key,
                                        final DatabaseEntry data)
        throws DatabaseException {
        checkEnv();
        DatabaseUtil.checkForNullDbt(key"key"true);
        DatabaseUtil.checkForNullDbt(data"data"true);
        DatabaseUtil.checkForPartialKey(key);
        checkOpen("Can't call Database.putNoDupData");
        if (!.getSortedDuplicates()) {
            throw new UnsupportedOperationException
                ("Database is not configured for duplicate data.");
        }
        checkWritable("putNoDupData");
        trace(."Database.putNoDupData"txnkeydatanull);
        return putInternal(txnkeydata.);
    }

    
Internal version of put() that does no parameter checking.
                                final DatabaseEntry key,
                                final DatabaseEntry data,
                                final PutMode putMode)
        throws DatabaseException {
        try {
            Locker locker = null;
            Cursor cursor = null;
            OperationStatus commitStatus = .;
            try {
                locker = LockerFactory.getWritableLocker
                    (txn,
                     .isInternalDb(),
                     isTransactional(),
                     .isReplicated()); // autoTxnIsReplicated
                cursor = new Cursor(thislockernull);
                cursor.setNonCloning(true);
                commitStatus = cursor.putInternal(keydataputMode);
                return commitStatus;
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
                if (locker != null) {
                    locker.operationEnd(commitStatus);
                }
            }
        } catch (Error E) {
            DbInternal.getEnvironmentImpl().invalidate(E);
            throw E;
        }
    }

    
Creates a specialized join cursor for use in performing equality or natural joins on secondary indices.

Each cursor in the cursors array must have been initialized to refer to the key on which the underlying database should be joined. Typically, this initialization is done by calling Cursor.getSearchKey(com.sleepycat.je.DatabaseEntry,com.sleepycat.je.DatabaseEntry,com.sleepycat.je.LockMode).

Once the cursors have been passed to this method, they should not be accessed or modified until the newly created join cursor has been closed, or else inconsistent results may be returned. However, the position of the cursors will not be changed by this method or by the methods of the join cursor.

Parameters:
cursors an array of cursors associated with this primary database. In a replicated environment, an explicit transaction must be specified when opening each cursor, unless read-uncommitted isolation is isolation is specified via the CursorConfig or LockMode parameter.
config The join attributes. If null, default attributes are used.
Returns:
a specialized cursor that returns the results of the equality join operation.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
java.lang.IllegalArgumentException if an invalid parameter is specified, for example, an invalid JoinConfig parameter.
See also:
JoinCursor
    public JoinCursor join(final Cursor[] cursorsfinal JoinConfig config)
        throws DatabaseExceptionIllegalArgumentException {
        try {
            checkEnv();
            checkOpen("Can't call Database.join");
            DatabaseUtil.checkForNullParam(cursors"cursors");
            if (cursors.length == 0) {
                throw new IllegalArgumentException
                    ("At least one cursor is required.");
            }
            /*
             * Check that all cursors use the same locker, if any cursor is
             * transactional.  And if non-transactional, that all databases are
             * in the same environment.
             */
            Locker locker = cursors[0].getCursorImpl().getLocker();
            if (!locker.isTransactional()) {
                EnvironmentImpl env = .getEnvironmentImpl();
                for (int i = 1; i < cursors.lengthi += 1) {
                    Locker locker2 = cursors[i].getCursorImpl().getLocker();
                    if (locker2.isTransactional()) {
                        throw new IllegalArgumentException
                            ("All cursors must use the same transaction.");
                    }
                    EnvironmentImpl env2 = cursors[i].getDatabaseImpl()
                        .getDbEnvironment();
                    if (env != env2) {
                        throw new IllegalArgumentException
                            ("All cursors must use the same environment.");
                    }
                }
                locker = null/* Don't reuse a non-transactional locker. */
            } else {
                for (int i = 1; i < cursors.lengthi += 1) {
                    Locker locker2 = cursors[i].getCursorImpl().getLocker();
                    if (locker.getTxnLocker() != locker2.getTxnLocker()) {
                        throw new IllegalArgumentException
                            ("All cursors must use the same transaction.");
                    }
                }
            }
            /* Create the join cursor. */
            return new JoinCursor(lockerthiscursorsconfig);
        } catch (Error E) {
            DbInternal.getEnvironmentImpl().invalidate(E);
            throw E;
        }
    }

    
Preloads the cache. This method should only be called when there are no operations being performed on the database in other threads. Executing preload during concurrent updates may result in some or all of the tree being loaded into the JE cache. Executing preload during any other types of operations may result in JE exceeding its allocated cache size. preload() effectively locks the entire database and therefore will lock out the checkpointer, cleaner, and compressor, as well as not allow eviction to occur.

Deprecated:
As of JE 2.0.83, replaced by preload(com.sleepycat.je.PreloadConfig).
Parameters:
maxBytes The maximum number of bytes to load. If maxBytes is 0, je.evictor.maxMemory is used.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
    public void preload(final long maxBytes)
        throws DatabaseException {
        checkEnv();
        checkOpen("Can't call Database.preload");
        PreloadConfig config = new PreloadConfig();
        config.setMaxBytes(maxBytes);
        .preload(config);
    }

    
Preloads the cache. This method should only be called when there are no operations being performed on the database in other threads. Executing preload during concurrent updates may result in some or all of the tree being loaded into the JE cache. Executing preload during any other types of operations may result in JE exceeding its allocated cache size. preload() effectively locks the entire database and therefore will lock out the checkpointer, cleaner, and compressor, as well as not allow eviction to occur.

Deprecated:
As of JE 2.0.101, replaced by preload(com.sleepycat.je.PreloadConfig).
Parameters:
maxBytes The maximum number of bytes to load. If maxBytes is 0, je.evictor.maxMemory is used.
maxMillisecs The maximum time in milliseconds to use when preloading. Preloading stops once this limit has been reached. If maxMillisecs is 0, preloading can go on indefinitely or until maxBytes (if non-0) is reached.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
    public void preload(final long maxBytesfinal long maxMillisecs)
        throws DatabaseException {
        checkEnv();
        checkOpen("Can't call Database.preload");
        PreloadConfig config = new PreloadConfig();
        config.setMaxBytes(maxBytes);
        config.setMaxMillisecs(maxMillisecs);
        .preload(config);
    }

    
Preloads the cache. This method should only be called when there are no operations being performed on the database in other threads. Executing preload during concurrent updates may result in some or all of the tree being loaded into the JE cache. Executing preload during any other types of operations may result in JE exceeding its allocated cache size. preload() effectively locks the entire database and therefore will lock out the checkpointer, cleaner, and compressor, as well as not allow eviction to occur.

While this method preloads a single database, Environment.preload(com.sleepycat.je.Database[],com.sleepycat.je.PreloadConfig) lets you preload multiple databases.

Parameters:
config The PreloadConfig object that specifies the parameters of the preload.
Returns:
A PreloadStats object with various statistics about the preload() operation.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
java.lang.IllegalArgumentException if PreloadConfig.getMaxBytes is greater than size of the JE cache.
    public PreloadStats preload(final PreloadConfig config)
        throws DatabaseException {
        checkEnv();
        checkOpen("Can't call Database.preload");
        PreloadConfig useConfig =
            (config == null) ? new PreloadConfig() : config;
        return .preload(useConfig);
    }

    
Counts the key/data pairs in the database. This operation is faster than obtaining a count from a cursor based scan of the database, and will not perturb the current contents of the cache. However, the count is not guaranteed to be accurate if there are concurrent updates. Note that this method does scan a significant portion of the database and should be considered a fairly expensive operation.

A count of the key/data pairs in the database is returned without adding to the cache. The count may not be accurate in the face of concurrent update operations in the database.

Returns:
The count of key/data pairs in the database.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
    public long count()
        throws DatabaseException {
        checkEnv();
        checkOpen("Can't call Database.count");
        return .count();
    }

    
Returns database statistics.

If this method has not been configured to avoid expensive operations (using the StatsConfig.setFast method), it will access some of or all the pages in the database, incurring a severe performance penalty as well as possibly flushing the underlying cache.

In the presence of multiple threads or processes accessing an active database, the information returned by this method may be out-of-date.

Parameters:
config The statistics returned; if null, default statistics are returned.
Returns:
Database statistics.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
    public DatabaseStats getStats(final StatsConfig config)
        throws DatabaseException {
        checkEnv();
        checkOpen("Can't call Database.stat");
        StatsConfig useConfig =
            (config == null) ? . : config;
        if ( != null) {
            return .stat(useConfig);
        }
        return null;
    }

    
Verifies the integrity of the database.

Verification is an expensive operation that should normally only be used for troubleshooting and debugging.

Parameters:
config Configures the verify operation; if null, the default operation is performed.
Returns:
Database statistics.
Throws:
OperationFailureException if one of the Read Operation Failures occurs.
EnvironmentFailureException if an unexpected, internal or environment-wide failure occurs.
java.lang.IllegalStateException if the database has been closed.
java.lang.IllegalArgumentException if an invalid parameter is specified.
    public DatabaseStats verify(final VerifyConfig config)
        throws DatabaseException {
        try {
            checkEnv();
            checkOpen("Can't call Database.verify");
            VerifyConfig useConfig =
                (config == null) ? . : config;
            DatabaseStats stats = .getEmptyStats();
            .verify(useConfigstats);
            return stats;
        } catch (Error E) {
            DbInternal.getEnvironmentImpl().invalidate(E);
            throw E;
        }
    }

    
Returns the database name.

This method may be called at any time during the life of the application.

Returns:
The database name.
    public String getDatabaseName()
        throws DatabaseException {
        try {
            checkEnv();
            if ( != null) {
                return .getName();
            }
            return null;
        } catch (Error E) {
            DbInternal.getEnvironmentImpl().invalidate(E);
            throw E;
        }
    }
    /*
     * Non-transactional database name, safe to access when creating error
     * messages.
     */