mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Matthew Swift
05.14.2015 0bd57577bb85119b2b4495c5ef525ba189d8d17c
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/DatabaseContainer.java
@@ -28,17 +28,12 @@
import java.io.Closeable;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteSequence;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.backends.pluggable.spi.Cursor;
import org.opends.server.backends.pluggable.spi.ReadableStorage;
import org.opends.server.backends.pluggable.spi.Storage;
import org.opends.server.backends.pluggable.spi.StorageRuntimeException;
import org.opends.server.backends.pluggable.spi.TreeName;
import org.opends.server.backends.pluggable.spi.WriteableStorage;
import org.opends.server.util.ServerConstants;
import org.opends.server.util.StaticUtils;
/**
 * This class is a wrapper around the JE database object and provides basic
@@ -46,12 +41,11 @@
 */
abstract class DatabaseContainer implements Closeable
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  /** The database entryContainer. */
  final EntryContainer entryContainer;
  /** The name of the database within the entryContainer. */
  TreeName treeName;
  private TreeName name;
  /** The reference to the JE Storage. */
  final Storage storage;
@@ -67,7 +61,7 @@
  {
    this.storage = storage;
    this.entryContainer = entryContainer;
    this.treeName = treeName;
    this.name = treeName;
  }
  /**
@@ -81,11 +75,8 @@
   */
  void open(WriteableStorage txn) throws StorageRuntimeException
  {
    txn.openTree(treeName);
    if (logger.isTraceEnabled())
    {
      logger.trace("JE database %s opened. txn=%s", treeName, txn);
    }
    // FIXME: remove?
    txn.openTree(name);
  }
  /**
@@ -106,83 +97,8 @@
  @Override
  public synchronized void close() throws StorageRuntimeException
  {
    storage.closeTree(treeName);
    if(logger.isTraceEnabled())
    {
      logger.trace("Closed tree %s", treeName);
    }
  }
  void put(WriteableStorage txn, ByteSequence key, ByteSequence value) throws StorageRuntimeException
  {
    txn.create(treeName, key, value);
    if (logger.isTraceEnabled())
    {
      logger.trace(messageToLog(true, treeName, txn, key, value));
    }
  }
  ByteString read(ReadableStorage txn, ByteSequence key, boolean isRMW) throws StorageRuntimeException
  {
    ByteString value = isRMW ? txn.getRMW(treeName, key) : txn.read(treeName, key);
    if (logger.isTraceEnabled())
    {
      logger.trace(messageToLog(value != null, treeName, txn, key, value));
    }
    return value;
  }
  /**
   * Insert a record into a JE database, with optional debug logging. This is a
   * simple wrapper around the JE Database.putNoOverwrite method.
   * @param txn The JE transaction handle, or null if none.
   * @param key The record key.
   * @param value The record value.
   * @return {@code true} if the key-value mapping could be inserted,
   *         {@code false} if the key was already mapped to another value
   * @throws StorageRuntimeException If an error occurs in the JE operation.
   */
  boolean insert(WriteableStorage txn, ByteString key, ByteString value) throws StorageRuntimeException
  {
    boolean result = txn.putIfAbsent(treeName, key, value);
    if (logger.isTraceEnabled())
    {
      logger.trace(messageToLog(result, treeName, txn, key, value));
    }
    return result;
  }
  /**
   * Delete a record from a JE database, with optional debug logging. This is a
   * simple wrapper around the JE Database.delete method.
   * @param txn The JE transaction handle, or null if none.
   * @param key The key of the record to be read.
   * @return {@code true} if the key mapping was removed, {@code false} otherwise
   * @throws StorageRuntimeException If an error occurs in the JE operation.
   */
  boolean delete(WriteableStorage txn, ByteSequence key) throws StorageRuntimeException
  {
    final boolean result = txn.delete(treeName, key);
    if (logger.isTraceEnabled())
    {
      logger.trace(messageToLog(result, treeName, txn, key, null));
    }
    return result;
  }
  /**
   * Open a JE cursor on the JE database.  This is a simple wrapper around
   * the JE Database.openCursor method.
   * @param txn A JE database transaction to be used by the cursor,
   * or null if none.
   * @return A JE cursor.
   * @throws StorageRuntimeException If an error occurs while attempting to open
   * the cursor.
   */
  final Cursor openCursor(ReadableStorage txn) throws StorageRuntimeException
  {
    return txn.openCursor(treeName);
    // FIXME: is this method needed?
    storage.closeTree(name);
  }
  /**
@@ -194,17 +110,11 @@
   */
  long getRecordCount(ReadableStorage txn) throws StorageRuntimeException
  {
    long count = count(txn);
    if (logger.isTraceEnabled())
    {
      logger.trace(messageToLog(true, treeName, txn, null, null));
    }
    return count;
  }
  private long count(ReadableStorage txn)
  {
    final Cursor cursor = txn.openCursor(treeName);
    /*
     * FIXME: push down to storage. Some DBs have native support for this, e.g. using counted
     * B-Trees.
     */
    final Cursor cursor = txn.openCursor(name);
    try
    {
      long count = 0;
@@ -227,7 +137,7 @@
  @Override
  public String toString()
  {
    return treeName.toString();
    return name.toString();
  }
  /**
@@ -237,7 +147,7 @@
   */
  final TreeName getName()
  {
    return treeName;
    return name;
  }
  /**
@@ -247,40 +157,6 @@
   */
  final void setName(TreeName name)
  {
    this.treeName = name;
    this.name = name;
  }
  /** Returns the message to log given the provided information. */
  private String messageToLog(boolean success, TreeName treeName, ReadableStorage txn, ByteSequence key,
      ByteSequence value)
  {
    StringBuilder builder = new StringBuilder();
    builder.append(" (");
    builder.append(success ? "SUCCESS" : "ERROR");
    builder.append(")");
    builder.append(" db=");
    builder.append(treeName);
    builder.append(" txn=");
    builder.append(txn);
    builder.append(ServerConstants.EOL);
    if (key != null)
    {
      builder.append("key:");
      builder.append(ServerConstants.EOL);
      StaticUtils.byteArrayToHexPlusAscii(builder, key.toByteArray(), 4);
    }
    // If the operation was successful we log the same common information
    // plus the data
    if (value != null)
    {
      builder.append("value(len=");
      builder.append(value.length());
      builder.append("):");
      builder.append(ServerConstants.EOL);
      StaticUtils.byteArrayToHexPlusAscii(builder, value.toByteArray(), 4);
    }
    return builder.toString();
  }
}