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

Jean-Noel Rouvignac
11.47.2014 9ff093de3e9f067d08bcc6d3134121128974a681
OPENDJ-1308 Migrate schema support

In SubstringIndexer.createKeys(), used the IndexingOptions parameter rather than the field.
Caller of createKeys() was passing in a null IndexingOptions, so this has to be fixed all the way up the call hierarchy.



SubstringIndexer.java:
In createKeys(), used the IndexingOptions parameter rather than the field.
In ctor, remove now unused IndexingOptions parameter.


AttributeIndex.java:
Consequence of the change to SubstringIndexer.
Added getIndexingOptions().
In applyConfigurationChange(), also used applyChangeToIndex() for substringIndexer.
In addEntry(), removeEntry() and modifyEntry(), renamed local variables + passed down the IndexingOptions.

Indexer.java, ID2CIndexer.java, ID2SIndexer.java, PresenceIndexer.java:
In indexEntry(), replaceEntry() and modifyEntry(), added IndexingOptions parameter.
Added Indexer.toString() to mutualize javadocs for this method.
Used {@inheritDoc}.

Index.java, NullIndex.java, JEExtensibleIndexer.java:
In a few methods, added IndexingOptions parameter + passed them down.


VerifyJob.java:
In iterateIndex(), passed down the IndexingOptions.
In iterateAttrIndex(), added IndexingOptions parameter + passed them down + removed unused parameters.
Removed now unused IndexType enum.

Importer.java:
In fillIndexKey(), processIndexes() andprocessExtensibleIndexes(),
In a few methods, added IndexingOptions parameter + passed them down.

TestBackendImpl.java:
In newSubstringIndexer(), consequence of the change to SubstringIndexer ctor.
Extracted method getOptions() + called it from assertIndexContainsID() methods.
12 files modified
495 ■■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java 99 ●●●●● 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 39 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/Indexer.java 18 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/JEExtensibleIndexer.java 58 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/NullIndex.java 13 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/PresenceIndexer.java 42 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/SubstringIndexer.java 9 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java 64 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java 45 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java 26 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
@@ -161,7 +161,7 @@
    if (indexConfig.getIndexType().contains(IndexType.SUBSTRING))
    {
      Index substringIndex = buildExtIndex(name, attrType, indexEntryLimit,
          attrType.getSubstringMatchingRule(), new SubstringIndexer(attrType, config));
          attrType.getSubstringMatchingRule(), new SubstringIndexer(attrType));
      nameToIndexes.put(IndexType.SUBSTRING.toString(), substringIndex);
    }
@@ -300,6 +300,16 @@
  }
  /**
   * Return the indexing options of this AttributeIndex.
   *
   * @return the indexing options of this AttributeIndex.
   */
  public IndexingOptions getIndexingOptions()
  {
    return indexQueryFactory.getIndexingOptions();
  }
  /**
   * Get the JE index configuration used by this index.
   * @return The configuration in effect.
   */
