From 3ab9614db1a1a1a30c271424c4189999bf71b87a Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Fri, 07 Mar 2014 10:58:03 +0000
Subject: [PATCH] OPENDJ-1308 Migrate schema support

---
 opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java |  851 +++++++++++++++++---------------------------------------
 1 files changed, 264 insertions(+), 587 deletions(-)

diff --git a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
index c5449f2..841d35d 100644
--- a/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
+++ b/opendj3-server-dev/src/server/org/opends/server/backends/jeb/AttributeIndex.java
@@ -26,7 +26,9 @@
  *      Portions Copyright 2014 Manuel Gaupp
  */
 package org.opends.server.backends.jeb;
+
 import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
@@ -35,6 +37,7 @@
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.spi.IndexQueryFactory;
 import org.forgerock.opendj.ldap.spi.IndexingOptions;
+import org.forgerock.util.Utils;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.meta.LocalDBIndexCfgDefn;
 import org.opends.server.admin.std.server.LocalDBIndexCfg;
@@ -151,20 +154,8 @@
     if (indexConfig.getIndexType().contains(
             LocalDBIndexCfgDefn.IndexType.EQUALITY))
     {
-      if (attrType.getEqualityMatchingRule() == null)
-      {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "equality"));
-      }
-
-      Indexer equalityIndexer = new EqualityIndexer(attrType);
-      this.equalityIndex = new Index(name + ".equality",
-                                     equalityIndexer,
-                                     state,
-                                     indexEntryLimit,
-                                     cursorEntryLimit,
-                                     false,
-                                     env,
-                                     entryContainer);
+      this.equalityIndex = buildExtIndex(
+          name, attrType, attrType.getEqualityMatchingRule(), new EqualityIndexer());
     }
 
     if (indexConfig.getIndexType().contains(
@@ -184,57 +175,21 @@
     if (indexConfig.getIndexType().contains(
             LocalDBIndexCfgDefn.IndexType.SUBSTRING))
     {
-      if (attrType.getSubstringMatchingRule() == null)
-      {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "substring"));
-      }
-
-      Indexer substringIndexer = new SubstringIndexer(attrType, config);
-      this.substringIndex = new Index(name + ".substring",
-                                     substringIndexer,
-                                     state,
-                                     indexEntryLimit,
-                                     cursorEntryLimit,
-                                     false,
-                                     env,
-                                     entryContainer);
+      this.substringIndex = buildExtIndex(
+          name, attrType, attrType.getSubstringMatchingRule(), new SubstringIndexer(attrType, config));
     }
 
     if (indexConfig.getIndexType().contains(
             LocalDBIndexCfgDefn.IndexType.ORDERING))
     {
-      if (attrType.getOrderingMatchingRule() == null)
-      {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "ordering"));
-      }
-
-      Indexer orderingIndexer = new OrderingIndexer(attrType);
-      this.orderingIndex = new Index(name + ".ordering",
-                                     orderingIndexer,
-                                     state,
-                                     indexEntryLimit,
-                                     cursorEntryLimit,
-                                     false,
-                                     env,
-                                     entryContainer);
+      this.orderingIndex = buildExtIndex(
+          name, attrType, attrType.getOrderingMatchingRule(), new OrderingIndexer(attrType));
     }
     if (indexConfig.getIndexType().contains(
         LocalDBIndexCfgDefn.IndexType.APPROXIMATE))
     {
-      if (attrType.getApproximateMatchingRule() == null)
-      {
-        throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(attrType, "approximate"));
-      }
-
-      Indexer approximateIndexer = new ApproximateIndexer(attrType);
-      this.approximateIndex = new Index(name + ".approximate",
-                                        approximateIndexer,
-                                        state,
-                                        indexEntryLimit,
-                                        cursorEntryLimit,
-                                        false,
-                                        env,
-                                        entryContainer);
+      this.approximateIndex = buildExtIndex(
+          name, attrType, attrType.getApproximateMatchingRule(), new ApproximateIndexer(attrType));
     }
     if (indexConfig.getIndexType().contains(
         LocalDBIndexCfgDefn.IndexType.EXTENSIBLE))
@@ -294,6 +249,26 @@
     }
   }
 
