From 83dd61651cb5d73c1a15dfcb7d217c0f272722d2 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Tue, 03 Oct 2006 19:09:36 +0000
Subject: [PATCH] Refactoring of the JEB backend to simplify the container and entryContainer abstraction. This also elimates exposing the JE interface to backendImpl by creating a new RootContainer class. It provides a higher-level interface to access raw data in JE from anywhere in the server (ie. unit tests).
---
opends/src/server/org/opends/server/backends/jeb/EntryContainer.java | 667 +++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 551 insertions(+), 116 deletions(-)
diff --git a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
index 050782e..13a1f4c 100644
--- a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
+++ b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -26,16 +26,7 @@
*/
package org.opends.server.backends.jeb;
-import com.sleepycat.je.Cursor;
-import com.sleepycat.je.Database;
-import com.sleepycat.je.DatabaseConfig;
-import com.sleepycat.je.DatabaseEntry;
-import com.sleepycat.je.DatabaseException;
-import com.sleepycat.je.DatabaseNotFoundException;
-import com.sleepycat.je.DeadlockException;
-import com.sleepycat.je.LockMode;
-import com.sleepycat.je.OperationStatus;
-import com.sleepycat.je.Transaction;
+import com.sleepycat.je.*;
import org.opends.server.api.AttributeSyntax;
import org.opends.server.api.Backend;
@@ -47,6 +38,7 @@
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.Operation;
import org.opends.server.core.SearchOperation;
+import org.opends.server.loggers.Debug;
import org.opends.server.protocols.asn1.ASN1OctetString;
import org.opends.server.protocols.ldap.LDAPException;
import org.opends.server.controls.PagedResultsControl;
@@ -55,6 +47,7 @@
import org.opends.server.types.AttributeValue;
import org.opends.server.types.CancelledOperationException;
import org.opends.server.types.Control;
+import org.opends.server.types.DebugLogCategory;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
@@ -77,6 +70,10 @@
import static org.opends.server.messages.MessageHandler.getMessage;
import static org.opends.server.messages.JebMessages.*;
import static org.opends.server.loggers.Debug.debugException;
+import static org.opends.server.types.DebugLogSeverity.VERBOSE;
+import static org.opends.server.types.DebugLogCategory.DATABASE_ACCESS;
+import static org.opends.server.types.DebugLogCategory.DATABASE_WRITE;
+import static org.opends.server.types.DebugLogCategory.DATABASE_READ;
import static org.opends.server.util.ServerConstants.OID_SUBTREE_DELETE_CONTROL;
import static org.opends.server.util.ServerConstants.OID_PAGED_RESULTS_CONTROL;
@@ -93,6 +90,16 @@
private static final String CLASS_NAME =
"org.opends.server.backends.jeb.EntryContainer";
+ /**
+ * The JE database environment.
+ */
+ private static Environment env;
+
+ /**
+ * The backend configuration.
+ */
+ private static Config config;
+
/**
* The name of the entry database.
*/
@@ -124,19 +131,26 @@
public static final String ATTR_DEBUG_SEARCH_INDEX = "debugsearchindex";
/**
- * The backend to which this entry container belongs.
+ * The backend to which this entry entryContainer belongs.
*/
private Backend backend;
/**
- * The database container.
+ * The baseDN this entry container is responsible for.
*/
- private Container container;
+ private DN baseDN;
/**
- * The backend configuration.
+ * A list of JE database handles opened through this entryContainer.
+ * They will be closed by the entryContainer.
*/
- private Config config;
+ private ArrayList<Database> databases;
+
+ /**
+ * A list of JE cursor handles registered with this entryContainer.
+ * They will be closed by the entryContainer.
+ */
+ private ArrayList<Cursor> cursors;
/**
* The DN database maps a normalized DN string to an entry ID (8 bytes).
@@ -179,25 +193,34 @@
private HashMap<AttributeType, AttributeIndex> attrIndexMap;
/**
- * Create a new entry container object. This method does not actually create
- * anything in the JE database environment.
+ * Create a new entry entryContainer object.
+ *
+ * @param baseDN The baseDN this entry container will be responsible for
+ * storing on disk.
* @param backend A reference to the JE backend that is creating this entry
- * container. It is needed by the Directory Server entry cache methods.
+ * container. It is needed by the Directory Server entry cache
+ * methods.
* @param config The configuration of the JE backend.
- * @param container The databases reside in this container.
+ * @param env The JE environment to create this entryContainer in
*/
- public EntryContainer(Backend backend, Config config, Container container)
+ public EntryContainer(DN baseDN, Backend backend, Config config,
+ Environment env)
{
this.backend = backend;
+ this.baseDN = baseDN;
this.config = config;
- this.container = container;
+ this.env = env;
+
+ // Instantiate database and cursor lists
+ databases = new ArrayList<Database>();
+ cursors = new ArrayList<Cursor>();
// Instantiate indexes for id2children and id2subtree.
- id2children = new Index(container, ID2CHILDREN_DATABASE_NAME,
+ id2children = new Index(this, ID2CHILDREN_DATABASE_NAME,
new ID2CIndexer(),
config.getBackendIndexEntryLimit(),
0);
- id2subtree = new Index(container, ID2SUBTREE_DATABASE_NAME,
+ id2subtree = new Index(this, ID2SUBTREE_DATABASE_NAME,
new ID2SIndexer(),
config.getBackendIndexEntryLimit(),
0);
@@ -208,7 +231,7 @@
{
for (IndexConfig indexConfig : config.getIndexConfigMap().values())
{
- AttributeIndex index = new AttributeIndex(indexConfig, container);
+ AttributeIndex index = new AttributeIndex(this, indexConfig);
attrIndexMap.put(indexConfig.getAttributeType(), index);
}
}
@@ -218,7 +241,7 @@
}
/**
- * Opens the container for reading and writing.
+ * Opens the entryContainer for reading and writing.
*
* @throws DatabaseException If an error occurs in the JE database.
*/
@@ -229,10 +252,10 @@
DatabaseConfig dbNodupsConfig = new DatabaseConfig();
dbNodupsConfig.setAllowCreate(true);
dbNodupsConfig.setTransactional(true);
- container.open();
+
try
{
- id2entry = new ID2Entry(container, dbNodupsConfig, entryDataConfig,
+ id2entry = new ID2Entry(this, dbNodupsConfig, entryDataConfig,
ID2ENTRY_DATABASE_NAME);
id2entry.open();
@@ -242,7 +265,7 @@
dn2idConfig.setAllowCreate(true);
dn2idConfig.setTransactional(true);
dn2idConfig.setBtreeComparator(dn2idComparator.getClass());
- dn2id = new DN2ID(container, dn2idConfig, DN2ID_DATABASE_NAME);
+ dn2id = new DN2ID(this, dn2idConfig, DN2ID_DATABASE_NAME);
dn2id.open();
id2children.open(dbNodupsConfig);
@@ -253,7 +276,7 @@
dn2uriConfig.setAllowCreate(true);
dn2uriConfig.setTransactional(true);
dn2uriConfig.setBtreeComparator(dn2idComparator.getClass());
- dn2uri = new DN2URI(container, dn2uriConfig, REFERRAL_DATABASE_NAME);
+ dn2uri = new DN2URI(this, dn2uriConfig, REFERRAL_DATABASE_NAME);
dn2uri.open();
for (AttributeIndex index : attrIndexMap.values())
@@ -264,16 +287,16 @@
catch (DatabaseException e)
{
assert debugException(CLASS_NAME, "open", e);
- container.close();
+ close();
throw e;
}
}
/**
- * Opens the container for reading and writing without transactions.
+ * Opens the entryContainer for reading and writing without transactions.
*
- * @param deferredWrite Indicates whether to open the container using the
- * deferred write mode.
+ * @param deferredWrite Indicates whether to open the entryContainer using
+ * the deferred write mode.
*
* @throws DatabaseException If an error occurs in the JE database.
*/
@@ -286,10 +309,9 @@
dbNodupsConfig.setTransactional(false);
dbNodupsConfig.setDeferredWrite(deferredWrite);
- container.open();
try
{
- id2entry = new ID2Entry(container, dbNodupsConfig, entryDataConfig,
+ id2entry = new ID2Entry(this, dbNodupsConfig, entryDataConfig,
ID2ENTRY_DATABASE_NAME);
id2entry.open();
@@ -300,7 +322,7 @@
dn2idConfig.setTransactional(false);
dn2idConfig.setBtreeComparator(dn2idComparator.getClass());
dn2idConfig.setDeferredWrite(deferredWrite);
- dn2id = new DN2ID(container, dn2idConfig, DN2ID_DATABASE_NAME);
+ dn2id = new DN2ID(this, dn2idConfig, DN2ID_DATABASE_NAME);
dn2id.open();
id2children.open(dbNodupsConfig);
@@ -312,7 +334,7 @@
dn2uriConfig.setTransactional(false);
dn2uriConfig.setBtreeComparator(dn2idComparator.getClass());
dn2uriConfig.setDeferredWrite(deferredWrite);
- dn2uri = new DN2URI(container, dn2uriConfig, REFERRAL_DATABASE_NAME);
+ dn2uri = new DN2URI(this, dn2uriConfig, REFERRAL_DATABASE_NAME);
dn2uri.open();
for (AttributeIndex index : attrIndexMap.values())
@@ -323,13 +345,13 @@
catch (DatabaseException e)
{
assert debugException(CLASS_NAME, "open", e);
- container.close();
+ close();
throw e;
}
}
/**
- * Opens the container for reading only.
+ * Opens the entryContainer for reading only.
*
* @throws DatabaseException If an error occurs in the JE database.
*/
@@ -342,10 +364,9 @@
dbNodupsConfig.setAllowCreate(false);
dbNodupsConfig.setTransactional(false);
- container.open();
try
{
- id2entry = new ID2Entry(container, dbNodupsConfig, entryDataConfig,
+ id2entry = new ID2Entry(this, dbNodupsConfig, entryDataConfig,
ID2ENTRY_DATABASE_NAME);
id2entry.open();
@@ -356,7 +377,7 @@
dn2idConfig.setAllowCreate(false);
dn2idConfig.setTransactional(false);
dn2idConfig.setBtreeComparator(dn2idComparator.getClass());
- dn2id = new DN2ID(container, dn2idConfig, DN2ID_DATABASE_NAME);
+ dn2id = new DN2ID(this, dn2idConfig, DN2ID_DATABASE_NAME);
dn2id.open();
id2children.open(dbNodupsConfig);
@@ -368,7 +389,7 @@
dn2uriConfig.setAllowCreate(false);
dn2uriConfig.setTransactional(false);
dn2uriConfig.setBtreeComparator(dn2idComparator.getClass());
- dn2uri = new DN2URI(container, dn2uriConfig, REFERRAL_DATABASE_NAME);
+ dn2uri = new DN2URI(this, dn2uriConfig, REFERRAL_DATABASE_NAME);
dn2uri.open();
for (AttributeIndex index : attrIndexMap.values())
@@ -379,21 +400,36 @@
catch (DatabaseException e)
{
assert debugException(CLASS_NAME, "openReadOnly", e);
- container.close();
+ close();
throw e;
}
}
/**
- * Closes the entry container.
+ * Closes the entry entryContainer.
*
* @throws DatabaseException If an error occurs in the JE database.
*/
public void close()
throws DatabaseException
{
- // The database container is responsible for closing the JE databases.
- container.close();
+ // Close each cursor that has been registered.
+ for (Cursor cursor : cursors)
+ {
+ cursor.close();
+ }
+
+ // Close each database handle that has been opened.
+ for (Database database : databases)
+ {
+ if (database.getConfig().getDeferredWrite())
+ {
+ database.sync();
+ }
+
+ database.close();
+ }
+
for (AttributeIndex index : attrIndexMap.values())
{
index.close();
@@ -401,8 +437,8 @@
}
/**
- * Get the DN database used by this entry container. The container must
- * have been opened.
+ * Get the DN database used by this entry entryContainer. The entryContainer
+ * must have been opened.
*
* @return The DN database.
*/
@@ -412,8 +448,8 @@
}
/**
- * Get the entry database used by this entry container. The container must
- * have been opened.
+ * Get the entry database used by this entry entryContainer. The
+ * entryContainer must have been opened.
*
* @return The entry database.
*/
@@ -423,8 +459,8 @@
}
/**
- * Get the referral database used by this entry container. The container must
- * have been opened.
+ * Get the referral database used by this entry entryContainer. The
+ * entryContainer must have been opened.
*
* @return The referral database.
*/
@@ -434,8 +470,8 @@
}
/**
- * Get the children database used by this entry container.
- * The container must have been opened.
+ * Get the children database used by this entry entryContainer.
+ * The entryContainer must have been opened.
*
* @return The children database.
*/
@@ -445,8 +481,8 @@
}
/**
- * Get the subtree database used by this entry container.
- * The container must have been opened.
+ * Get the subtree database used by this entry entryContainer.
+ * The entryContainer must have been opened.
*
* @return The subtree database.
*/
@@ -467,8 +503,8 @@
}
/**
- * Determine the highest entryID in the container.
- * The container must already be open.
+ * Determine the highest entryID in the entryContainer.
+ * The entryContainer must already be open.
*
* @return The highest entry ID.
* @throws JebException If an error occurs in the JE backend.
@@ -499,7 +535,7 @@
}
/**
- * Processes the specified search in this container.
+ * Processes the specified search in this entryContainer.
* Matching entries should be provided back to the core server using the
* <CODE>SearchOperation.returnEntry</CODE> method.
*
@@ -1269,12 +1305,12 @@
operation.invokeOperation(txn);
// Commit the transaction.
- Container.transactionCommit(txn);
+ EntryContainer.transactionCommit(txn);
completed = true;
}
catch (DeadlockException deadlockException)
{
- Container.transactionAbort(txn);
+ EntryContainer.transactionAbort(txn);
if (retryRemaining-- <= 0)
{
throw deadlockException;
@@ -1284,22 +1320,22 @@
}
catch (DatabaseException databaseException)
{
- Container.transactionAbort(txn);
+ EntryContainer.transactionAbort(txn);
throw databaseException;
}
catch (DirectoryException directoryException)
{
- Container.transactionAbort(txn);
+ EntryContainer.transactionAbort(txn);
throw directoryException;
}
catch (JebException jebException)
{
- Container.transactionAbort(txn);
+ EntryContainer.transactionAbort(txn);
throw jebException;
}
catch (Exception e)
{
- Container.transactionAbort(txn);
+ EntryContainer.transactionAbort(txn);
int messageID = MSGID_JEB_UNCHECKED_EXCEPTION;
String message = getMessage(messageID);
@@ -1378,7 +1414,7 @@
*/
public Transaction beginTransaction() throws DatabaseException
{
- return container.beginTransaction();
+ return EntryContainer.beginTransaction();
}
/**
@@ -1827,7 +1863,7 @@
*/
public Transaction beginTransaction() throws DatabaseException
{
- return container.beginTransaction();
+ return EntryContainer.beginTransaction();
}
/**
@@ -2356,7 +2392,7 @@
*/
public Transaction beginTransaction() throws DatabaseException
{
- return container.beginTransaction();
+ return EntryContainer.beginTransaction();
}
/**
@@ -2718,7 +2754,7 @@
*/
public Transaction beginTransaction() throws DatabaseException
{
- return container.beginTransaction();
+ return EntryContainer.beginTransaction();
}
/**
@@ -3196,9 +3232,9 @@
}
/**
- * Get a count of the number of entries stored in this entry container.
+ * Get a count of the number of entries stored in this entry entryContainer.
*
- * @return The number of entries stored in this entry container.
+ * @return The number of entries stored in this entry entryContainer.
* @throws DatabaseException If an error occurs in the JE database.
*/
public long getEntryCount() throws DatabaseException
@@ -3207,7 +3243,8 @@
}
/**
- * Remove the entry container from disk. The container must not be open.
+ * Remove the entry entryContainer from disk. The entryContainer must not be
+ * open.
*
* @throws DatabaseException If an error occurs in the JE database.
*/
@@ -3215,7 +3252,7 @@
{
try
{
- container.removeDatabase(DN2ID_DATABASE_NAME);
+ removeDatabase(DN2ID_DATABASE_NAME);
}
catch (DatabaseNotFoundException e)
{
@@ -3223,7 +3260,7 @@
}
try
{
- container.removeDatabase(ID2ENTRY_DATABASE_NAME);
+ removeDatabase(ID2ENTRY_DATABASE_NAME);
}
catch (DatabaseNotFoundException e)
{
@@ -3231,7 +3268,7 @@
}
try
{
- container.removeDatabase(ID2CHILDREN_DATABASE_NAME);
+ removeDatabase(ID2CHILDREN_DATABASE_NAME);
}
catch (DatabaseNotFoundException e)
{
@@ -3239,7 +3276,7 @@
}
try
{
- container.removeDatabase(ID2SUBTREE_DATABASE_NAME);
+ removeDatabase(ID2SUBTREE_DATABASE_NAME);
}
catch (DatabaseNotFoundException e)
{
@@ -3260,7 +3297,7 @@
/**
* Get the number of values for which the entry limit has been exceeded
- * since the entry container was opened.
+ * since the entry entryContainer was opened.
* @return The number of values for which the entry limit has been exceeded.
*/
public int getEntryLimitExceededCount()
@@ -3276,53 +3313,18 @@
}
/**
- * Begin a leaf transaction.
- * @return A JE transaction handle.
- * @throws DatabaseException If an error occurs in the JE database.
- */
- protected Transaction beginTransaction()
- throws DatabaseException
- {
- return container.beginTransaction();
- }
-
- /**
- * Commit a transaction.
- * @param txn The JE transaction handle.
- * @throws DatabaseException If an error occurs in the JE database.
- */
- protected void transactionCommit(Transaction txn)
- throws DatabaseException
- {
- Container.transactionCommit(txn);
- }
-
- /**
- * Abort a transaction.
- * @param txn The JE transaction handle.
- * @throws DatabaseException If an error occurs in the JE database.
- */
- protected void transactionAbort(Transaction txn)
- throws DatabaseException
- {
- Container.transactionAbort(txn);
- }
-
- /**
- * Get a list of the databases opened by this container. There will be
+ * Get a list of the databases opened by this entryContainer. There will be
* only one handle in the list for each database, regardless of the number
* of handles open for a given database.
* @param dbList A list of JE database handles.
*/
public void listDatabases(List<Database> dbList)
{
- // The container has a list of all handles opened.
- List<Database> dbCompleteList = container.getDatabaseList();
// There may be more than one handle open for a given database
// so we eliminate duplicates here.
HashSet<String> set = new HashSet<String>();
- for (Database db : dbCompleteList)
+ for (Database db : databases)
{
try
{
@@ -3362,4 +3364,437 @@
return false;
}
-}
+ /**
+ * Constructs a full JE database name incorporating a entryContainer name.
+ *
+ * @param builder A string builder to which the full name will be appended.
+ * @param name The short database name.
+ */
+ private void buildDatabaseName(StringBuilder builder, String name)
+ {
+ builder.append(getContainerName());
+ builder.append('_');
+ builder.append(name);
+ }
+
+ /**
+ * Opens a JE database in this entryContainer. The resulting database handle
+ * must not be closed by the caller, as it will be closed by the
+ * entryContainer. If the provided database configuration is transactional,
+ * a transaction will be created and used to perform the open.
+ * <p>
+ * Note that a database can be opened multiple times and will result in
+ * multiple unique handles to the database. This is used for example to
+ * give each server thread its own database handle to eliminate contention
+ * that could occur on a single handle.
+ *
+ * @param dbConfig The JE database configuration to be used to open the
+ * database.
+ * @param name The short database name, to which the entryContainer name
+ * will be added.
+ * @return A new JE database handle.
+ * @throws DatabaseException If an error occurs while attempting to open the
+ * database.
+ */
+ public synchronized Database openDatabase(DatabaseConfig dbConfig,
+ String name)
+ throws DatabaseException
+ {
+ Database database;
+
+ StringBuilder builder = new StringBuilder();
+ buildDatabaseName(builder, name);
+ String fullName = builder.toString();
+
+ if (dbConfig.getTransactional())
+ {
+ // Open the database under a transaction.
+ Transaction txn = beginTransaction();
+ try
+ {
+ database = env.openDatabase(txn, fullName, dbConfig);
+ assert Debug.debugMessage(DATABASE_ACCESS, VERBOSE, CLASS_NAME,
+ "openDatabase",
+ "open db=" + database.getDatabaseName() +
+ " txnid=" + txn.getId());
+ transactionCommit(txn);
+ }
+ catch (DatabaseException e)
+ {
+ transactionAbort(txn);
+ throw e;
+ }
+ }
+ else
+ {
+ database = env.openDatabase(null, fullName, dbConfig);
+ assert Debug.debugMessage(DATABASE_ACCESS, VERBOSE, CLASS_NAME,
+ "openDatabase",
+ "open db=" + database.getDatabaseName() +
+ " txnid=none");
+ }
+
+ // Insert into the list of database handles.
+ databases.add(database);
+
+ return database;
+ }
+
+ /**
+ * Register a cursor with the entryContainer. The entryContainer will then
+ * take care of closing the cursor when the entryContainer is closed.
+ *
+ * @param cursor A cursor to one of the databases in the entryContainer.
+ */
+ public synchronized void addCursor(Cursor cursor)
+ {
+ cursors.add(cursor);
+ }
+
+ /**
+ * Begin a leaf transaction using the default configuration.
+ * Provides assertion debug logging.
+ * @return A JE transaction handle.
+ * @throws DatabaseException If an error occurs while attempting to begin
+ * a new transaction.
+ */
+ public static Transaction beginTransaction()
+ throws DatabaseException
+ {
+ Transaction parentTxn = null;
+ TransactionConfig txnConfig = null;
+ Transaction txn = env.beginTransaction(parentTxn, txnConfig);
+ assert Debug.debugMessage(DATABASE_ACCESS, VERBOSE, CLASS_NAME,
+ "beginTransaction", "begin txnid=" + txn.getId());
+ return txn;
+ }
+
+ /**
+ * Commit a transaction.
+ * Provides assertion debug logging.
+ * @param txn The JE transaction handle.
+ * @throws DatabaseException If an error occurs while attempting to commit
+ * the transaction.
+ */
+ public static void transactionCommit(Transaction txn)
+ throws DatabaseException
+ {
+ if (txn != null)
+ {
+ txn.commit();
+ assert Debug.debugMessage(DATABASE_ACCESS, VERBOSE, CLASS_NAME,
+ "transactionCommit", "commit txnid=" +
+ txn.getId());
+ }
+ }
+
+ /**
+ * Abort a transaction.
+ * Provides assertion debug logging.
+ * @param txn The JE transaction handle.
+ * @throws DatabaseException If an error occurs while attempting to abort the
+ * transaction.
+ */
+ public static void transactionAbort(Transaction txn)
+ throws DatabaseException
+ {
+ if (txn != null)
+ {
+ txn.abort();
+ assert Debug.debugMessage(DATABASE_ACCESS, VERBOSE, CLASS_NAME,
+ "transactionAbort", "abort txnid=" +
+ txn.getId());
+ }
+ }
+
+ /**
+ * Debug log a read or write access to the database.
+ * @param operation The operation label: "read", "put", "insert".
+ * @param category The log category for raw data value logging
+ * @param status The JE return status code of the operation.
+ * @param database The JE database handle operated on.
+ * @param txn The JE transaction handle used in the operation.
+ * @param key The database key operated on.
+ * @param data The database value read or written.
+ * @return true so that the method can be used in an assertion
+ * @throws DatabaseException If an error occurs while retrieving information
+ * about the JE objects provided to the method.
+ */
+ private static boolean debugAccess(String operation,
+ DebugLogCategory category,
+ OperationStatus status,
+ Database database,
+ Transaction txn,
+ DatabaseEntry key, DatabaseEntry data)
+ throws DatabaseException
+ {
+ // Build the string that is common to category DATABASE_ACCESS and
+ // DATABASE_READ/DATABASE_WRITE
+ StringBuilder builder = new StringBuilder();
+ builder.append(operation);
+ if (status == OperationStatus.SUCCESS)
+ {
+ builder.append(" (ok)");
+ }
+ else
+ {
+ builder.append(" (");
+ builder.append(status.toString());
+ builder.append(")");
+ }
+ builder.append(" db=");
+ builder.append(database.getDatabaseName());
+ if (txn != null)
+ {
+ builder.append(" txnid=");
+ builder.append(txn.getId());
+ }
+ else
+ {
+ builder.append(" txnid=none");
+ }
+ Debug.debugMessage(DATABASE_ACCESS, VERBOSE, CLASS_NAME,
+ "debugAccess", builder.toString());
+
+ // If the operation was successful we log the same common information
+ // plus the key and data under category DATABASE_READ or DATABASE_WRITE
+ if (status == OperationStatus.SUCCESS)
+ {
+ builder.append(" key:");
+ builder.append(ServerConstants.EOL);
+ StaticUtils.byteArrayToHexPlusAscii(builder, key.getData(), 0);
+ if (data != null)
+ {
+ builder.append("data(len=");
+ builder.append(data.getSize());
+ builder.append("):");
+ builder.append(ServerConstants.EOL);
+ StaticUtils.byteArrayToHexPlusAscii(builder, data.getData(), 0);
+ }
+ Debug.debugMessage(category, VERBOSE, CLASS_NAME,
+ "debugAccess", builder.toString());
+/*
+ if (category == DATABASE_WRITE)
+ {
+ System.out.println(builder.toString());
+ }
+*/
+ }
+ return true;
+ }
+
+ /**
+ * Insert a record into a JE database, with optional debug logging. This is a
+ * simple wrapper around the JE Database.putNoOverwrite method.
+ * @param database The JE database handle.
+ * @param txn The JE transaction handle, or null if none.
+ * @param key The record key.
+ * @param data The record value.
+ * @return The operation status.
+ * @throws DatabaseException If an error occurs in the JE operation.
+ */
+ public static OperationStatus insert(Database database, Transaction txn,
+ DatabaseEntry key, DatabaseEntry data)
+ throws DatabaseException
+ {
+ OperationStatus status = database.putNoOverwrite(txn, key, data);
+ assert debugAccess("insert", DATABASE_WRITE,
+ status, database, txn, key, data);
+ return status;
+ }
+
+ /**
+ * Insert a record into a JE database through a cursor, with optional debug
+ * logging. This is a simple wrapper around the JE Cursor.putNoOverwrite
+ * method.
+ * @param cursor The JE cursor handle.
+ * @param key The record key.
+ * @param data The record value.
+ * @return The operation status.
+ * @throws DatabaseException If an error occurs in the JE operation.
+ */
+ public static OperationStatus cursorInsert(Cursor cursor,
+ DatabaseEntry key,
+ DatabaseEntry data)
+ throws DatabaseException
+ {
+ OperationStatus status = cursor.putNoOverwrite(key, data);
+ assert debugAccess("cursorInsert", DATABASE_WRITE,
+ status, cursor.getDatabase(), null, key, data);
+ return status;
+ }
+
+ /**
+ * Replace or insert a record into a JE database, with optional debug logging.
+ * This is a simple wrapper around the JE Database.put method.
+ * @param database The JE database handle.
+ * @param txn The JE transaction handle, or null if none.
+ * @param key The record key.
+ * @param data The record value.
+ * @return The operation status.
+ * @throws DatabaseException If an error occurs in the JE operation.
+ */
+ public static OperationStatus put(Database database, Transaction txn,
+ DatabaseEntry key, DatabaseEntry data)
+ throws DatabaseException
+ {
+ OperationStatus status = database.put(txn, key, data);
+ assert debugAccess("put", DATABASE_WRITE,
+ status, database, txn, key, data);
+ return status;
+ }
+
+ /**
+ * Replace or insert a record into a JE database through a cursor, with
+ * optional debug logging. This is a simple wrapper around the JE Cursor.put
+ * method.
+ * @param cursor The JE cursor handle.
+ * @param key The record key.
+ * @param data The record value.
+ * @return The operation status.
+ * @throws DatabaseException If an error occurs in the JE operation.
+ */
+ public static OperationStatus cursorPut(Cursor cursor,
+ DatabaseEntry key,
+ DatabaseEntry data)
+ throws DatabaseException
+ {
+ OperationStatus status = cursor.put(key, data);
+ assert debugAccess("cursorPut", DATABASE_WRITE,
+ status, cursor.getDatabase(), null, key, data);
+ return status;
+ }
+
+ /**
+ * Read a record from a JE database, with optional debug logging. This is a
+ * simple wrapper around the JE Database.get method.
+ * @param database The JE database handle.
+ * @param txn The JE transaction handle, or null if none.
+ * @param key The key of the record to be read.
+ * @param data The record value returned as output. Its byte array does not
+ * need to be initialized by the caller.
+ * @param lockMode The JE locking mode to be used for the read.
+ * @return The operation status.
+ * @throws DatabaseException If an error occurs in the JE operation.
+ */
+ public static OperationStatus read(Database database, Transaction txn,
+ DatabaseEntry key, DatabaseEntry data,
+ LockMode lockMode)
+ throws DatabaseException
+ {
+ OperationStatus status = database.get(txn, key, data, lockMode);
+ assert debugAccess("read", DATABASE_READ,
+ status, database, txn, key, data);
+ return status;
+ }
+
+ /**
+ * Read a record from a JE database through a cursor, with optional debug
+ * logging. This is a simple wrapper around the JE Cursor.getSearchKey method.
+ * @param cursor The JE cursor handle.
+ * @param key The key of the record to be read.
+ * @param data The record value returned as output. Its byte array does not
+ * need to be initialized by the caller.
+ * @param lockMode The JE locking mode to be used for the read.
+ * @return The operation status.
+ * @throws DatabaseException If an error occurs in the JE operation.
+ */
+ public static OperationStatus cursorRead(Cursor cursor,
+ DatabaseEntry key,
+ DatabaseEntry data,
+ LockMode lockMode)
+ throws DatabaseException
+ {
+ OperationStatus status = cursor.getSearchKey(key, data, lockMode);
+ assert debugAccess("cursorRead", DATABASE_READ,
+ status, cursor.getDatabase(), null, key, data);
+ return status;
+ }
+
+ /**
+ * Delete a record from a JE database, with optional debug logging. This is a
+ * simple wrapper around the JE Database.delete method.
+ * @param database The JE database handle.
+ * @param txn The JE transaction handle, or null if none.
+ * @param key The key of the record to be read.
+ * @return The operation status.
+ * @throws DatabaseException If an error occurs in the JE operation.
+ */
+ public static OperationStatus delete(Database database, Transaction txn,
+ DatabaseEntry key)
+ throws DatabaseException
+ {
+ OperationStatus status = database.delete(txn, key);
+ assert debugAccess("delete", DATABASE_WRITE,
+ status, database, txn, key, null);
+ return status;
+ }
+
+ /**
+ * Remove a database from disk.
+ *
+ * @param name The short database name, to which the entryContainer name will
+ * be added.
+ * @throws DatabaseException If an error occurs while attempting to delete the
+ * database.
+ */
+ public void removeDatabase(String name) throws DatabaseException
+ {
+ StringBuilder builder = new StringBuilder();
+ buildDatabaseName(builder, name);
+ String fullName = builder.toString();
+ env.removeDatabase(null, fullName);
+ }
+
+ /**
+ * Remove from disk all the databases in this entryContainer.
+ *
+ * @throws DatabaseException If an error occurs while attempting to delete any
+ * database.
+ */
+ private void removeAllDatabases() throws DatabaseException
+ {
+ for(Database database : databases)
+ {
+ String name = database.getDatabaseName();
+ env.removeDatabase(null, name);
+ }
+ }
+
+ /**
+ * This method constructs a container name from a base DN. Only alphanumeric
+ * characters are preserved, all other characters are replaced with an
+ * underscore.
+ *
+ * @return The container name for the base DN.
+ */
+ public String getContainerName()
+ {
+
+ String normStr = baseDN.toNormalizedString();
+ StringBuilder builder = new StringBuilder(normStr.length());
+ for (int i = 0; i < normStr.length(); i++)
+ {
+ char ch = normStr.charAt(i);
+ if (Character.isLetterOrDigit(ch))
+ {
+ builder.append(ch);
+ }
+ else
+ {
+ builder.append('_');
+ }
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Get the baseDN this entry container is responsible for.
+ *
+ * @return The Base DN for this entry container.
+ */
+ public DN getBaseDN()
+ {
+ return baseDN;
+ }
+}
\ No newline at end of file
--
Gitblit v1.10.0