@@ -319,15 +329,15 @@
   * @throws DatabaseException If an error occurs in the JE database.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  public boolean addEntry(IndexBuffer buffer, EntryID entryID,
                          Entry entry)
  public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  {
    boolean success = true;
    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
    for (Index index : nameToIndexes.values())
    {
      if (!index.addEntry(buffer, entryID, entry))
      if (!index.addEntry(buffer, entryID, entry, options))
      {
        success = false;
      }
@@ -335,9 +345,9 @@
    if(extensibleIndexes!=null)
    {
      for(Index extensibleIndex:extensibleIndexes.getIndexes())
      for (Index index : extensibleIndexes.getIndexes())
      {
        if(!extensibleIndex.addEntry(buffer, entryID,entry))
        if (!index.addEntry(buffer, entryID, entry, options))
        {
          success = false;
        }
@@ -363,9 +373,10 @@
  {
    boolean success = true;
    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
    for (Index index : nameToIndexes.values())
    {
      if (!index.addEntry(txn, entryID, entry))
      if (!index.addEntry(txn, entryID, entry, options))
      {
        success = false;
      }
@@ -373,9 +384,9 @@
    if(extensibleIndexes!=null)
    {
      for(Index extensibleIndex:extensibleIndexes.getIndexes())
      for (Index index : extensibleIndexes.getIndexes())
      {
        if(!extensibleIndex.addEntry(txn, entryID,entry))
        if (!index.addEntry(txn, entryID, entry, options))
        {
          success = false;
        }
@@ -394,20 +405,20 @@
   * @throws DatabaseException If an error occurs in the JE database.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  public void removeEntry(IndexBuffer buffer, EntryID entryID,
                          Entry entry)
  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  {
    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
    for (Index index : nameToIndexes.values())
    {
      index.removeEntry(buffer, entryID, entry);
      index.removeEntry(buffer, entryID, entry, options);
    }
    if(extensibleIndexes!=null)
    {
      for(Index extensibleIndex:extensibleIndexes.getIndexes())
      for (Index index : extensibleIndexes.getIndexes())
      {
        extensibleIndex.removeEntry(buffer, entryID, entry);
        index.removeEntry(buffer, entryID, entry, options);
      }
    }
  }
@@ -424,16 +435,17 @@
  public void removeEntry(Transaction txn, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  {
    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
    for (Index index : nameToIndexes.values())
    {
      index.removeEntry(txn, entryID, entry);
      index.removeEntry(txn, entryID, entry, options);
    }
    if(extensibleIndexes!=null)
    {
      for(Index extensibleIndex:extensibleIndexes.getIndexes())
      for (Index index : extensibleIndexes.getIndexes())
      {
        extensibleIndex.removeEntry(txn, entryID, entry);
        index.removeEntry(txn, entryID, entry, options);
      }
    }
  }
@@ -457,16 +469,17 @@
                          List<Modification> mods)
       throws DatabaseException
  {
    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
    for (Index index : nameToIndexes.values())
    {
      index.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
      index.modifyEntry(txn, entryID, oldEntry, newEntry, mods, options);
    }
    if(extensibleIndexes!=null)
    {
      for(Index extensibleIndex:extensibleIndexes.getIndexes())
      for (Index index : extensibleIndexes.getIndexes())
      {
        extensibleIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
        index.modifyEntry(txn, entryID, oldEntry, newEntry, mods, options);
      }
    }
  }
@@ -490,16 +503,17 @@
                          List<Modification> mods)
       throws DatabaseException
  {
    final IndexingOptions options = indexQueryFactory.getIndexingOptions();
    for (Index index : nameToIndexes.values())
    {
      index.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
      index.modifyEntry(buffer, entryID, oldEntry, newEntry, mods, options);
    }
    if(extensibleIndexes!=null)
    {
      for(Index extensibleIndex:extensibleIndexes.getIndexes())
      for (Index index : extensibleIndexes.getIndexes())
      {
        extensibleIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
        index.modifyEntry(buffer, entryID, oldEntry, newEntry, mods, options);
      }
    }
  }
@@ -1024,9 +1038,6 @@
      final int indexEntryLimit = cfg.getIndexEntryLimit();
      final JEIndexConfig config = new JEIndexConfig(cfg.getSubstringLength());
      applyChangeToIndex(cfg, attrType, name, IndexType.EQUALITY,
          new EqualityIndexer(attrType), adminActionRequired, messages);
      Index presenceIndex = nameToIndexes.get(IndexType.PRESENCE.toString());
      if (cfg.getIndexType().contains(IndexType.PRESENCE))
      {
@@ -1052,38 +1063,10 @@
        removeIndex(presenceIndex, IndexType.PRESENCE);
      }
      Index substringIndex = nameToIndexes.get(IndexType.SUBSTRING.toString());
      if (cfg.getIndexType().contains(IndexType.SUBSTRING))
      {
        SubstringIndexer indexer = new SubstringIndexer(attrType, config);
        Indexer extIndexer = new JEExtensibleIndexer(attrType, indexer);
        if(substringIndex == null)
        {
          Index index = newIndex(name + "." + indexer.getExtensibleIndexID(),
              indexEntryLimit, extIndexer);
          substringIndex = openIndex(index, adminActionRequired, messages);
          nameToIndexes.put(IndexType.SUBSTRING.toString(), substringIndex);
        }
        else
        {
          // already exists. Just update index entry limit.
          if(substringIndex.setIndexEntryLimit(indexEntryLimit))
          {
            adminActionRequired.set(true);
            messages.add(NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(substringIndex.getName()));
          }
          if (indexConfig.getSubstringLength() != cfg.getSubstringLength())
          {
            substringIndex.setIndexer(extIndexer);
          }
        }
      }
      else
      {
        removeIndex(substringIndex, IndexType.SUBSTRING);
      }
      applyChangeToIndex(cfg, attrType, name, IndexType.EQUALITY,
          new EqualityIndexer(attrType), adminActionRequired, messages);
      applyChangeToIndex(cfg, attrType, name, IndexType.SUBSTRING,
          new SubstringIndexer(attrType), adminActionRequired, messages);
      applyChangeToIndex(cfg, attrType, name, IndexType.ORDERING,
          new OrderingIndexer(attrType), adminActionRequired, messages);
      applyChangeToIndex(cfg, attrType, name, IndexType.APPROXIMATE,
opendj3-server-dev/src/server/org/opends/server/backends/jeb/ID2CIndexer.java
@@ -29,6 +29,7 @@
import java.util.*;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
@@ -47,25 +48,16 @@
    // No implementation required.
  }
  /**
   * Get a string representation of this object.  The returned value is
   * used to name an index created using this object.
   * @return A string representation of this object.
   */
  /** {@inheritDoc} */
  @Override
  public String toString()
  {
    return "id2children";
  }
  /**
   * 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.
   */
  /** {@inheritDoc} */
  @Override
  public void indexEntry(Entry entry, Set<ByteString> addKeys)
  public void indexEntry(Entry entry, Set<ByteString> addKeys, IndexingOptions options)
  {
    // The superior entry IDs are in the entry attachment.
    ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment();
@@ -82,36 +74,19 @@
    }
  }
  /**
   * Generate the set of index keys to be added and the set of index keys
   * to be deleted for an entry that has been replaced.
   *
   * @param oldEntry The original entry contents.
   * @param newEntry The new entry contents.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  /** {@inheritDoc} */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<ByteString, Boolean> modifiedKeys)
                           Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
  {
    // Nothing to do.
  }
  /**
   * Generate the set of index keys to be added and the set of index keys
   * to be deleted for an entry that was modified.
   *
   * @param oldEntry The original entry contents.
   * @param newEntry The new entry contents.
   * @param mods The set of modifications that were applied to the entry.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  /** {@inheritDoc} */
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<ByteString, Boolean> modifiedKeys)
                          Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
  {
    // Nothing to do.
  }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/ID2SIndexer.java
@@ -29,6 +29,7 @@
import java.util.*;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.types.Entry;
import org.opends.server.types.Modification;
@@ -46,25 +47,16 @@
  {
  }
  /**
   * Get a string representation of this object.  The returned value is
   * used to name an index created using this object.
   * @return A string representation of this object.
   */
  /** {@inheritDoc} */
  @Override
  public String toString()
  {
    return "id2subtree";
  }
  /**
   * 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.
   */
  /** {@inheritDoc} */
  @Override
  public void indexEntry(Entry entry, Set<ByteString> addKeys)
  public void indexEntry(Entry entry, Set<ByteString> addKeys, IndexingOptions options)
  {
    // The superior entry IDs are in the entry attachment.
    ArrayList<EntryID> ids = (ArrayList<EntryID>) entry.getAttachment();
@@ -81,36 +73,19 @@
    }
  }
  /**
   * Generate the set of index keys to be added and the set of index keys
   * to be deleted for an entry that has been replaced.
   *
   * @param oldEntry The original entry contents.
   * @param newEntry The new entry contents.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  /** {@inheritDoc} */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<ByteString, Boolean> modifiedKeys)
                           Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
  {
    // Nothing to do.
  }
  /**
   * Generate the set of index keys to be added and the set of index keys
   * to be deleted for an entry that was modified.
   *
   * @param oldEntry The original entry contents.
   * @param newEntry The new entry contents.
   * @param mods The set of modifications that were applied to the entry.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  /** {@inheritDoc} */
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<ByteString, Boolean> modifiedKeys)
                          Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
  {
    // Nothing to do.
  }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/Index.java
@@ -31,6 +31,7 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.backends.jeb.importLDIF.ImportIDSet;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
@@ -1177,16 +1178,17 @@
   * @param buffer The index buffer to use to store the deleted keys
   * @param entryID     The entry ID.
   * @param entry       The entry to be indexed.
   * @param options     The indexing options to use
   * @return True if all the indexType keys for the entry are added. False if
   *         the entry ID already exists for some keys.
   * @throws DatabaseException If an error occurs in the JE database.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry,
      IndexingOptions options) throws DatabaseException, DirectoryException
  {
    HashSet<ByteString> addKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, addKeys);
    indexer.indexEntry(entry, addKeys, options);
    boolean success = true;
    for (ByteString keyBytes : addKeys)