+  private Index buildExtIndex(String name, AttributeType attrType,
+      MatchingRule rule, ExtensibleIndexer extIndexer) throws ConfigException
+  {
+    if (rule == null)
+    {
+      throw new ConfigException(ERR_CONFIG_INDEX_TYPE_NEEDS_MATCHING_RULE.get(
+          attrType, extIndexer.getExtensibleIndexID()));
+    }
+
+    Indexer indexer = new JEExtensibleIndexer(attrType, rule, extIndexer);
+    return new Index(name + "." + extIndexer.getExtensibleIndexID(),
+                                   indexer,
+                                   state,
+                                   indexConfig.getIndexEntryLimit(),
+                                   cursorEntryLimit,
+                                   false,
+                                   env,
+                                   entryContainer);
+  }
+
   /**
    * Open the attribute index.
    *
@@ -302,30 +277,11 @@
    */
   public void open() throws DatabaseException
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.open();
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.open();
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.open();
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.open();
-    }
-
-    if (approximateIndex != null)
-    {
-      approximateIndex.open();
-    }
+    open(equalityIndex);
+    open(presenceIndex);
+    open(substringIndex);
+    open(orderingIndex);
+    open(approximateIndex);
 
     if(extensibleIndexes!=null)
     {
@@ -338,6 +294,14 @@
     indexConfig.addChangeListener(this);
   }
 
+  private void open(Index index)
+  {
+    if (index != null)
+    {
+      index.open();
+    }
+  }
+
   /**
    * Close the attribute index.
    *
@@ -346,37 +310,12 @@
    */
   public void close() throws DatabaseException
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.close();
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.close();
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.close();
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.close();
-    }
-
-    if (approximateIndex != null)
-    {
-      approximateIndex.close();
-    }
+    Utils.closeSilently(equalityIndex, presenceIndex, substringIndex,
+        orderingIndex, approximateIndex);
 
     if(extensibleIndexes!=null)
     {
-      for(Index extensibleIndex:extensibleIndexes.getIndexes())
-      {
-        extensibleIndex.close();
-      }
+      Utils.closeSilently(extensibleIndexes.getIndexes());
     }
 
     indexConfig.removeChangeListener(this);
