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

Jean-Noel Rouvignac
14.31.2014 2f13f91c158747ca997a44d8e61830f46b77dd82
OPENDJ-1308 (CR-3156) Migrate schema support - ByteString - Indexer

Used ByteString everywhere with the JE Backend Indexer.
Changed all code up down and sideways to use ByteStrings too.


AttributeIndex.java:
Added BSKeyComparator to match the order defined by KeyComparator for backward compatibility.

Index.java:
Added byte string comparator field.

Indexer.java:
Pulled up comparator field + getComparator() here.
Added bsComparator field + getBSComparator() for ByteStrings.

VerifyJob.java:
In verifyAttribute(), reused the DatabaseEntry object.
15 files modified
642 ■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java 53 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java 31 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryIDSet.java 28 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/ID2CIndexer.java 41 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/ID2SIndexer.java 41 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/Index.java 96 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexBuffer.java 60 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/Indexer.java 46 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/JEExtensibleIndexer.java 50 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/NullIndex.java 11 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/PresenceIndexer.java 58 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java 30 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java 20 ●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java 37 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java 40 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
@@ -1313,6 +1313,59 @@
  }
  /**
   * Byte string key comparator. The default lexicographic byte string
   * comparator.
   * <p>
   * This is the byte string equivalent of {@link KeyComparator}.
   * <p>
   * Note: Matt reckons we could simply use ByteString.compareTo(),
   * but I am using this for now as an intermediate step.
   */
  public static class BSKeyComparator implements Comparator<ByteString>
  {
    /**
     * Compares its two arguments for order. Returns a negative integer, zero,
     * or a positive integer as the first argument is less than, equal to, or
     * greater than the second.
     *
     * @param a
     *          the first object to be compared.
     * @param b
     *          the second object to be compared.
     * @return a negative integer, zero, or a positive integer as the first
     *         argument is less than, equal to, or greater than the second.
     */
    @Override
    public int compare(ByteString a, ByteString b)
    {
      int i;
      for (i = 0; i < a.length() && i < b.length(); i++)
      {
        if (a.byteAt(i) > b.byteAt(i))
        {
          return 1;
        }
        else if (a.byteAt(i) < b.byteAt(i))
        {
          return -1;
        }
      }
      if (a.length() == b.length())
      {
        return 0;
      }
      if (a.length() > b.length())
      {
        return 1;
      }
      else
      {
        return -1;
      }
    }
  }
  /**
   * Retrieve the entry IDs that might match an approximate filter.
   *
   * @param approximateFilter The approximate filter.
opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -34,7 +34,9 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
import org.opends.server.admin.server.ConfigurationAddListener;
import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -46,12 +48,10 @@
import org.opends.server.api.ClientConnection;
import org.opends.server.api.EntryCache;
import org.opends.server.api.plugin.PluginResult;
import org.forgerock.opendj.config.server.ConfigException;
import org.opends.server.controls.*;
import org.opends.server.core.*;
import org.opends.server.protocols.ldap.LDAPResultCode;
import org.opends.server.types.*;
import org.forgerock.opendj.ldap.ResultCode;
import org.opends.server.util.ServerConstants;
import org.opends.server.util.StaticUtils;
@@ -2045,8 +2045,7 @@
    // Remove the id2c and id2s records for this entry.
    if(indexBuffer != null)
    {
      byte[] leafIDKeyBytes =
        JebFormat.entryIDToDatabase(leafID.longValue());
      ByteString leafIDKeyBytes = ByteString.valueOf(leafID.longValue());
      id2children.delete(indexBuffer, leafIDKeyBytes);
      id2subtree.delete(indexBuffer, leafIDKeyBytes);
    }
@@ -2073,8 +2072,7 @@
      if(indexBuffer != null)
      {
        byte[] parentIDBytes =
          JebFormat.entryIDToDatabase(parentID.longValue());
        ByteString parentIDBytes = ByteString.valueOf(parentID.longValue());
        // Remove from id2children.
        if (isParent)
        {
@@ -2636,15 +2634,12 @@
    // Add the new ID to id2children and id2subtree of new apex parent entry.
    if(isApexEntryMoved)
    {
      EntryID parentID;
      byte[] parentIDKeyBytes;
      boolean isParent = true;
      for (DN dn = getParentWithinBase(newEntry.getName()); dn != null;
           dn = getParentWithinBase(dn))
      {
        parentID = dn2id.get(txn, dn, LockMode.DEFAULT);
        parentIDKeyBytes =
            JebFormat.entryIDToDatabase(parentID.longValue());
        EntryID parentID = dn2id.get(txn, dn, LockMode.DEFAULT);
        ByteString parentIDKeyBytes = ByteString.valueOf(parentID.longValue());
        if(isParent)
        {
          id2children.insertID(buffer, parentIDKeyBytes, newID);
@@ -2685,14 +2680,11 @@
    // the old apex parent entry.
    if(oldSuperiorDN != null && isApexEntryMoved)
    {
      EntryID parentID;
      byte[] parentIDKeyBytes;
      boolean isParent = true;
      for (DN dn = oldSuperiorDN; dn != null; dn = getParentWithinBase(dn))
      {
        parentID = dn2id.get(txn, dn, LockMode.DEFAULT);
        parentIDKeyBytes =
          JebFormat.entryIDToDatabase(parentID.longValue());
        EntryID parentID = dn2id.get(txn, dn, LockMode.DEFAULT);
        ByteString parentIDKeyBytes = ByteString.valueOf(parentID.longValue());
        if(isParent)
        {
          id2children.removeID(buffer, parentIDKeyBytes, oldID);
@@ -2706,7 +2698,7 @@
    {
      // All the subordinates will be renumbered so we have to rebuild
      // id2c and id2s with the new ID.
      byte[] oldIDKeyBytes = JebFormat.entryIDToDatabase(oldID.longValue());
      ByteString oldIDKeyBytes = ByteString.valueOf(oldID.longValue());
      id2children.delete(buffer, oldIDKeyBytes);
      id2subtree.delete(buffer, oldIDKeyBytes);
@@ -2800,8 +2792,7 @@
      for (DN dn = oldSuperiorDN; dn != null; dn = getParentWithinBase(dn))
      {
        EntryID parentID = dn2id.get(txn, dn, LockMode.DEFAULT);
        byte[] parentIDKeyBytes =
          JebFormat.entryIDToDatabase(parentID.longValue());
        ByteString parentIDKeyBytes = ByteString.valueOf(parentID.longValue());
        id2subtree.removeID(buffer, parentIDKeyBytes, oldID);
      }
    }
@@ -2810,7 +2801,7 @@
    {
      // All the subordinates will be renumbered so we have to rebuild
      // id2c and id2s with the new ID.
      byte[] oldIDKeyBytes = JebFormat.entryIDToDatabase(oldID.longValue());
      ByteString oldIDKeyBytes = ByteString.valueOf(oldID.longValue());
      id2children.delete(buffer, oldIDKeyBytes);
      id2subtree.delete(buffer, oldIDKeyBytes);
opendj3-server-dev/src/server/org/opends/server/backends/jeb/EntryIDSet.java
@@ -22,12 +22,15 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 */
package org.opends.server.backends.jeb;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import org.forgerock.opendj.ldap.ByteString;
/**
 * Represents a set of Entry IDs.  It can represent a set where the IDs are
@@ -53,7 +56,7 @@
   * The database key containing this set, if the set was constructed
   * directly from the database.
   */
  private byte[] keyBytes = null;
  private ByteString keyBytes;
  /**
   * Create a new undefined set.
@@ -83,6 +86,19 @@
   */
  public EntryIDSet(byte[] keyBytes, byte[] bytes)
  {
    this(keyBytes != null ? ByteString.wrap(keyBytes) : null, bytes);
  }
  /**
   * Create a new entry ID set from the raw database value.
   *
   * @param keyBytes
   *          The database key that contains this value.
   * @param bytes
   *          The database value, or null if there are no entry IDs.
   */
  public EntryIDSet(ByteString keyBytes, byte[] bytes)
  {
    this.keyBytes = keyBytes;
    if (bytes == null)
@@ -189,11 +205,11 @@
    long[] n1 = new long[n.length];
    long last = -1;
    int j = 0;
    for (int i = 0; i < n.length; i++)
    for (long l : n)
    {
      if (n[i] != last)
      if (l != last)
      {
        last = n1[j++] = n[i];
        last = n1[j++] = l;
      }
    }
    if (j == n1.length)
@@ -229,6 +245,7 @@
   * Get a string representation of this object.
   * @return A string representation of this object.
   */
  @Override
  public String toString()
  {
    StringBuilder buffer = new StringBuilder(16);
@@ -679,6 +696,7 @@
   *
   * @return An EntryID iterator.
   */
  @Override
  public Iterator<EntryID> iterator()
  {
    if (values == null)
opendj3-server-dev/src/server/org/opends/server/backends/jeb/ID2CIndexer.java
@@ -22,28 +22,24 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 */
package org.opends.server.backends.jeb;
import java.util.*;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import com.sleepycat.je.DatabaseEntry;
import java.util.*;
/**
 * Implementation of an Indexer for the children index.
 */
public class ID2CIndexer extends Indexer
{
  /**
   * The comparator for keys generated by this class.
   */
  private static final Comparator<byte[]> comparator =
       new AttributeIndex.KeyComparator();
  /**
   * Create a new indexer for a children index.
   */
  public ID2CIndexer()
@@ -56,42 +52,33 @@
   * used to name an index created using this object.
   * @return A string representation of this object.
   */
  @Override
  public String toString()
  {
    return "id2children";
  }
  /**
   * Get the comparator that must be used to compare index keys
   * generated by this class.
   *
   * @return A byte array comparator.
   */
  public Comparator<byte[]> getComparator()
  {
    return comparator;
  }
  /**
   * Generate the set of index keys for an entry.
   *
   * @param entry The entry.
   * @param addKeys The set into which the generated keys will be inserted.
   */
  public void indexEntry(Entry entry, Set<byte[]> addKeys)
  @Override
  public void indexEntry(Entry entry, Set<ByteString> addKeys)
  {
    // The superior entry IDs are in the entry attachment.
    ArrayList ids = (ArrayList)entry.getAttachment();
    ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment();
    // Skip the entry's own ID.
    Iterator iter = ids.iterator();
    Iterator<EntryID> iter = ids.iterator();
    iter.next();
    // Get the parent ID.
    if (iter.hasNext())
    {
      DatabaseEntry nodeIDData = ((EntryID)iter.next()).getDatabaseEntry();
      addKeys.add(nodeIDData.getData());
      DatabaseEntry nodeIDData = iter.next().getDatabaseEntry();
      addKeys.add(ByteString.wrap(nodeIDData.getData()));
    }
  }
@@ -103,8 +90,9 @@
   * @param newEntry The new entry contents.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<byte[], Boolean> modifiedKeys)
                           Map<ByteString, Boolean> modifiedKeys)
  {
    // Nothing to do.
  }
@@ -120,9 +108,10 @@
   * @param mods The set of modifications that were applied to the entry.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<byte[], Boolean> modifiedKeys)
                          Map<ByteString, Boolean> modifiedKeys)
  {
    // Nothing to do.
  }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/ID2SIndexer.java