@@ -1205,17 +1207,18 @@
   * @param txn A database transaction, or null if none is required.
   * @param entryID     The entry ID.
   * @param entry       The entry to be indexed.
   * @param options     The indexing options to use
   * @return True if all the indexType keys for the entry are added. False if
   *         the entry ID already exists for some keys.
   * @throws DatabaseException If an error occurs in the JE database.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  public boolean addEntry(Transaction txn, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  public boolean addEntry(Transaction txn, EntryID entryID, Entry entry,
      IndexingOptions options) throws DatabaseException, DirectoryException
  {
    TreeSet<ByteString> addKeys =
        new TreeSet<ByteString>(indexer.getBSComparator());
    indexer.indexEntry(entry, addKeys);
    indexer.indexEntry(entry, addKeys, options);
    DatabaseEntry key = new DatabaseEntry();
    boolean success = true;
@@ -1236,14 +1239,15 @@
   * @param buffer The index buffer to use to store the deleted keys
   * @param entryID     The entry ID
   * @param entry       The contents of the deleted entry.
   * @param options     The indexing options to use
   * @throws DatabaseException If an error occurs in the JE database.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry,
      IndexingOptions options) throws DatabaseException, DirectoryException
  {
    HashSet<ByteString> delKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, delKeys);
    indexer.indexEntry(entry, delKeys, options);
    for (ByteString keyBytes : delKeys)
    {
@@ -1257,15 +1261,16 @@
   * @param txn A database transaction, or null if none is required.
   * @param entryID     The entry ID
   * @param entry       The contents of the deleted entry.
   * @param options     The indexing options to use
   * @throws DatabaseException If an error occurs in the JE database.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  public void removeEntry(Transaction txn, EntryID entryID, Entry entry)
       throws DatabaseException, DirectoryException
  public void removeEntry(Transaction txn, EntryID entryID, Entry entry,
      IndexingOptions options) throws DatabaseException, DirectoryException
  {
    TreeSet<ByteString> delKeys =
        new TreeSet<ByteString>(indexer.getBSComparator());
    indexer.indexEntry(entry, delKeys);
    indexer.indexEntry(entry, delKeys, options);
    DatabaseEntry key = new DatabaseEntry();
    for (ByteString keyBytes : delKeys)
@@ -1285,18 +1290,19 @@
   * @param oldEntry The entry before the modifications were applied.
   * @param newEntry The entry after the modifications were applied.
   * @param mods The sequence of modifications in the Modify operation.
   * @param options The indexing options to use
   * @throws DatabaseException If an error occurs in the JE database.
   */
  public void modifyEntry(Transaction txn,
                          EntryID entryID,
                          Entry oldEntry,
                          Entry newEntry,
                          List<Modification> mods)
                          List<Modification> mods, IndexingOptions options)
       throws DatabaseException
  {
    TreeMap<ByteString, Boolean> modifiedKeys =
        new TreeMap<ByteString, Boolean>(indexer.getBSComparator());
    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys);
    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys, options);
    DatabaseEntry key = new DatabaseEntry();
    for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet())