@@ -416,33 +355,13 @@
                           Entry entry)
        throws DatabaseException, DirectoryException
   {
-    boolean success = false;
+    boolean success = true;
 
-    if (equalityIndex != null
-        && !equalityIndex.addEntry(buffer, entryID, entry))
-    {
-      success = false;
-    }
-    if (presenceIndex != null
-        && !presenceIndex.addEntry(buffer, entryID, entry))
-    {
-      success = false;
-    }
-    if (substringIndex != null
-        && !substringIndex.addEntry(buffer, entryID, entry))
-    {
-      success = false;
-    }
-    if (orderingIndex != null
-        && !orderingIndex.addEntry(buffer, entryID, entry))
-    {
-      success = false;
-    }
-    if (approximateIndex != null
-        && !approximateIndex.addEntry(buffer, entryID, entry))
-    {
-      success = false;
-    }
+    success = addEntry(equalityIndex, buffer, entryID, entry, success);
+    success = addEntry(presenceIndex, buffer, entryID, entry, success);
+    success = addEntry(substringIndex, buffer, entryID, entry, success);
+    success = addEntry(orderingIndex, buffer, entryID, entry, success);
+    success = addEntry(approximateIndex, buffer, entryID, entry, success);
 
     if(extensibleIndexes!=null)
     {
@@ -458,6 +377,15 @@
     return success;
   }
 
+  private boolean addEntry(Index index, IndexBuffer buffer, EntryID entryID,
+      Entry entry, boolean success) throws DirectoryException, DatabaseException
+  {
+    if (index != null && !index.addEntry(buffer, entryID, entry))
+    {
+      return false;
+    }
+    return success;
+  }
 
   /**
    * Update the attribute index for a new entry.
@@ -475,27 +403,11 @@
   {
     boolean success = true;
 
-    if (equalityIndex != null && !equalityIndex.addEntry(txn, entryID, entry))
-    {
-      success = false;
-    }
-    if (presenceIndex != null && !presenceIndex.addEntry(txn, entryID, entry))
-    {
-      success = false;
-    }
-    if (substringIndex != null && !substringIndex.addEntry(txn, entryID, entry))
-    {
-      success = false;
-    }
-    if (orderingIndex != null && !orderingIndex.addEntry(txn, entryID, entry))
-    {
-      success = false;
-    }
-    if (approximateIndex != null
-        && !approximateIndex.addEntry(txn, entryID, entry))
-    {
-      success = false;
-    }
+    success = addEntry(equalityIndex, txn, entryID, entry, success);
+    success = addEntry(presenceIndex, txn, entryID, entry, success);
+    success = addEntry(substringIndex, txn, entryID, entry, success);
+    success = addEntry(orderingIndex, txn, entryID, entry, success);
+    success = addEntry(approximateIndex, txn, entryID, entry, success);
 
     if(extensibleIndexes!=null)
     {
@@ -511,6 +423,17 @@
     return success;
   }
 
+  private boolean addEntry(Index index, Transaction txn, EntryID entryID,
+      Entry entry, boolean success) throws DirectoryException, DatabaseException
+  {
+    if (index != null && !index.addEntry(txn, entryID, entry))
+    {
+      return false;
+    }
+    return success;
+  }
+
+
   /**
    * Update the attribute index for a deleted entry.
    *
@@ -524,30 +447,11 @@
                           Entry entry)
        throws DatabaseException, DirectoryException
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.removeEntry(buffer, entryID, entry);
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.removeEntry(buffer, entryID, entry);
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.removeEntry(buffer, entryID, entry);
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.removeEntry(buffer, entryID, entry);
-    }
-
-    if(approximateIndex != null)
-    {
-      approximateIndex.removeEntry(buffer, entryID, entry);
-    }
+    removeEntry(equalityIndex, buffer, entryID, entry);
+    removeEntry(presenceIndex, buffer, entryID, entry);
+    removeEntry(substringIndex, buffer, entryID, entry);
+    removeEntry(orderingIndex, buffer, entryID, entry);
+    removeEntry(approximateIndex, buffer, entryID, entry);
 
     if(extensibleIndexes!=null)
     {
@@ -558,6 +462,15 @@
     }
   }
 
+  private void removeEntry(Index index, IndexBuffer buffer, EntryID entryID,
+      Entry entry) throws DirectoryException, DatabaseException
+  {
+    if (index != null)
+    {
+      index.removeEntry(buffer, entryID, entry);
+    }
+  }
+
   /**
    * Update the attribute index for a deleted entry.
    *
@@ -570,30 +483,11 @@
   public void removeEntry(Transaction txn, EntryID entryID, Entry entry)
        throws DatabaseException, DirectoryException
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.removeEntry(txn, entryID, entry);
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.removeEntry(txn, entryID, entry);
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.removeEntry(txn, entryID, entry);
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.removeEntry(txn, entryID, entry);
-    }
-
-    if(approximateIndex != null)
-    {
-      approximateIndex.removeEntry(txn, entryID, entry);
-    }
+    removeEntry(equalityIndex, txn, entryID, entry);
+    removeEntry(presenceIndex, txn, entryID, entry);
+    removeEntry(substringIndex, txn, entryID, entry);
+    removeEntry(orderingIndex, txn, entryID, entry);
+    removeEntry(approximateIndex, txn, entryID, entry);
 
     if(extensibleIndexes!=null)
     {
@@ -604,6 +498,15 @@
     }
   }
 
+  private void removeEntry(Index index, Transaction txn, EntryID entryID,
+      Entry entry) throws DirectoryException, DatabaseException
+  {
+    if (index != null)
+    {
+      index.removeEntry(txn, entryID, entry);
+    }
+  }
+
   /**
    * Update the index to reflect a sequence of modifications in a Modify
    * operation.
@@ -623,30 +526,11 @@
                           List<Modification> mods)
        throws DatabaseException
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (approximateIndex != null)
-    {
-      approximateIndex.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
-    }
+    modifyEntry(equalityIndex, txn, entryID, oldEntry, newEntry, mods);
+    modifyEntry(presenceIndex, txn, entryID, oldEntry, newEntry, mods);
+    modifyEntry(substringIndex, txn, entryID, oldEntry, newEntry, mods);
+    modifyEntry(orderingIndex, txn, entryID, oldEntry, newEntry, mods);
+    modifyEntry(approximateIndex, txn, entryID, oldEntry, newEntry, mods);
 
     if(extensibleIndexes!=null)
     {
@@ -657,6 +541,16 @@
     }
   }
 
+  private void modifyEntry(Index index, Transaction txn, EntryID entryID,
+      Entry oldEntry, Entry newEntry, List<Modification> mods)
+      throws DatabaseException
+  {
+    if (index != null)
+    {
+      index.modifyEntry(txn, entryID, oldEntry, newEntry, mods);
+    }
+  }
+
   /**
    * Update the index to reflect a sequence of modifications in a Modify
    * operation.
@@ -676,30 +570,11 @@
                           List<Modification> mods)
        throws DatabaseException
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
-    }
-
-    if (approximateIndex != null)
-    {
-      approximateIndex.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
-    }
+    modifyEntry(equalityIndex, buffer, entryID, oldEntry, newEntry, mods);
+    modifyEntry(presenceIndex, buffer, entryID, oldEntry, newEntry, mods);
+    modifyEntry(substringIndex, buffer, entryID, oldEntry, newEntry, mods);
+    modifyEntry(orderingIndex, buffer, entryID, oldEntry, newEntry, mods);
+    modifyEntry(approximateIndex, buffer, entryID, oldEntry, newEntry, mods);
 
     if(extensibleIndexes!=null)
     {
@@ -710,6 +585,16 @@
     }
   }
 
+  private void modifyEntry(Index index, IndexBuffer buffer, EntryID entryID,
+      Entry oldEntry, Entry newEntry, List<Modification> mods)
+      throws DatabaseException
+  {
+    if (index != null)
+    {
+      index.modifyEntry(buffer, entryID, oldEntry, newEntry, mods);
+    }
+  }
+
   /**
    * Makes a byte array representing a substring index key for
    * one substring of a value.
@@ -735,8 +620,7 @@
    * @return A set of index keys.
    */
   Set<ByteString> substringKeys(byte[] value)
-  {
-    // FIXME replace this code with SDK's
+  { // FIXME replace this code with SDK's
     // AbstractSubstringMatchingRuleImpl.SubstringIndexer.createKeys()
 
     // Eliminate duplicates by putting the keys into a set.
@@ -769,8 +653,7 @@
    * @return The candidate entry IDs.
    */
   private EntryIDSet matchSubstring(byte[] bytes)
-  {
-    // FIXME replace this code with SDK's
+  { // FIXME replace this code with SDK's
     // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery()
 
     int substrLength = indexConfig.getSubstringLength();
@@ -855,8 +738,7 @@
    * @return The candidate entry IDs.
    */
   private EntryIDSet matchInitialSubstring(byte[] bytes)
-  {
-    // FIXME replace this code with SDK's
+  { // FIXME replace this code with SDK's
     // AbstractSubstringMatchingRuleImpl.DefaultSubstringAssertion.createIndexQuery()
 
     // Iterate through all the keys that have this value as the prefix.
@@ -1051,74 +933,10 @@
       SearchFilter filter, StringBuilder debugBuffer,
       DatabaseEnvironmentMonitor monitor)
   {
-    if (orderingIndex == null)
-    {
-      if(monitor.isFilterUseEnabled())
-      {
-        monitor.updateStats(filter,
-            INFO_JEB_INDEX_FILTER_INDEX_TYPE_DISABLED.get("ordering",
-                indexConfig.getAttribute().getNameOrOID()));
-      }
-      return new EntryIDSet();
-    }
-
-    try
-    {
-      // Set the lower bound for a range search.
-      // Use the ordering matching rule to normalize the value.
-      OrderingMatchingRule orderingRule =
-           filter.getAttributeType().getOrderingMatchingRule();
-      byte[] lower = orderingRule.normalizeAttributeValue(
-           filter.getAssertionValue().getValue()).toByteArray();
-
-      // Set the upper bound to 0 to search all keys greater then the lower
-      // bound.
-      byte[] upper = new byte[0];
-
-      if(debugBuffer != null)
-      {
-        debugBuffer.append("[INDEX:");
-        debugBuffer.append(indexConfig.getAttribute().getNameOrOID());
-        debugBuffer.append(".");
-        debugBuffer.append("ordering]");
-      }
-
-      // Read the range: lower <= keys < upper.
-      EntryIDSet idSet = orderingIndex.readRange(lower, upper, true, false);
-      if(monitor.isFilterUseEnabled())
-      {
-        if(idSet.isDefined())
-        {
-          monitor.updateStats(filter, idSet.size());
-        }
-        else if(!orderingIndex.isTrusted())
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_NOT_TRUSTED.get(
-                  orderingIndex.getName()));
-        }
-        else if(orderingIndex.isRebuildRunning())
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_REBUILD_IN_PROGRESS.get(
-                  orderingIndex.getName()));
-        }
-        else
-        {
-          monitor.updateStats(filter,
-              INFO_JEB_INDEX_FILTER_INDEX_LIMIT_EXCEEDED.get(
-                  orderingIndex.getName()));
-        }
-      }
-      return idSet;
-    }
-    catch (DecodeException e)
-    {
-      logger.traceException(e);
-      return new EntryIDSet();
-    }
+    return evaluateOrderingFilter(filter, true, debugBuffer, monitor);
   }
 
+
   /**
    * Retrieve the entry IDs that might match a less-or-equal filter.
    *
@@ -1135,6 +953,14 @@
                                               StringBuilder debugBuffer,
                                              DatabaseEnvironmentMonitor monitor)
   {
+    return evaluateOrderingFilter(filter, false, debugBuffer, monitor);
+  }
+
+  private EntryIDSet evaluateOrderingFilter(SearchFilter filter,
+      boolean greater, StringBuilder debugBuffer,
+      DatabaseEnvironmentMonitor monitor)
+  {
+
     if (orderingIndex == null)
     {
       if(monitor.isFilterUseEnabled())
@@ -1148,16 +974,28 @@
 
     try
     {
-      // Set the lower bound to 0 to start the range search from the smallest
-      // key.
-      byte[] lower = new byte[0];
-
-      // Set the upper bound for a range search.
       // Use the ordering matching rule to normalize the value.
       OrderingMatchingRule orderingRule =
            filter.getAttributeType().getOrderingMatchingRule();
-      byte[] upper = orderingRule.normalizeAttributeValue(
-           filter.getAssertionValue().getValue()).toByteArray();
+      // FIXME JNR this looks wrong, it should use normalizeAssertionValue()
+      byte[] normalizedValue = orderingRule.normalizeAttributeValue(
+          filter.getAssertionValue().getValue()).toByteArray();
+
+      // Set the lower and upper bounds for a range search.
+      byte[] lower;
+      byte[] upper;
+      if (greater)
+      {
+        // Set upper bound to 0 to search all keys greater than the lower bound.
+        lower = normalizedValue;
+        upper = new byte[0];
+      }
+      else
+      {
+        // Set lower bound to 0 to start the range search from the smallest key.
+        lower = new byte[0];
+        upper = normalizedValue;
+      }
 
       if(debugBuffer != null)
       {
@@ -1167,8 +1005,8 @@
         debugBuffer.append("ordering]");
       }
 
-      // Read the range: lower < keys <= upper.
-      EntryIDSet idSet = orderingIndex.readRange(lower, upper, false, true);
+      // Read the range: lower <= keys < upper OR lower < keys <= upper
+      EntryIDSet idSet = orderingIndex.readRange(lower, upper, greater, !greater);
       if(monitor.isFilterUseEnabled())
       {
         if(idSet.isDefined())
@@ -1506,6 +1344,7 @@
       ApproximateMatchingRule approximateMatchingRule =
           approximateFilter.getAttributeType().getApproximateMatchingRule();
       // Make a key from the normalized assertion value.
+      // FIXME JNR this looks wrong, it should use normalizeAssertionValue()
       byte[] keyBytes =
            approximateMatchingRule.normalizeAttributeValue(
                approximateFilter.getAssertionValue().getValue()).toByteArray();
@@ -1648,30 +1487,11 @@
    */
   public void listDatabases(List<DatabaseContainer> dbList)
   {
-    if (equalityIndex != null)
-    {
-      dbList.add(equalityIndex);
-    }
-
-    if (presenceIndex != null)
-    {
-      dbList.add(presenceIndex);
-    }
-
-    if (substringIndex != null)
-    {
-      dbList.add(substringIndex);
-    }
-
-    if (orderingIndex != null)
-    {
-      dbList.add(orderingIndex);
-    }
-
-    if (approximateIndex != null)
-    {
-      dbList.add(approximateIndex);
-    }
+    addIfNotNull(dbList, equalityIndex);
+    addIfNotNull(dbList, presenceIndex);
+    addIfNotNull(dbList, substringIndex);
+    addIfNotNull(dbList, orderingIndex);
+    addIfNotNull(dbList, approximateIndex);
 
     if(extensibleIndexes!=null)
     {
@@ -1682,6 +1502,14 @@
     }
   }
 
+  private void addIfNotNull(Collection<? super Index> dbList, Index index)
+  {
+    if (index != null)
+    {
+      dbList.add(index);
+    }
+  }
+
   /**
    * Get a string representation of this object.
    * @return return A string representation of this object.
@@ -1748,7 +1576,8 @@
   public synchronized ConfigChangeResult applyConfigurationChange(
       LocalDBIndexCfg cfg)
   {
-    boolean adminActionRequired = false;
+    // this method is not perf sensitive, using an AtomicBoolean will not hurt
+    AtomicBoolean adminActionRequired = new AtomicBoolean(false);
     ArrayList<LocalizableMessage> messages = new ArrayList<LocalizableMessage>();
     try
     {
@@ -1762,32 +1591,16 @@
       {
         if (equalityIndex == null)
         {
-          // Adding equality index
-          Indexer equalityIndexer = new EqualityIndexer(attrType);
-          equalityIndex = new Index(name + ".equality",
-                                    equalityIndexer,
-                                    state,
-                                    indexEntryLimit,
-                                    cursorEntryLimit,
-                                    false,
-                                    env,
-                                    entryContainer);
-          equalityIndex.open();
-
-          if(!equalityIndex.isTrusted())
-          {
-            adminActionRequired = true;
-            messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
-                equalityIndex.getName()));
-          }
-
+          EqualityIndexer indexer = new EqualityIndexer();
+          Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getEqualityMatchingRule(), indexer);
+          equalityIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
         }
         else
         {
           // already exists. Just update index entry limit.
           if(this.equalityIndex.setIndexEntryLimit(indexEntryLimit))
           {
-            adminActionRequired = true;
+            adminActionRequired.set(true);
             LocalizableMessage message =
                     NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                             equalityIndex.getName());
@@ -1806,13 +1619,6 @@
             entryContainer.deleteDatabase(equalityIndex);
             equalityIndex = null;
           }
-          catch(DatabaseException de)
-          {
-            messages.add(LocalizableMessage.raw(
-                    StaticUtils.stackTraceToSingleLineString(de)));
-            return new ConfigChangeResult(
-                DirectoryServer.getServerErrorResultCode(), false, messages);
-          }
           finally
           {
             entryContainer.exclusiveLock.unlock();
@@ -1837,7 +1643,7 @@
 
           if(!presenceIndex.isTrusted())
           {
-            adminActionRequired = true;
+            adminActionRequired.set(true);
             messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
                 presenceIndex.getName()));
           }
@@ -1847,8 +1653,7 @@
           // already exists. Just update index entry limit.
           if(this.presenceIndex.setIndexEntryLimit(indexEntryLimit))
           {
-            adminActionRequired = true;
-
+            adminActionRequired.set(true);
             LocalizableMessage message =
                     NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                             presenceIndex.getName());
@@ -1866,13 +1671,6 @@
             entryContainer.deleteDatabase(presenceIndex);
             presenceIndex = null;
           }
-          catch(DatabaseException de)
-          {
-            messages.add(LocalizableMessage.raw(
-                    StaticUtils.stackTraceToSingleLineString(de)));
-            return new ConfigChangeResult(
-                DirectoryServer.getServerErrorResultCode(), false, messages);
-          }
           finally
           {
             entryContainer.exclusiveLock.unlock();
@@ -1882,43 +1680,27 @@
 
       if (cfg.getIndexType().contains(LocalDBIndexCfgDefn.IndexType.SUBSTRING))
       {
+        SubstringIndexer indexer = new SubstringIndexer(attrType, config);
+        Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getSubstringMatchingRule(), indexer);
         if(substringIndex == null)
         {
-          Indexer substringIndexer = new SubstringIndexer(attrType, config);
-          substringIndex = new Index(name + ".substring",
-                                     substringIndexer,
-                                     state,
-                                     indexEntryLimit,
-                                     cursorEntryLimit,
-                                     false,
-                                     env,
-                                     entryContainer);
-          substringIndex.open();
-
-          if(!substringIndex.isTrusted())
-          {
-            adminActionRequired = true;
-            messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
-                substringIndex.getName()));
-          }
+          substringIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
         }
         else
         {
           // already exists. Just update index entry limit.
           if(this.substringIndex.setIndexEntryLimit(indexEntryLimit))
           {
-            adminActionRequired = true;
+            adminActionRequired.set(true);
             LocalizableMessage message =
                     NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                             substringIndex.getName());
             messages.add(message);
           }
 
-          if(indexConfig.getSubstringLength() !=
-              cfg.getSubstringLength())
+          if (indexConfig.getSubstringLength() != cfg.getSubstringLength())
           {
-            Indexer substringIndexer = new SubstringIndexer(attrType, config);
-            this.substringIndex.setIndexer(substringIndexer);
+            this.substringIndex.setIndexer(extIndexer);
           }
         }
       }
@@ -1932,13 +1714,6 @@
             entryContainer.deleteDatabase(substringIndex);
             substringIndex = null;
           }
-          catch(DatabaseException de)
-          {
-            messages.add(LocalizableMessage.raw(
-                    StaticUtils.stackTraceToSingleLineString(de)));
-            return new ConfigChangeResult(
-                DirectoryServer.getServerErrorResultCode(), false, messages);
-          }
           finally
           {
             entryContainer.exclusiveLock.unlock();
@@ -1950,31 +1725,16 @@
       {
         if(orderingIndex == null)
         {
-          Indexer orderingIndexer = new OrderingIndexer(attrType);
-          orderingIndex = new Index(name + ".ordering",
-                                    orderingIndexer,
-                                    state,
-                                    indexEntryLimit,
-                                    cursorEntryLimit,
-                                    false,
-                                    env,
-                                    entryContainer);
-          orderingIndex.open();
-
-          if(!orderingIndex.isTrusted())
-          {
-            adminActionRequired = true;
-            messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
-                orderingIndex.getName()));
-          }
+          OrderingIndexer indexer = new OrderingIndexer(attrType);
+          Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getOrderingMatchingRule(), indexer);
+          orderingIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
         }
         else
         {
           // already exists. Just update index entry limit.
           if(this.orderingIndex.setIndexEntryLimit(indexEntryLimit))
           {
-            adminActionRequired = true;
-
+            adminActionRequired.set(true);
             LocalizableMessage message =
                     NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                             orderingIndex.getName());
@@ -1992,13 +1752,6 @@
             entryContainer.deleteDatabase(orderingIndex);
             orderingIndex = null;
           }
-          catch(DatabaseException de)
-          {
-            messages.add(LocalizableMessage.raw(
-                    StaticUtils.stackTraceToSingleLineString(de)));
-            return new ConfigChangeResult(
-                DirectoryServer.getServerErrorResultCode(), false, messages);
-          }
           finally
           {
             entryContainer.exclusiveLock.unlock();
@@ -2011,31 +1764,16 @@
       {
         if(approximateIndex == null)
         {
-          Indexer approximateIndexer = new ApproximateIndexer(attrType);
-          approximateIndex = new Index(name + ".approximate",
-                                       approximateIndexer,
-                                       state,
-                                       indexEntryLimit,
-                                       cursorEntryLimit,
-                                       false,
-                                       env,
-                                       entryContainer);
-          approximateIndex.open();
-
-          if(!approximateIndex.isTrusted())
-          {
-            adminActionRequired = true;
-            messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
-                approximateIndex.getName()));
-          }
+          ApproximateIndexer indexer = new ApproximateIndexer(attrType);
+          Indexer extIndexer = new JEExtensibleIndexer(attrType, attrType.getApproximateMatchingRule(), indexer);
+          approximateIndex = openNewIndex(name, extIndexer, indexer, adminActionRequired, messages);
         }
         else
         {
           // already exists. Just update index entry limit.
           if(this.approximateIndex.setIndexEntryLimit(indexEntryLimit))
           {
-            adminActionRequired = true;
-
+            adminActionRequired.set(true);
             LocalizableMessage message =
                     NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                             approximateIndex.getName());
@@ -2053,13 +1791,6 @@
             entryContainer.deleteDatabase(approximateIndex);
             approximateIndex = null;
           }
-          catch(DatabaseException de)
-          {
-            messages.add(
-                    LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
-            return new ConfigChangeResult(
-                DirectoryServer.getServerErrorResultCode(), false, messages);
-          }
           finally
           {
             entryContainer.exclusiveLock.unlock();
@@ -2114,7 +1845,7 @@
 
               if(!extensibleIndex.isTrusted())
               {
-                adminActionRequired = true;
+                adminActionRequired.set(true);
                 messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(
                     extensibleIndex.getName()));
               }
@@ -2124,7 +1855,7 @@
               Index extensibleIndex = extensibleIndexes.getIndex(indexID);
               if(extensibleIndex.setIndexEntryLimit(indexEntryLimit))
               {
-                adminActionRequired = true;
+                adminActionRequired.set(true);
                 LocalizableMessage message =
                       NOTE_JEB_CONFIG_INDEX_ENTRY_LIMIT_REQUIRES_REBUILD.get(
                               extensibleIndex.getName());
@@ -2201,13 +1932,6 @@
               }
             }
           }
-          catch(DatabaseException de)
-          {
-            messages.add(
-                  LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
-            return new ConfigChangeResult(
-                DirectoryServer.getServerErrorResultCode(), false, messages);
-          }
           finally
           {
             entryContainer.exclusiveLock.unlock();
@@ -2228,13 +1952,6 @@
             }
             extensibleIndexes.deleteAll();
           }
-          catch(DatabaseException de)
-          {
-            messages.add(
-                  LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(de)));
-            return new ConfigChangeResult(
-                DirectoryServer.getServerErrorResultCode(), false, messages);
-          }
           finally
           {
             entryContainer.exclusiveLock.unlock();
@@ -2244,17 +1961,34 @@
 
       indexConfig = cfg;
 
-      return new ConfigChangeResult(ResultCode.SUCCESS, adminActionRequired,
-                                    messages);
+      return new ConfigChangeResult(
+          ResultCode.SUCCESS, adminActionRequired.get(), messages);
     }
     catch(Exception e)
     {
       messages.add(LocalizableMessage.raw(StaticUtils.stackTraceToSingleLineString(e)));
       return new ConfigChangeResult(
-          DirectoryServer.getServerErrorResultCode(), adminActionRequired, messages);
+          DirectoryServer.getServerErrorResultCode(), adminActionRequired.get(), messages);
     }
   }
 
+  private Index openNewIndex(String name, Indexer indexer, ExtensibleIndexer extIndexer,
+      AtomicBoolean adminActionRequired, ArrayList<LocalizableMessage> messages)
+  {
+    Index index = new Index(name + "." + extIndexer.getExtensibleIndexID(), indexer,
+        state, indexConfig.getIndexEntryLimit(), cursorEntryLimit, false, env,
+        entryContainer);
+    index.open();
+
+    if (!index.isTrusted())
+    {
+      adminActionRequired.set(true);
+      messages.add(NOTE_JEB_INDEX_ADD_REQUIRES_REBUILD.get(index
+          .getName()));
+    }
+    return index;
+  }
+
   /**
    * Set the index truststate.
    * @param txn A database transaction, or null if none is required.
@@ -2265,30 +1999,11 @@
   public synchronized void setTrusted(Transaction txn, boolean trusted)
       throws DatabaseException
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.setTrusted(txn, trusted);
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.setTrusted(txn, trusted);
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.setTrusted(txn, trusted);
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.setTrusted(txn, trusted);
-    }
-
-    if (approximateIndex != null)
-    {
-      approximateIndex.setTrusted(txn, trusted);
-    }
+    setTrusted(equalityIndex, txn, trusted);
+    setTrusted(presenceIndex, txn, trusted);
+    setTrusted(substringIndex, txn, trusted);
+    setTrusted(orderingIndex, txn, trusted);
+    setTrusted(approximateIndex, txn, trusted);
 
     if(extensibleIndexes!=null)
     {
@@ -2299,33 +2014,25 @@
     }
   }
 
+  private void setTrusted(Index index, Transaction txn, boolean trusted)
+  {
+    if (index != null)
+    {
+      index.setTrusted(txn, trusted);
+    }
+  }
+
   /**
    * Return true iff this index is trusted.
    * @return the trusted state of this index
    */
   public boolean isTrusted()
   {
-    if (equalityIndex != null && !equalityIndex.isTrusted())
-    {
-      return false;
-    }
-
-    if (presenceIndex != null && !presenceIndex.isTrusted())
-    {
-      return false;
-    }
-
-    if (substringIndex != null && !substringIndex.isTrusted())
-    {
-      return false;
-    }
-
-    if (orderingIndex != null && !orderingIndex.isTrusted())
-    {
-      return false;
-    }
-
-    if (approximateIndex != null && !approximateIndex.isTrusted())
+    if ((equalityIndex != null && !equalityIndex.isTrusted())
+        || (presenceIndex != null && !presenceIndex.isTrusted())
+        || (substringIndex != null && !substringIndex.isTrusted())
+        || (orderingIndex != null && !orderingIndex.isTrusted())
+        || (approximateIndex != null && !approximateIndex.isTrusted()))
     {
       return false;
     }
@@ -2351,30 +2058,11 @@
    */
   public synchronized void setRebuildStatus(boolean rebuildRunning)
   {
-    if (equalityIndex != null)
-    {
-      equalityIndex.setRebuildStatus(rebuildRunning);
-    }
-
-    if (presenceIndex != null)
-    {
-      presenceIndex.setRebuildStatus(rebuildRunning);
-    }
-
-    if (substringIndex != null)
-    {
-      substringIndex.setRebuildStatus(rebuildRunning);
-    }
-
-    if (orderingIndex != null)
-    {
-      orderingIndex.setRebuildStatus(rebuildRunning);
-    }
-
-    if (approximateIndex != null)
-    {
-      approximateIndex.setRebuildStatus(rebuildRunning);
-    }
+    setRebuildStatus(rebuildRunning, equalityIndex);
+    setRebuildStatus(rebuildRunning, presenceIndex);
+    setRebuildStatus(rebuildRunning, substringIndex);
+    setRebuildStatus(rebuildRunning, orderingIndex);
+    setRebuildStatus(rebuildRunning, approximateIndex);
 
     if(extensibleIndexes!=null)
     {
@@ -2385,6 +2073,14 @@
     }
   }
 
+  private void setRebuildStatus(boolean rebuildRunning, Index index)
+  {
+    if (index != null)
+    {
+      index.setRebuildStatus(rebuildRunning);
+    }
+  }
+
   /**
    * Get the JE database name prefix for indexes in this attribute index.
    *
@@ -2466,30 +2162,11 @@
   public Collection<Index> getAllIndexes() {
     LinkedHashSet<Index> indexes = new LinkedHashSet<Index>();
 
-    if (equalityIndex != null)
-    {
-      indexes.add(equalityIndex);
-    }
-
-    if (presenceIndex != null)
-    {
-      indexes.add(presenceIndex);
-    }
-
-    if (substringIndex != null)
-    {
-      indexes.add(substringIndex);
-    }
-
-    if (orderingIndex != null)
-    {
-      indexes.add(orderingIndex);
-    }
-
-    if (approximateIndex != null)
-    {
-      indexes.add(approximateIndex);
-    }
+    addIfNotNull(indexes, equalityIndex);
+    addIfNotNull(indexes, presenceIndex);
+    addIfNotNull(indexes, substringIndex);
+    addIfNotNull(indexes, orderingIndex);
+    addIfNotNull(indexes, approximateIndex);
 
     if(extensibleIndexes!=null)
     {

--
Gitblit v1.10.0