@@ -22,28 +22,24 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 */
package org.opends.server.backends.jeb;
import java.util.*;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import com.sleepycat.je.DatabaseEntry;
import java.util.*;
/**
 * Implementation of an Indexer for the subtree index.
 */
public class ID2SIndexer extends Indexer
{
  /**
   * The comparator for keys generated by this class.
   */
  private static final Comparator<byte[]> comparator =
       new AttributeIndex.KeyComparator();
  /**
   * Create a new indexer for a subtree index.
   */
  public ID2SIndexer()
@@ -55,42 +51,33 @@
   * used to name an index created using this object.
   * @return A string representation of this object.
   */
  @Override
  public String toString()
  {
    return "id2subtree";
  }
  /**
   * Get the comparator that must be used to compare index keys
   * generated by this class.
   *
   * @return A byte array comparator.
   */
  public Comparator<byte[]> getComparator()
  {
    return comparator;
  }
  /**
   * Generate the set of index keys for an entry.
   *
   * @param entry The entry.
   * @param addKeys The set into which the generated keys will be inserted.
   */
  public void indexEntry(Entry entry, Set<byte[]> addKeys)
  @Override
  public void indexEntry(Entry entry, Set<ByteString> addKeys)
  {
    // The superior entry IDs are in the entry attachment.
    ArrayList ids = (ArrayList)entry.getAttachment();
    ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment();
    // Skip the entry's own ID.
    Iterator iter = ids.iterator();
    Iterator<EntryID> iter = ids.iterator();
    iter.next();
    // Iterate through the superior IDs.
    while (iter.hasNext())
    {
      DatabaseEntry nodeIDData = ((EntryID)iter.next()).getDatabaseEntry();
      addKeys.add(nodeIDData.getData());
      DatabaseEntry nodeIDData = iter.next().getDatabaseEntry();
      addKeys.add(ByteString.wrap(nodeIDData.getData()));
    }
  }
@@ -102,8 +89,9 @@
   * @param newEntry The new entry contents.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<byte[], Boolean> modifiedKeys)
                           Map<ByteString, Boolean> modifiedKeys)
  {
    // Nothing to do.
  }