@@ -1322,18 +1328,19 @@
   * @param oldEntry The entry before the modifications were applied.
   * @param newEntry The entry after the modifications were applied.
   * @param mods The sequence of modifications in the Modify operation.
   * @param options The indexing options to use
   * @throws DatabaseException If an error occurs in the JE database.
   */
  public void modifyEntry(IndexBuffer buffer,
                          EntryID entryID,
                          Entry oldEntry,
                          Entry newEntry,
                          List<Modification> mods)
                          List<Modification> mods, IndexingOptions options)
      throws DatabaseException
  {
    TreeMap<ByteString, Boolean> modifiedKeys =
        new TreeMap<ByteString, Boolean>(indexer.getBSComparator());
    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys);
    indexer.modifyEntry(oldEntry, newEntry, mods, modifiedKeys, options);
    for (Map.Entry<ByteString, Boolean> modifiedKey : modifiedKeys.entrySet())
    {
opendj3-server-dev/src/server/org/opends/server/backends/jeb/Indexer.java
@@ -32,6 +32,7 @@
import java.util.Set;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.backends.jeb.AttributeIndex.BSKeyComparator;
import org.opends.server.backends.jeb.AttributeIndex.KeyComparator;
import org.opends.server.types.Entry;
@@ -76,8 +77,9 @@
   *
   * @param entry The entry.
   * @param keys The set into which the generated keys will be inserted.
   * @param options The indexing options to use
   */
  public abstract void indexEntry(Entry entry, Set<ByteString> keys);
  public abstract void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options);
  /**
   * Generate the set of index keys to be added and the set of index keys
@@ -86,9 +88,10 @@
   * @param oldEntry The original entry contents.
   * @param newEntry The new entry contents.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   * @param options The indexing options to use
   */
  public abstract void replaceEntry(Entry oldEntry, Entry newEntry,
                                    Map<ByteString, Boolean> modifiedKeys);
      Map<ByteString, Boolean> modifiedKeys, IndexingOptions options);
  /**
   * Generate the set of index keys to be added and the set of index keys
@@ -98,9 +101,16 @@
   * @param newEntry The new entry contents.
   * @param mods The set of modifications that were applied to the entry.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   * @param options The indexing options to use
   */
  public abstract void modifyEntry(Entry oldEntry, Entry newEntry,
                                   List<Modification> mods,
                                   Map<ByteString, Boolean> modifiedKeys);
      List<Modification> mods, Map<ByteString, Boolean> modifiedKeys,
      IndexingOptions options);
  /**
   * Get a string representation of this object.  The returned value is
   * used to name an index created using this object.
   * @return A string representation of this object.
   */
  public abstract String toString();
}
opendj3-server-dev/src/server/org/opends/server/backends/jeb/JEExtensibleIndexer.java
@@ -34,6 +34,7 @@
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.api.ExtensibleIndexer;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
@@ -77,11 +78,7 @@
    this.extensibleIndexer = extensibleIndexer;
  }
   /**
   * Gets a string representation of this object.  The returned value is
   * used to name an index created using this object.
   * @return A string representation of this object.
   */
  /** {@inheritDoc} */
  @Override
  public String toString()
  {
@@ -89,53 +86,40 @@
            + extensibleIndexer.getExtensibleIndexID();
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public void indexEntry(Entry entry, Set<ByteString> keys)
  public void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options)
  {
    List<Attribute> attrList =
         entry.getAttribute(attributeType);
    List<Attribute> attrList = entry.getAttribute(attributeType);
    if (attrList != null)
    {
      indexAttribute(attrList, keys);
      indexAttribute(attrList, keys, options);
    }
  }
 /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<ByteString, Boolean> modifiedKeys)
      Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
    indexAttribute(oldAttributes, modifiedKeys, false);
    indexAttribute(newAttributes, modifiedKeys, true);
    indexAttribute(oldAttributes, modifiedKeys, false, options);
    indexAttribute(newAttributes, modifiedKeys, true, options);
  }
  /**
   * {@inheritDoc}
   */
  /** {@inheritDoc} */
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<ByteString, Boolean> modifiedKeys)
      List<Modification> mods, Map<ByteString, Boolean> modifiedKeys,
      IndexingOptions options)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
    indexAttribute(oldAttributes, modifiedKeys, false);
    indexAttribute(newAttributes, modifiedKeys, true);
    indexAttribute(oldAttributes, modifiedKeys, false, options);
    indexAttribute(newAttributes, modifiedKeys, true, options);
  }
@@ -145,8 +129,8 @@
   * @param attrList The attribute for which substring keys are required.
   * @param keys The set into which the generated keys will be inserted.
   */
  private void indexAttribute(List<Attribute> attrList,
                              Set<ByteString> keys)
  private void indexAttribute(List<Attribute> attrList, Set<ByteString> keys,
      IndexingOptions options)
  {
    if (attrList == null) return;
@@ -158,7 +142,7 @@
        {
          try
          {
            extensibleIndexer.createKeys(null, value, null, keys);
            extensibleIndexer.createKeys(null, value, options, keys);
          }
          catch (DecodeException e)
          {
@@ -180,13 +164,13 @@
   * be inserted or <code>false</code> otherwise.
   */
  private void indexAttribute(List<Attribute> attrList,
                              Map<ByteString, Boolean> modifiedKeys,
                              Boolean insert)
      Map<ByteString, Boolean> modifiedKeys, Boolean insert,
      IndexingOptions options)
  {
    if (attrList == null) return;
    final Set<ByteString> keys = new HashSet<ByteString>();
    indexAttribute(attrList, keys);
    indexAttribute(attrList, keys, options);
    computeModifiedKeys(modifiedKeys, insert, keys);
  }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/NullIndex.java
@@ -29,6 +29,7 @@
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.backends.jeb.importLDIF.ImportIDSet;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
@@ -228,7 +229,7 @@
  /** {@inheritDoc} */
  @Override
  public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
  public boolean addEntry(IndexBuffer buffer, EntryID entryID, Entry entry, IndexingOptions options)
      throws DatabaseException, DirectoryException
  {
    return true;
@@ -238,7 +239,7 @@
  /** {@inheritDoc} */
  @Override
  public boolean addEntry(Transaction txn, EntryID entryID, Entry entry)
  public boolean addEntry(Transaction txn, EntryID entryID, Entry entry, IndexingOptions options)
      throws DatabaseException, DirectoryException
  {
    return true;
@@ -248,7 +249,7 @@
  /** {@inheritDoc} */
  @Override
  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry)
  public void removeEntry(IndexBuffer buffer, EntryID entryID, Entry entry, IndexingOptions options)
      throws DatabaseException, DirectoryException
  {
    // Do nothing.
@@ -258,7 +259,7 @@
  /** {@inheritDoc} */
  @Override
  public void removeEntry(Transaction txn, EntryID entryID, Entry entry)
  public void removeEntry(Transaction txn, EntryID entryID, Entry entry, IndexingOptions options)
      throws DatabaseException, DirectoryException
  {
    // Do nothing.
@@ -269,7 +270,7 @@
  /** {@inheritDoc} */
  @Override
  public void modifyEntry(Transaction txn, EntryID entryID, Entry oldEntry,
      Entry newEntry, List<Modification> mods) throws DatabaseException
      Entry newEntry, List<Modification> mods, IndexingOptions options) throws DatabaseException
  {
    // Do nothing.
  }
@@ -279,7 +280,7 @@
  /** {@inheritDoc} */
  @Override
  public void modifyEntry(IndexBuffer buffer, EntryID entryID, Entry oldEntry,
      Entry newEntry, List<Modification> mods) throws DatabaseException
      Entry newEntry, List<Modification> mods, IndexingOptions options) throws DatabaseException
  {
    // Do nothing.
  }
opendj3-server-dev/src/server/org/opends/server/backends/jeb/PresenceIndexer.java
@@ -31,6 +31,7 @@
import java.util.Set;
import org.forgerock.opendj.ldap.ByteString;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
import org.opends.server.types.Entry;
@@ -58,24 +59,16 @@
    this.attributeType = attributeType;
  }
  /**
   * Get a string representation of this object.
   * @return A string representation of this object.
   */
  /** {@inheritDoc} */
  @Override
  public String toString()
  {
    return attributeType.getNameOrOID() + ".presence";
  }
  /**
   * 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.
   */
  /** {@inheritDoc} */
  @Override
  public void indexEntry(Entry entry, Set<ByteString> keys)
  public void indexEntry(Entry entry, Set<ByteString> keys, IndexingOptions options)
  {
    List<Attribute> attrList =
         entry.getAttribute(attributeType);
@@ -88,19 +81,10 @@
    }
  }
  /**
   * Generate the set of index keys to be added and the set of index keys
   * to be deleted for an entry that has been replaced.
   *
   * @param oldEntry The original entry contents.
   * @param newEntry The new entry contents.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  /** {@inheritDoc} */
  @Override
  public void replaceEntry(Entry oldEntry, Entry newEntry,
                           Map<ByteString, Boolean> modifiedKeys)
                           Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
@@ -120,21 +104,11 @@
    }
  }
  /**
   * Generate the set of index keys to be added and the set of index keys
   * to be deleted for an entry that was modified.
   *
   * @param oldEntry The original entry contents.
   * @param newEntry The new entry contents.
   * @param mods The set of modifications that were applied to the entry.
   * @param modifiedKeys The map into which the modified keys will be inserted.
   */
  /** {@inheritDoc} */
  @Override
  public void modifyEntry(Entry oldEntry, Entry newEntry,
                          List<Modification> mods,
                          Map<ByteString, Boolean> modifiedKeys)
                          Map<ByteString, Boolean> modifiedKeys, IndexingOptions options)
  {
    List<Attribute> newAttributes = newEntry.getAttribute(attributeType, true);
    List<Attribute> oldAttributes = oldEntry.getAttribute(attributeType, true);
opendj3-server-dev/src/server/org/opends/server/backends/jeb/SubstringIndexer.java
@@ -44,21 +44,16 @@
{
  private SubstringMatchingRule substringRule;
  private IndexingOptions indexingOptions;
  /**
   * Create a new attribute substring indexer for the given index configuration.
   *
   * @param attributeType
   *          The attribute type for which an indexer is required.
   * @param indexingOptions
   *          The decomposed substring length.
   */
  public SubstringIndexer(AttributeType attributeType,
      IndexingOptions indexingOptions)
  public SubstringIndexer(AttributeType attributeType)
  {
    this.substringRule = attributeType.getSubstringMatchingRule();
    this.indexingOptions = indexingOptions;
  }
  /** {@inheritDoc} */
@@ -84,7 +79,7 @@
  { // FIXME Code similar to
    // AbstractSubstringMatchingRuleImpl.SubstringIndexer.createKeys()
    ByteString normValue = substringRule.normalizeAttributeValue(value);
    final int substringKeySize = indexingOptions.substringKeySize();
    final int substringKeySize = options.substringKeySize();
    // Example: The value is ABCDE and the substring length is 3.
    // We produce the keys ABC BCD CDE DE E
opendj3-server-dev/src/server/org/opends/server/backends/jeb/VerifyJob.java
@@ -34,6 +34,7 @@
import org.forgerock.opendj.ldap.ConditionResult;
import org.forgerock.opendj.ldap.DecodeException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.api.MatchingRule;
import org.opends.server.core.DirectoryServer;
import org.opends.server.types.*;
@@ -151,14 +152,6 @@
  private ArrayList<VLVIndex> vlvIndexList = new ArrayList<VLVIndex>();
  /**
   * The types of indexes that are verifiable.
   */
  private enum IndexType
  {
      PRES, EQ, SUBSTRING, ORDERING, APPROXIMATE
  }
  /**
   * Construct a VerifyJob.
   *
   * @param verifyConfig The verify configuration.
@@ -346,10 +339,8 @@
        rate = 1000f*keyCount / totalTime;
      }
      addStatEntry(statEntry, "verify-error-count",
                   String.valueOf(errorCount));
      addStatEntry(statEntry, "verify-key-count",
                   String.valueOf(keyCount));
      addStatEntry(statEntry, "verify-error-count", String.valueOf(errorCount));
      addStatEntry(statEntry, "verify-key-count", String.valueOf(keyCount));
      if (cleanMode)
      {
        logger.info(NOTE_JEB_VERIFY_CLEAN_FINAL_STATUS, keyCount, errorCount, totalTime/1000, rate);
@@ -437,8 +428,7 @@
      Long storedEntryCount = id2entry.getRecordCount();
      while (cursor.getNext(key, data, null) ==
                OperationStatus.SUCCESS)
      while (cursor.getNext(key, data, null) == OperationStatus.SUCCESS)
      {
        EntryID entryID;
        try
@@ -529,17 +519,12 @@
      if(attrIndexList.size() > 0)
      {
        AttributeIndex attrIndex = attrIndexList.get(0);
        iterateAttrIndex(attrIndex.getAttributeType(),
                         attrIndex.getEqualityIndex(), IndexType.EQ );
        iterateAttrIndex(attrIndex.getAttributeType(),
                         attrIndex.getPresenceIndex(), IndexType.PRES);
        iterateAttrIndex(attrIndex.getAttributeType(),
                         attrIndex.getSubstringIndex(), IndexType.SUBSTRING);
        iterateAttrIndex(attrIndex.getAttributeType(),
                         attrIndex.getOrderingIndex(), IndexType.ORDERING);
        iterateAttrIndex(attrIndex.getAttributeType(),
                         attrIndex.getApproximateIndex(),
                         IndexType.APPROXIMATE);
        final IndexingOptions options = attrIndex.getIndexingOptions();
        iterateAttrIndex(attrIndex.getEqualityIndex(), options);
        iterateAttrIndex(attrIndex.getPresenceIndex(), options);
        iterateAttrIndex(attrIndex.getSubstringIndex(), options);
        iterateAttrIndex(attrIndex.getOrderingIndex(), options);
        iterateAttrIndex(attrIndex.getApproximateIndex(), options);
       // TODO: Need to iterate through ExtendedMatchingRules indexes.
      } else if(vlvIndexList.size() > 0)
      {
@@ -562,8 +547,7 @@
      DatabaseEntry key = new DatabaseEntry();
      DatabaseEntry data = new DatabaseEntry();
      while (cursor.getNext(key, data, null) ==
                OperationStatus.SUCCESS)
      while (cursor.getNext(key, data, null) == OperationStatus.SUCCESS)
      {
        keyCount++;
@@ -610,8 +594,7 @@
        else
        {
          if (!Arrays.equals(JebFormat.dnToDNKey(
              entry.getName(), verifyConfig.getBaseDN().size()),
                             key.getData()))
              entry.getName(), verifyConfig.getBaseDN().size()), key.getData()))
          {
            errorCount++;
            if (logger.isTraceEnabled())
@@ -645,8 +628,7 @@
      DatabaseEntry key = new DatabaseEntry();
      DatabaseEntry data = new DatabaseEntry();
      while (cursor.getNext(key, data, null) ==
                OperationStatus.SUCCESS)
      while (cursor.getNext(key, data, null) == OperationStatus.SUCCESS)
      {
        keyCount++;
@@ -778,8 +760,7 @@
      DatabaseEntry key = new DatabaseEntry();
      DatabaseEntry data = new DatabaseEntry();
      while (cursor.getNext(key, data, null) ==
                OperationStatus.SUCCESS)
      while (cursor.getNext(key, data, null) == OperationStatus.SUCCESS)
      {
        keyCount++;
@@ -1065,14 +1046,11 @@
  /**
   * Iterate through the entries in an attribute index to perform a check for
   * index cleanliness.
   * @param attrType The attribute type of the index to be checked.
   * @param index The index database to be checked.
   * @param indexType Type of the index (ie, SUBSTRING, ORDERING)
   * @throws JebException If an error occurs in the JE backend.
   * @throws DatabaseException If an error occurs in the JE database.
   */
  private void iterateAttrIndex(AttributeType attrType,
          Index index, IndexType indexType)
  private void iterateAttrIndex(Index index, IndexingOptions options)
       throws JebException, DatabaseException
  {
    if (index == null)
@@ -1086,8 +1064,7 @@
      DatabaseEntry key = new DatabaseEntry();
      DatabaseEntry data = new DatabaseEntry();
      while (cursor.getNext(key, data, null) ==
                OperationStatus.SUCCESS)
      while (cursor.getNext(key, data, null) == OperationStatus.SUCCESS)
      {
        keyCount++;
@@ -1193,7 +1170,7 @@
            };
            index.indexer.indexEntry(entry, dummySet);
            index.indexer.indexEntry(entry, dummySet, options);
            if (!foundMatchingKey.get())
            {
@@ -1499,13 +1476,13 @@
    buffer.append(vlvIndex);
    buffer.append(ServerConstants.EOL);
    buffer.append("Key (last sort values):");
    if(keySortValues == null)
    if(keySortValues != null)
    {
      buffer.append("UNBOUNDED (0x00)");
      buffer.append(keySortValues);
    }
    else
    {
      buffer.append(keySortValues);
      buffer.append("UNBOUNDED (0x00)");
    }
    return buffer.toString();
  }
@@ -1619,7 +1596,6 @@
    Index approximateIndex = attrIndex.getApproximateIndex();
    // TODO: Add support for Extended Matching Rules indexes.
    // Presence index.
    if (presenceIndex != null)
    {
      DatabaseEntry presenceKey = AttributeIndex.presenceKey;
opendj3-server-dev/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java
@@ -35,8 +35,10 @@
import org.forgerock.i18n.LocalizableMessage;
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.spi.IndexingOptions;
import org.forgerock.util.Utils;
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn;
import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn.IndexType;
@@ -45,7 +47,6 @@
import org.opends.server.api.DiskSpaceMonitorHandler;
import org.opends.server.backends.jeb.*;
import org.opends.server.backends.jeb.RebuildConfig.RebuildMode;
import org.forgerock.opendj.config.server.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.extensions.DiskSpaceMonitor;
import org.opends.server.types.*;
@@ -1529,20 +1530,20 @@
    }
    @Override
    void processAttribute(Index index, Entry entry, EntryID entryID,
    void processAttribute(Index index, Entry entry, EntryID entryID, IndexingOptions options,
        IndexKey indexKey) throws DatabaseException, InterruptedException
    {
      if (oldEntry != null)
      {
        deleteKeySet.clear();
        index.indexer.indexEntry(oldEntry, deleteKeySet);
        index.indexer.indexEntry(oldEntry, deleteKeySet, options);
        for (ByteString delKey : deleteKeySet)
        {
          processKey(index, delKey.toByteArray(), entryID, indexComparator, indexKey, false);
        }
      }
      insertKeySet.clear();
      index.indexer.indexEntry(entry, insertKeySet);
      index.indexer.indexEntry(entry, insertKeySet, options);
      for (ByteString key : insertKeySet)
      {
        processKey(index, key.toByteArray(), entryID, indexComparator, indexKey, true);
@@ -1678,30 +1679,31 @@
        InterruptedException, DirectoryException, JebException
    {
      AttributeIndex attributeIndex = mapEntry.getValue();
      IndexingOptions options = attributeIndex.getIndexingOptions();
      Index index;
      if ((index = attributeIndex.getEqualityIndex()) != null)
      {
        processAttribute(index, entry, entryID, new IndexKey(attributeType,
        processAttribute(index, entry, entryID, options, new IndexKey(attributeType,
            ImportIndexType.EQUALITY, index.getIndexEntryLimit()));
      }
      if ((index = attributeIndex.getPresenceIndex()) != null)
      {
        processAttribute(index, entry, entryID, new IndexKey(attributeType,
        processAttribute(index, entry, entryID, options, new IndexKey(attributeType,
            ImportIndexType.PRESENCE, index.getIndexEntryLimit()));
      }
      if ((index = attributeIndex.getSubstringIndex()) != null)
      {
        processAttribute(index, entry, entryID, new IndexKey(attributeType,
        processAttribute(index, entry, entryID, options, new IndexKey(attributeType,
            ImportIndexType.SUBSTRING, index.getIndexEntryLimit()));
      }
      if ((index = attributeIndex.getOrderingIndex()) != null)
      {
        processAttribute(index, entry, entryID, new IndexKey(attributeType,
        processAttribute(index, entry, entryID, options, new IndexKey(attributeType,
            ImportIndexType.ORDERING, index.getIndexEntryLimit()));
      }
      if ((index = attributeIndex.getApproximateIndex()) != null)
      {
        processAttribute(index, entry, entryID, new IndexKey(attributeType,
        processAttribute(index, entry, entryID, options, new IndexKey(attributeType,
            ImportIndexType.APPROXIMATE, index.getIndexEntryLimit()));
      }
      for (VLVIndex vlvIdx : suffix.getEntryContainer().getVLVIndexes())
@@ -1720,7 +1722,7 @@
        {
          for (Index subIndex : subIndexes)
          {
            processAttribute(subIndex, entry, entryID, new IndexKey(
            processAttribute(subIndex, entry, entryID, options, new IndexKey(
                attributeType, ImportIndexType.EX_SUBSTRING, subIndex
                    .getIndexEntryLimit()));
          }
@@ -1732,7 +1734,7 @@
        {
          for (Index sharedIndex : sharedIndexes)
          {
            processAttribute(sharedIndex, entry, entryID, new IndexKey(
            processAttribute(sharedIndex, entry, entryID, options, new IndexKey(
                attributeType, ImportIndexType.EX_SHARED, sharedIndex
                    .getIndexEntryLimit()));
          }
@@ -1740,11 +1742,11 @@
      }
    }
    void processAttribute(Index index, Entry entry, EntryID entryID,
    void processAttribute(Index index, Entry entry, EntryID entryID, IndexingOptions options,
        IndexKey indexKey) throws DatabaseException, InterruptedException
    {
      insertKeySet.clear();
      index.indexer.indexEntry(entry, insertKeySet);
      index.indexer.indexEntry(entry, insertKeySet, options);
      for (ByteString key : insertKeySet)
      {
        processKey(index, key.toByteArray(), entryID, indexComparator, indexKey, true);
@@ -3886,10 +3888,11 @@
        AttributeType attrType = key.getAttributeType();
        if (entry.hasAttribute(attrType))
        {
          Collection<Index> indexes = mapEntry.getValue();
          for (Index index : indexes)
          AttributeIndex attributeIndex = entryContainer.getAttributeIndex(attrType);
          IndexingOptions options = attributeIndex.getIndexingOptions();
          for (Index index : mapEntry.getValue())
          {
            processAttribute(index, entry, entryID, key);
            processAttribute(index, entry, entryID, options, key);
          }
        }
      }
@@ -3904,17 +3907,19 @@
        AttributeType attrType = key.getAttributeType();
        if (entry.hasAttribute(attrType))
        {
          AttributeIndex attributeIndex = entryContainer.getAttributeIndex(attrType);
          IndexingOptions options = attributeIndex.getIndexingOptions();
          ImportIndexType indexType = key.getIndexType();
          Index index = mapEntry.getValue();
          if (indexType == ImportIndexType.SUBSTRING)
          {
            processAttribute(index, entry, entryID, new IndexKey(attrType,
                ImportIndexType.SUBSTRING, index.getIndexEntryLimit()));
            processAttribute(index, entry, entryID, options,
                new IndexKey(attrType, ImportIndexType.SUBSTRING, index.getIndexEntryLimit()));
          }
          else
          {
            processAttribute(index, entry, entryID, new IndexKey(attrType,
                indexType, index.getIndexEntryLimit()));
            processAttribute(index, entry, entryID, options,
                new IndexKey(attrType, indexType, index.getIndexEntryLimit()));
          }
        }
      }
opendj3-server-dev/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestBackendImpl.java
@@ -28,11 +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;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.*;
import org.forgerock.opendj.ldap.spi.IndexingOptions;
import org.opends.server.TestCaseUtils;
import org.opends.server.admin.server.AdminTestCaseUtils;
@@ -833,18 +829,30 @@
  private Indexer newSubstringIndexer(AttributeIndex index)
  {
    AttributeType attrType = index.getAttributeType();
    return new JEExtensibleIndexer(attrType, new SubstringIndexer(attrType));
  }
  private IndexingOptions getOptions(AttributeIndex index)
  {
    final IndexingOptions options = mock(IndexingOptions.class);
    when(options.substringKeySize()).thenReturn(
        index.getConfiguration().getSubstringLength());
    AttributeType attrType = index.getAttributeType();
    return new JEExtensibleIndexer(attrType, new SubstringIndexer(attrType, options));
    return options;
  }
  private IndexingOptions getOptions()
  {
    final IndexingOptions options = mock(IndexingOptions.class);
    when(options.substringKeySize()).thenReturn(6);
    return options;
  }
  private void assertIndexContainsID(Indexer indexer, Entry entry, Index index,
      EntryID entryID)
  {
    Set<ByteString> addKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, addKeys);
    indexer.indexEntry(entry, addKeys, getOptions());
    DatabaseEntry key = new DatabaseEntry();
    for (ByteString keyBytes : addKeys)
@@ -858,7 +866,7 @@
      Index index, EntryID entryID, ConditionResult expected)
  {
    Set<ByteString> addKeys = new HashSet<ByteString>();
    indexer.indexEntry(entry, addKeys);
    indexer.indexEntry(entry, addKeys, getOptions());
    assertIndexContainsID(addKeys, index, entryID, expected);
  }