@@ -119,9 +107,10 @@
   * @param mods The set of modifications that were applied to the entry.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<byte[], Boolean> modifiedKeys)
                          Map<ByteString, Boolean> modifiedKeys)
  {
    // Nothing to do.
  }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/Index.java
@@ -29,6 +29,7 @@
import java.util.*;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.opends.server.backends.jeb.importLDIF.ImportIDSet;
import org.opends.server.types.DirectoryException;
@@ -61,6 +62,11 @@
  private final Comparator<byte[]> comparator;
  /**
   * The comparator for index keys.
   */
  private final Comparator<ByteString> bsComparator;
  /**
   * The limit on the number of entry IDs that may be indexed by one key.
   */
  private int indexEntryLimit;
@@ -106,8 +112,8 @@
   * A flag to indicate if a rebuild process is running on this index.
   * During the rebuild process, we assume that no entryIDSets are
   * accurate and return an undefined set on all read operations.
   * However all write opeations will succeed. The rebuildRunning
   * flag overrides all behaviours of the trusted flag.
   * However all write operations will succeed. The rebuildRunning
   * flag overrides all behaviors of the trusted flag.
   */
  private boolean rebuildRunning = false;
@@ -126,7 +132,7 @@
   * @param cursorEntryLimit The configured limit on the number of entry IDs
   * @param maintainCount Whether to maintain a count of IDs for a key once
   * the entry limit has exceeded.
   * @param env The JE Environemnt
   * @param env The JE Environment
   * @param entryContainer The database entryContainer holding this index.
   * @throws DatabaseException If an error occurs in the JE database.
   */
@@ -139,6 +145,7 @@
    super(name, env, entryContainer);
    this.indexer = indexer;
    this.comparator = indexer.getComparator();
    this.bsComparator = indexer.getBSComparator();
    this.indexEntryLimit = indexEntryLimit;
    this.cursorEntryLimit = cursorEntryLimit;
    this.maintainCount = maintainCount;
@@ -191,17 +198,17 @@
   *         count is exceeded. False if it already exists in the entry ID set
   *         for the given key.
   */
  public boolean insertID(IndexBuffer buffer, byte[] keyBytes,
  public boolean insertID(IndexBuffer buffer, ByteString keyBytes,
                          EntryID entryID)
  {
    TreeMap<byte[], IndexBuffer.BufferedIndexValues> bufferedOperations =
    TreeMap<ByteString, IndexBuffer.BufferedIndexValues> bufferedOperations =
        buffer.getBufferedIndex(this);
    IndexBuffer.BufferedIndexValues values = null;
    if(bufferedOperations == null)
    {
      bufferedOperations = new TreeMap<byte[],
          IndexBuffer.BufferedIndexValues>(comparator);
      bufferedOperations =
          new TreeMap<ByteString, IndexBuffer.BufferedIndexValues>(bsComparator);
      buffer.putBufferedIndex(this, bufferedOperations);
    }
    else
@@ -244,10 +251,8 @@
  public boolean insertID(Transaction txn, DatabaseEntry key, EntryID entryID)
       throws DatabaseException
  {
    OperationStatus status;
    DatabaseEntry entryIDData = entryID.getDatabaseEntry();
    DatabaseEntry data = new DatabaseEntry();
    boolean success = false;
    if(maintainCount)
    {
@@ -262,7 +267,7 @@
    }
    else
    {
      status = read(txn, key, data, LockMode.READ_COMMITTED);
      final OperationStatus status = read(txn, key, data, LockMode.READ_COMMITTED);
      if(status == OperationStatus.SUCCESS)
      {
        EntryIDSet entryIDList =
@@ -284,8 +289,7 @@
      {
        if(rebuildRunning || trusted)
        {
          status = insert(txn, key, entryIDData);
          if(status == OperationStatus.KEYEXIST)
          if (insert(txn, key, entryIDData) == OperationStatus.KEYEXIST)
          {
            for(int i = 1; i < phantomWriteRetires; i++)
            {
@@ -303,8 +307,7 @@
        }
      }
    }
    return success;
    return false;
  }
@@ -705,17 +708,17 @@
   *         count is exceeded. False if it already exists in the entry ID set
   *         for the given key.
   */
  public boolean removeID(IndexBuffer buffer, byte[] keyBytes,
  public boolean removeID(IndexBuffer buffer, ByteString keyBytes,
                          EntryID entryID)
  {
    TreeMap<byte[], IndexBuffer.BufferedIndexValues> bufferedOperations =
    TreeMap<ByteString, IndexBuffer.BufferedIndexValues> bufferedOperations =
        buffer.getBufferedIndex(this);
    IndexBuffer.BufferedIndexValues values = null;
    if(bufferedOperations == null)
    {
      bufferedOperations = new TreeMap<byte[],
          IndexBuffer.BufferedIndexValues>(comparator);
      bufferedOperations =
          new TreeMap<ByteString, IndexBuffer.BufferedIndexValues>(bsComparator);
      buffer.putBufferedIndex(this, bufferedOperations);
    }
    else
@@ -878,16 +881,16 @@
   * @param buffer The index buffer to use to store the deleted keys
   * @param keyBytes The index key bytes.
   */
  public void delete(IndexBuffer buffer, byte[] keyBytes)
  public void delete(IndexBuffer buffer, ByteString keyBytes)
  {
    TreeMap<byte[], IndexBuffer.BufferedIndexValues> bufferedOperations =
    TreeMap<ByteString, IndexBuffer.BufferedIndexValues> bufferedOperations =
        buffer.getBufferedIndex(this);
    IndexBuffer.BufferedIndexValues values = null;
    if(bufferedOperations == null)
    {
      bufferedOperations = new TreeMap<byte[],
          IndexBuffer.BufferedIndexValues>(comparator);
      bufferedOperations =
          new TreeMap<ByteString, IndexBuffer.BufferedIndexValues>(bsComparator);
      buffer.putBufferedIndex(this, bufferedOperations);
    }
    else
@@ -1182,19 +1185,17 @@
  public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  {
    HashSet<byte[]> addKeys = new HashSet<byte[]>();
    boolean success = true;
    HashSet<ByteString> addKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, addKeys);
    for (byte[] keyBytes : addKeys)
    boolean success = true;
    for (ByteString keyBytes : addKeys)
    {
      if(!insertID(buffer, keyBytes, entryID))
      {
        success = false;
      }
    }
    return success;
  }
@@ -1212,21 +1213,20 @@
  public boolean addEntry(Transaction txn, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  {
    TreeSet<byte[]> addKeys = new TreeSet<byte[]>(indexer.getComparator());
    boolean success = true;
    TreeSet<ByteString> addKeys =
        new TreeSet<ByteString>(indexer.getBSComparator());
    indexer.indexEntry(entry, addKeys);
    DatabaseEntry key = new DatabaseEntry();
    for (byte[] keyBytes : addKeys)
    boolean success = true;
    for (ByteString keyBytes : addKeys)
    {
      key.setData(keyBytes);
      key.setData(keyBytes.toByteArray());
      if(!insertID(txn, key, entryID))
      {
        success = false;
      }
    }
    return success;
  }
@@ -1242,11 +1242,10 @@
  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  {
    HashSet<byte[]> delKeys = new HashSet<byte[]>();
    HashSet<ByteString> delKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, delKeys);
    for (byte[] keyBytes : delKeys)
    for (ByteString keyBytes : delKeys)
    {
      removeID(buffer, keyBytes, entryID);
    }
@@ -1264,14 +1263,14 @@
  public void removeEntry(Transaction txn, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  {
    TreeSet<byte[]> delKeys = new TreeSet<byte[]>(indexer.getComparator());
    TreeSet<ByteString> delKeys =
        new TreeSet<ByteString>(indexer.getBSComparator());
    indexer.indexEntry(entry, delKeys);
    DatabaseEntry key = new DatabaseEntry();
    for (byte[] keyBytes : delKeys)
    for (ByteString keyBytes : delKeys)
    {
      key.setData(keyBytes);
      key.setData(keyBytes.toByteArray());
      removeID(txn, key, entryID);
    }
  }
@@ -1295,15 +1294,14 @@
                          List<Modification> mods)
       throws DatabaseException
  {
    TreeMap<byte[], Boolean> modifiedKeys =
        new TreeMap<byte[], Boolean>(indexer.getComparator());
    TreeMap<ByteString, Boolean> modifiedKeys =
        new TreeMap<ByteString, Boolean>(indexer.getBSComparator());
    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys);
    DatabaseEntry key = new DatabaseEntry();
    for (Map.Entry<byte[], Boolean> modifiedKey : modifiedKeys.entrySet())
    for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet())
    {
      key.setData(modifiedKey.getKey());
      key.setData(modifiedKey.getKey().toByteArray());
      if(modifiedKey.getValue())
      {
        insertID(txn, key, entryID);
@@ -1333,11 +1331,11 @@
                          List<Modification> mods)
      throws DatabaseException
  {
    TreeMap<byte[], Boolean> modifiedKeys =
      new TreeMap<byte[], Boolean>(indexer.getComparator());
    TreeMap<ByteString, Boolean> modifiedKeys =
        new TreeMap<ByteString, Boolean>(indexer.getBSComparator());
    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys);
    for (Map.Entry<byte[], Boolean> modifiedKey : modifiedKeys.entrySet())
    for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet())
    {
      if(modifiedKey.getValue())
      {
opendj3-server-dev/src/server/org/opends/server/backends/jeb/IndexBuffer.java
@@ -22,17 +22,19 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 */
package org.opends.server.backends.jeb;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.DatabaseEntry;
import java.util.*;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.types.DirectoryException;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.DatabaseException;
import com.sleepycat.je.Transaction;
/**
 * A buffered index is used to buffer multiple reads or writes to the
 * same index key into a single read or write.
@@ -48,8 +50,7 @@
   * The buffered records stored as a map from the record key to the
   * buffered value for that key for each index.
   */
  private LinkedHashMap<Index,
      TreeMap<byte[], BufferedIndexValues>> bufferedIndexes;
  private LinkedHashMap<Index, TreeMap<ByteString, BufferedIndexValues>> bufferedIndexes;
  /**
   * The buffered records stored as a set of buffered VLV values
@@ -60,7 +61,8 @@
  /**
   * A simple class representing a pair of added and deleted indexed IDs.
   */
  public static class BufferedIndexValues {
  static class BufferedIndexValues
  {
    EntryIDSet addedIDs;
    EntryIDSet deletedIDs;
  }
@@ -68,7 +70,8 @@
  /**
   * A simple class representing a pair of added and deleted VLV values.
   */
  public static class BufferedVLVValues {
  static class BufferedVLVValues
  {
    TreeSet<SortValues> addedValues;
    TreeSet<SortValues> deletedValues;
  }
@@ -82,7 +85,7 @@
  public IndexBuffer(EntryContainer entryContainer)
  {
    bufferedIndexes =
        new LinkedHashMap<Index, TreeMap<byte[], BufferedIndexValues>>();
        new LinkedHashMap<Index, TreeMap<ByteString, BufferedIndexValues>>();
    bufferedVLVIndexes = new LinkedHashMap<VLVIndex, BufferedVLVValues>();
    this.entryContainer = entryContainer;
  }
@@ -94,7 +97,7 @@
   * @return The buffered values or <code>null</code> if there are
   * no buffered values for the specified index.
   */
  public TreeMap<byte[], BufferedIndexValues> getBufferedIndex(Index index)
  public TreeMap<ByteString, BufferedIndexValues> getBufferedIndex(Index index)
  {
    return bufferedIndexes.get(index);
  }
@@ -105,8 +108,8 @@
   * @param index The index affected by the buffered values.
   * @param bufferedValues The buffered values for the index.
   */
  public void putBufferedIndex(Index index, TreeMap<byte[],
      BufferedIndexValues> bufferedValues)
  public void putBufferedIndex(Index index,
      TreeMap<ByteString, BufferedIndexValues> bufferedValues)
  {
    bufferedIndexes.put(index, bufferedValues);
  }
@@ -146,9 +149,6 @@
  public void flush(Transaction txn)
      throws DatabaseException, DirectoryException
  {
    TreeMap<byte[], BufferedIndexValues> bufferedValues;
    BufferedVLVValues bufferedVLVValues;
    byte[] keyBytes;
    DatabaseEntry key = new DatabaseEntry();
    for(AttributeIndex attributeIndex :
@@ -156,18 +156,18 @@
    {
      for(Index index : attributeIndex.getAllIndexes())
      {
        bufferedValues = bufferedIndexes.remove(index);
        TreeMap<ByteString, BufferedIndexValues> bufferedValues =
            bufferedIndexes.remove(index);
        if(bufferedValues != null)
        {
          Iterator<Map.Entry<byte[], BufferedIndexValues>> keyIterator =
          Iterator<Map.Entry<ByteString, BufferedIndexValues>> keyIterator =
              bufferedValues.entrySet().iterator();
          while(keyIterator.hasNext())
          {
            Map.Entry<byte[], BufferedIndexValues> bufferedKey =
            Map.Entry<ByteString, BufferedIndexValues> bufferedKey =
                keyIterator.next();
            keyBytes = bufferedKey.getKey();
            key.setData(keyBytes);
            key.setData(bufferedKey.getKey().toByteArray());
            index.updateKey(txn, key, bufferedKey.getValue().deletedIDs,
                bufferedKey.getValue().addedIDs);
@@ -180,8 +180,7 @@
    for(VLVIndex vlvIndex : entryContainer.getVLVIndexes())
    {
      bufferedVLVValues = bufferedVLVIndexes.remove(vlvIndex);
      BufferedVLVValues bufferedVLVValues = bufferedVLVIndexes.remove(vlvIndex);
      if(bufferedVLVValues != null)
      {
        vlvIndex.updateIndex(txn, bufferedVLVValues.addedValues,
@@ -190,18 +189,18 @@
    }
    Index id2children = entryContainer.getID2Children();
    bufferedValues = bufferedIndexes.remove(id2children);
    TreeMap<ByteString, BufferedIndexValues> bufferedValues =
        bufferedIndexes.remove(id2children);
    if(bufferedValues != null)
    {
      Iterator<Map.Entry<byte[], BufferedIndexValues>> keyIterator =
      Iterator<Map.Entry<ByteString, BufferedIndexValues>> keyIterator =
          bufferedValues.entrySet().iterator();
      while(keyIterator.hasNext())
      {
        Map.Entry<byte[], BufferedIndexValues> bufferedKey =
        Map.Entry<ByteString, BufferedIndexValues> bufferedKey =
            keyIterator.next();
        keyBytes = bufferedKey.getKey();
        key.setData(keyBytes);
        key.setData(bufferedKey.getKey().toByteArray());
        id2children.updateKey(txn, key, bufferedKey.getValue().deletedIDs,
            bufferedKey.getValue().addedIDs);
@@ -215,14 +214,13 @@
    if(bufferedValues != null)
    {
      Iterator<Map.Entry<byte[], BufferedIndexValues>> keyIterator =
      Iterator<Map.Entry<ByteString, BufferedIndexValues>> keyIterator =
          bufferedValues.entrySet().iterator();
      while(keyIterator.hasNext())
      {
        Map.Entry<byte[], BufferedIndexValues> bufferedKey =
        Map.Entry<ByteString, BufferedIndexValues> bufferedKey =
            keyIterator.next();
        keyBytes = bufferedKey.getKey();
        key.setData(keyBytes);
        key.setData(bufferedKey.getKey().toByteArray());
        id2subtree.updateKey(txn, key, bufferedKey.getValue().deletedIDs,
            bufferedKey.getValue().addedIDs);
opendj3-server-dev/src/server/org/opends/server/backends/jeb/Indexer.java
@@ -22,17 +22,20 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions copyright 2012 ForgeRock AS.
 *      Portions copyright 2012-2014 ForgeRock AS.
 */
package org.opends.server.backends.jeb;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import java.util.Comparator;
import java.util.Set;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.backends.jeb.AttributeIndex.BSKeyComparator;
import org.opends.server.backends.jeb.AttributeIndex.KeyComparator;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
/**
 * This class attempts to abstract the generation and comparison of keys
@@ -41,12 +44,32 @@
public abstract class Indexer
{
  /**
   * Get the comparator that must be used to compare index keys
   * generated by this class.
   * The comparator for keys generated by this class.
   */
  private static final KeyComparator comparator = new KeyComparator();
  private static final BSKeyComparator bsComparator = new BSKeyComparator();
  /**
   * Get the comparator that must be used to compare index keys generated by
   * this class.
   *
   * @return A byte array comparator.
   */
  public abstract Comparator<byte[]> getComparator();
  public final Comparator<byte[]> getComparator()
  {
    return comparator;
  }
  /**
   * Get the comparator that must be used to compare index keys generated by
   * this class.
   *
   * @return A byte string comparator.
   */
  public final Comparator<ByteString> getBSComparator()
  {
    return bsComparator;
  }
  /**
   * Generate the set of index keys for an entry.
@@ -54,7 +77,7 @@
   * @param entry The entry.
   * @param keys The set into which the generated keys will be inserted.
   */
  public abstract void indexEntry(Entry entry, Set<byte[]> keys);
  public abstract void indexEntry(Entry entry, Set<ByteString> keys);
  /**
   * Generate the set of index keys to be added and the set of index keys
@@ -65,7 +88,7 @@
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  public abstract void replaceEntry(Entry oldEntry, Entry newEntry,
                                    Map<byte[], Boolean> modifiedKeys);
                                    Map<ByteString, Boolean> modifiedKeys);
  /**
   * Generate the set of index keys to be added and the set of index keys
@@ -78,5 +101,6 @@
   */
  public abstract void modifyEntry(Entry oldEntry, Entry newEntry,
                                   List<Modification> mods,
                                   Map<byte[], Boolean> modifiedKeys);
                                   Map<ByteString, Boolean> modifiedKeys);
}
opendj3-server-dev/src/server/org/opends/server/backends/jeb/JEExtensibleIndexer.java
@@ -26,12 +26,10 @@
 */
package org.opends.server.backends.jeb;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
@@ -52,14 +50,6 @@
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  /**
   * The comparator for index keys generated by this class.
   */
  private static final Comparator<byte[]> comparator =
       new AttributeIndex.KeyComparator();
  /**
   * The attribute type for which this instance will
   * generate index keys.
   */
@@ -104,26 +94,11 @@
  }
  /**
   * Gets the comparator that must be used to compare index keys
   * generated by this class.
   *
   * @return A byte array comparator.
   */
  @Override
  public Comparator<byte[]> getComparator()
  {
    return comparator;
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public void indexEntry(Entry entry, Set<byte[]> keys)
  public void indexEntry(Entry entry, Set<ByteString> keys)
  {
    List<Attribute> attrList =
         entry.getAttribute(attributeType);
@@ -140,7 +115,7 @@
   */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<byte[], Boolean> modifiedKeys)
                           Map<ByteString, Boolean> modifiedKeys)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
@@ -158,7 +133,7 @@
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<byte[], Boolean> modifiedKeys)
                          Map<ByteString, Boolean> modifiedKeys)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
@@ -175,11 +150,10 @@
   * @param keys The set into which the generated keys will be inserted.
   */
  private void indexAttribute(List<Attribute> attrList,
                              Set<byte[]> keys)
                              Set<ByteString> keys)
  {
    if (attrList == null) return;
    Set<ByteString> keysBS = new TreeSet<ByteString>();
    for (Attribute attr : attrList)
    {
      if (!attr.isVirtual())
@@ -188,7 +162,7 @@
        {
          try
          {
            extensibleIndexer.createKeys(null, value.getValue(), null, keysBS);
            extensibleIndexer.createKeys(null, value.getValue(), null, keys);
          }
          catch (DecodeException e)
          {
@@ -197,10 +171,6 @@
        }
      }
    }
    for (ByteString key : keysBS)
    {
      keys.add(key.toByteArray());
    }
  }
@@ -214,12 +184,12 @@
   * be inserted or <code>false</code> otherwise.
   */
  private void indexAttribute(List<Attribute> attrList,
                              Map<byte[], Boolean> modifiedKeys,
                              Map<ByteString, Boolean> modifiedKeys,
                              Boolean insert)
  {
    if (attrList == null) return;
    final Set<byte[]> keys = new HashSet<byte[]>();
    final Set<ByteString> keys = new HashSet<ByteString>();
    indexAttribute(attrList, keys);
    computeModifiedKeys(modifiedKeys, insert, keys);
  }
@@ -238,10 +208,10 @@
   * @param keys
   *          The index keys to map.
   */
  private static void computeModifiedKeys(Map<byte[], Boolean> modifiedKeys,
      Boolean insert, final Set<byte[]> keys)
  private static void computeModifiedKeys(Map<ByteString, Boolean> modifiedKeys,
      Boolean insert, Set<ByteString> keys)
  {
    for (byte[] key : keys)
    for (ByteString key : keys)
    {
      Boolean cInsert = modifiedKeys.get(key);
      if (cInsert == null)
opendj3-server-dev/src/server/org/opends/server/backends/jeb/NullIndex.java
@@ -27,6 +27,7 @@
import java.util.List;
import java.util.Set;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.opends.server.backends.jeb.importLDIF.ImportIDSet;
import org.opends.server.types.DirectoryException;
@@ -53,7 +54,7 @@
   * @param state
   *          The state database to persist index state info.
   * @param env
   *          The JE Environemnt
   *          The JE Environment
   * @param entryContainer
   *          The database entryContainer holding this index.
   * @throws DatabaseException
@@ -69,7 +70,8 @@
  /** {@inheritDoc} */
  @Override
  public boolean insertID(IndexBuffer buffer, byte[] keyBytes, EntryID entryID)
  public boolean insertID(IndexBuffer buffer, ByteString keyBytes,
      EntryID entryID)
  {
    return true;
  }
@@ -129,7 +131,8 @@
  /** {@inheritDoc} */
  @Override
  public boolean removeID(IndexBuffer buffer, byte[] keyBytes, EntryID entryID)
  public boolean removeID(IndexBuffer buffer, ByteString keyBytes,
      EntryID entryID)
  {
    return true;
  }
@@ -158,7 +161,7 @@
  /** {@inheritDoc} */
  @Override
  public void delete(IndexBuffer buffer, byte[] keyBytes)
  public void delete(IndexBuffer buffer, ByteString keyBytes)
  {
    // Do nothing.
  }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/PresenceIndexer.java
@@ -22,18 +22,19 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2014 ForgeRock AS
 */
package org.opends.server.backends.jeb;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.types.AttributeType;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.Map;
/**
 * An implementation of an Indexer for attribute presence.
@@ -41,13 +42,6 @@
public class PresenceIndexer extends Indexer
{
  /**
   * The comparator for index keys generated by this class.
   */
  private static final Comparator<byte[]> comparator =
       new AttributeIndex.KeyComparator();
  /**
   * The attribute type for which this instance will
   * generate index keys.
@@ -68,31 +62,20 @@
   * Get a string representation of this object.
   * @return A string representation of this object.
   */
  @Override
  public String toString()
  {
    return attributeType.getNameOrOID() + ".presence";
  }
  /**
   * Get the comparator that must be used to compare index keys
   * generated by this class.
   *
   * @return A byte array comparator.
   */
  public Comparator<byte[]> getComparator()
  {
    return comparator;
  }
  /**
   * Generate the set of index keys for an entry.
   *
   * @param entry The entry.
   * @param keys The set into which the generated keys will be inserted.
   */
  public void indexEntry(Entry entry,  Set<byte[]> keys)
  @Override
  public void indexEntry(Entry entry, Set<ByteString> keys)
  {
    List<Attribute> attrList =
         entry.getAttribute(attributeType);
@@ -100,7 +83,7 @@
    {
      if (!attrList.isEmpty())
      {
        keys.add(AttributeIndex.presenceKey.getData());
        keys.add(getPresenceKeyData());
      }
    }
  }
@@ -115,8 +98,9 @@
   * @param newEntry The new entry contents.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<byte[], Boolean> modifiedKeys)
                           Map<ByteString, Boolean> modifiedKeys)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
@@ -124,14 +108,14 @@
    {
      if(newAttributes != null)
      {
        modifiedKeys.put(AttributeIndex.presenceKey.getData(), true);
        modifiedKeys.put(getPresenceKeyData(), true);
      }
    }
    else
    {
      if(newAttributes == null)
      {
        modifiedKeys.put(AttributeIndex.presenceKey.getData(), false);
        modifiedKeys.put(getPresenceKeyData(), false);
      }
    }
  }
@@ -147,9 +131,10 @@
   * @param mods The set of modifications that were applied to the entry.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<byte[], Boolean> modifiedKeys)
                          Map<ByteString, Boolean> modifiedKeys)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
@@ -157,15 +142,20 @@
    {
      if(newAttributes != null)
      {
        modifiedKeys.put(AttributeIndex.presenceKey.getData(), true);
        modifiedKeys.put(getPresenceKeyData(), true);
      }
    }
    else
    {
      if(newAttributes == null)
      {
        modifiedKeys.put(AttributeIndex.presenceKey.getData(), false);
        modifiedKeys.put(getPresenceKeyData(), false);
      }
    }
  }
  private ByteString getPresenceKeyData()
  {
    return ByteString.wrap(AttributeIndex.presenceKey.getData());
  }
}
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java
@@ -1116,7 +1116,7 @@
        if (entryIDList.isDefined())
        {
          final byte[] value = key.getData();
          final ByteString value = ByteString.wrap(key.getData());
          EntryID prevID = null;
          for (EntryID id : entryIDList)
@@ -1163,13 +1163,13 @@
            // require referenced external variables to be final.
            final AtomicBoolean foundMatchingKey = new AtomicBoolean(false);
            Set<byte[]> dummySet = new AbstractSet<byte[]>()
            Set<ByteString> dummySet = new AbstractSet<ByteString>()
            {
              @Override
              public Iterator<byte[]> iterator()
              public Iterator<ByteString> iterator()
              {
                // The set is always empty.
                return Collections.<byte[]>emptySet().iterator();
                return Collections.<ByteString> emptySet().iterator();
              }
              @Override
@@ -1180,9 +1180,10 @@
              }
              @Override
              public boolean add(byte[] e)
              public boolean add(ByteString e)
              {
                if (Arrays.equals(e, value)) {
                if (value.equals(e))
                {
                  // We could terminate processing at this point by throwing an
                  // UnsupportedOperationException, but this optimization is
                  // already ugly enough.
@@ -1203,7 +1204,7 @@
                logger.trace("Reference to entry "
                    + "<%s> which does not match the value%n%s",
                    entry.getName(),
                    keyDump(index, value));
                    keyDump(index, value.toByteArray()));
              }
            }
          }
@@ -1626,6 +1627,7 @@
      verifyAttributeInIndex(presenceIndex, txn, presenceKey, entryID);
    }
    final DatabaseEntry key = new DatabaseEntry();
    for (Attribute attr : attrList)
    {
      final AttributeType attrType = attr.getAttributeType();
@@ -1637,17 +1639,13 @@
        if (equalityIndex != null)
        {
          // TODO JNR reuse DatabaseEntry object for all indexes?
          DatabaseEntry key = new DatabaseEntry(normalizedBytes);
          key.setData(normalizedBytes);
          verifyAttributeInIndex(equalityIndex, txn, key, entryID);
        }
        if (substringIndex != null)
        {
          Set<ByteString> keyBytesSet =
              attrIndex.substringKeys(normalizedBytes);
          DatabaseEntry key = new DatabaseEntry();
          for (ByteString keyBytes : keyBytesSet)
          for (ByteString keyBytes : attrIndex.substringKeys(normalizedBytes))
          {
            key.setData(keyBytes.toByteArray());
            verifyAttributeInIndex(substringIndex, txn, key, entryID);
@@ -1656,15 +1654,13 @@
        if (orderingIndex != null)
        {
          normalizedBytes = normalize(attrType.getOrderingMatchingRule(), bsValue);
          DatabaseEntry key = new DatabaseEntry(normalizedBytes);
          key.setData(normalize(attrType.getOrderingMatchingRule(), bsValue));
          verifyAttributeInIndex(orderingIndex, txn, key, entryID);
        }
        if (approximateIndex != null)
        {
          normalizedBytes = normalize(attrType.getApproximateMatchingRule(), bsValue);
          DatabaseEntry key = new DatabaseEntry(normalizedBytes);
          key.setData(normalize(attrType.getApproximateMatchingRule(), bsValue));
          verifyAttributeInIndex(approximateIndex, txn, key, entryID);
        }
      }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java
@@ -36,6 +36,7 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.util.Utils;
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn;
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType;
@@ -48,7 +49,6 @@
import org.opends.server.core.DirectoryServer;
import org.opends.server.extensions.DiskSpaceMonitor;
import org.opends.server.types.*;
import org.forgerock.opendj.ldap.ResultCode;
import org.opends.server.util.LDIFReader;
import org.opends.server.util.Platform;
import org.opends.server.util.StaticUtils;
@@ -1431,8 +1431,8 @@
   */
  private class AppendReplaceTask extends ImportTask
  {
    private final Set<byte[]> insertKeySet = new HashSet<byte[]>(),
        deleteKeySet = new HashSet<byte[]>();
    private final Set<ByteString> insertKeySet = new HashSet<ByteString>();
    private final Set<ByteString> deleteKeySet = new HashSet<ByteString>();
    private final EntryInformation entryInfo = new EntryInformation();
    private Entry oldEntry;
    private EntryID entryID;
@@ -1536,16 +1536,16 @@
      {
        deleteKeySet.clear();
        index.indexer.indexEntry(oldEntry, deleteKeySet);
        for (byte[] delKey : deleteKeySet)
        for (ByteString delKey : deleteKeySet)
        {
          processKey(index, delKey, entryID, indexComparator, indexKey, false);
          processKey(index, delKey.toByteArray(), entryID, indexComparator, indexKey, false);
        }
      }
      insertKeySet.clear();
      index.indexer.indexEntry(entry, insertKeySet);
      for (byte[] key : insertKeySet)
      for (ByteString key : insertKeySet)
      {
        processKey(index, key, entryID, indexComparator, indexKey, true);
        processKey(index, key.toByteArray(), entryID, indexComparator, indexKey, true);
      }
    }
  }
@@ -1558,7 +1558,7 @@
  {
    private final Map<IndexKey, IndexOutputBuffer> indexBufferMap =
        new HashMap<IndexKey, IndexOutputBuffer>();
    private final Set<byte[]> insertKeySet = new HashSet<byte[]>();
    private final Set<ByteString> insertKeySet = new HashSet<ByteString>();
    private final EntryInformation entryInfo = new EntryInformation();
    private DatabaseEntry keyEntry = new DatabaseEntry(),
        valEntry = new DatabaseEntry();
@@ -1745,9 +1745,9 @@
    {
      insertKeySet.clear();
      index.indexer.indexEntry(entry, insertKeySet);
      for (byte[] key : insertKeySet)
      for (ByteString key : insertKeySet)
      {
        processKey(index, key, entryID, indexComparator, indexKey, true);
        processKey(index, key.toByteArray(), entryID, indexComparator, indexKey, true);
      }
    }
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -28,6 +28,7 @@
import java.util.*;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
import org.forgerock.opendj.ldap.ResultCode;
@@ -47,6 +48,12 @@
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.types.*;
import org.opends.server.types.Attribute;
import org.opends.server.types.Attributes;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
import org.opends.server.types.RDN;
import org.opends.server.util.Base64;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@@ -887,13 +894,13 @@
  private void assertIndexContainsID(Indexer indexer, Entry entry, Index index,
      EntryID entryID)
  {
    Set<byte[]> addKeys = new HashSet<byte[]>();
    Set<ByteString> addKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, addKeys);
    DatabaseEntry key = new DatabaseEntry();
    for (byte[] keyBytes : addKeys)
    for (ByteString keyBytes : addKeys)
    {
      key.setData(keyBytes);
      key.setData(keyBytes.toByteArray());
      assertEquals(index.containsID(null, key, entryID), TRUE);
    }
  }
@@ -901,21 +908,22 @@
  private void assertIndexContainsID(Indexer indexer, Entry entry,
      Index index, EntryID entryID, ConditionResult expected)
  {
    Set<byte[]> addKeys = new HashSet<byte[]>();
    Set<ByteString> addKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, addKeys);
    assertIndexContainsID(addKeys, index, entryID, expected);
  }
  private void assertIndexContainsID(Set<byte[]> addKeys, Index index,
  private void assertIndexContainsID(Set<ByteString> addKeys, Index index,
      EntryID entryID, ConditionResult expected)
  {
    DatabaseEntry key = new DatabaseEntry();
    for (byte[] keyBytes : addKeys) {
      key.setData(keyBytes);
    }
    for (ByteString keyBytes : addKeys)
    {
      key.setData(keyBytes.toByteArray());
    assertEquals(index.containsID(null, key, entryID), expected);
  }
  }
  @Test(dependsOnMethods = {"testSearchNotIndexed", "testAdd",
      "testSearchIndex", "testSearchScope", "testMatchedDN",
@@ -987,7 +995,7 @@
    AttributeType attribute;
    AttributeIndex titleIndex;
    AttributeIndex nameIndex;
    Set<byte[]> addKeys;
    Set<ByteString> addKeys;
    Indexer presenceIndexer;
    Indexer equalityIndexer;
    Indexer substringIndexer;
@@ -1039,15 +1047,14 @@
      attribute = DirectoryServer.getAttributeType("name");
      nameIndex = ec.getAttributeIndex(attribute);
      // This current entry in the DB shouldn't be in the presence
      // titleIndex.
      addKeys = new HashSet<byte[]>();
      addKeys.add(AttributeIndex.presenceKey.getData());
      // This current entry in the DB shouldn't be in the presence titleIndex.
      addKeys = new HashSet<ByteString>();
      addKeys.add(ByteString.wrap(AttributeIndex.presenceKey.getData()));
      assertIndexContainsID(addKeys, titleIndex.presenceIndex, entryID, FALSE);
      // This current entry should be in the presence nameIndex.
      addKeys = new HashSet<byte[]>();
      addKeys.add(AttributeIndex.presenceKey.getData());
      addKeys = new HashSet<ByteString>();
      addKeys.add(ByteString.wrap(AttributeIndex.presenceKey.getData()));
      assertIndexContainsID(addKeys, nameIndex.presenceIndex, entryID, TRUE);
      List<Control> noControls = new ArrayList<Control>(0);
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
@@ -26,26 +26,27 @@
 */
package org.opends.server.backends.jeb;
import org.opends.server.core.DirectoryServer;
import org.opends.server.TestCaseUtils;
import org.opends.server.types.*;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.util.StaticUtils;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import static org.opends.server.util.ServerConstants.OC_TOP;
import static org.opends.server.util.ServerConstants.OC_EXTENSIBLE_OBJECT;
import org.testng.annotations.BeforeClass;
import org.forgerock.opendj.ldap.ByteString;
import org.opends.server.TestCaseUtils;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.*;
import org.opends.server.util.StaticUtils;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.LockMode;
import com.sleepycat.je.OperationStatus;
import com.sleepycat.je.Transaction;
import com.sleepycat.je.LockMode;
import java.util.*;
import static org.opends.server.util.ServerConstants.*;
import static org.testng.Assert.*;
public class TestVerifyJob extends JebTestCase
{
@@ -280,7 +281,7 @@
      idBytes[15] = (byte)1;
      //bad jeb format
      idBytes[23] = (byte) 0x04;
      idSet=new EntryIDSet(null, idBytes);
      idSet = newEntryIDSet(idBytes);
      id2child.writeKey(txn, key, idSet);
      performBECleanVerify("id2children", 6);
    }
@@ -290,6 +291,11 @@
    }
  }
  private EntryIDSet newEntryIDSet(byte[] idBytes)
  {
    return new EntryIDSet((ByteString) null, idBytes);
  }
  /**
   * Runs clean verify against the id2subtree index after adding
   * various errors in that index file.
@@ -313,17 +319,17 @@
      idBytes[3] = (byte)0xff;
      //non-subordinate
      idBytes[15] = (byte)1;
      idSet=new EntryIDSet(null, idBytes);
      idSet = newEntryIDSet(idBytes);
      id2subtree.writeKey(txn, key, idSet);
      //Try to break JebFormat version of key entry
      key=addID2EntryReturnKey(junkDN, 4, true);
      idBytes[3]=(byte) 0x04;
      idBytes[15]=(byte)0x00;
      EntryIDSet idSet1=new EntryIDSet(null, idBytes);
      EntryIDSet idSet1 = newEntryIDSet(idBytes);
      id2subtree.writeKey(txn, key, idSet1);
      //put invalid key -- no EntryID matches
      key= new EntryID(45).getDatabaseEntry();
      idSet=new EntryIDSet(null, idBytes);
      idSet = newEntryIDSet(idBytes);
      id2subtree.writeKey(txn, key, idSet);
      performBECleanVerify("id2subtree", 7);
    }
@@ -518,7 +524,7 @@
      DatabaseEntry key=addID2EntryReturnKey(noParentDN, 10, false);
      byte[] idBytes=new byte[16];
      idBytes[7]=(byte) 0x0A;
      EntryIDSet idSet=new EntryIDSet(null, idBytes);
      EntryIDSet idSet = newEntryIDSet(idBytes);
      id2child.writeKey(txn, key, idSet);
      //Add child entry - don't worry about key
      addID2EntryReturnKey(cDN, 11, false);
@@ -527,7 +533,7 @@
      //add parent key/IDSet with bad IDset id
      byte[] idBytesp=new byte[16];
      idBytesp[7]=(byte) 0xFF;
      EntryIDSet idSetp=new EntryIDSet(null, idBytesp);
      EntryIDSet idSetp = newEntryIDSet(idBytesp);
      id2child.writeKey(txn, keyp, idSetp);
      performBECompleteVerify("id2children", 3);
    }