From d0fe5d05f13134bae430b3ffd60abd4cbe85c964 Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <ylecaillez@forgerock.com>
Date: Thu, 15 Oct 2015 15:15:18 +0000
Subject: [PATCH] OPENDJ-2321: Name of rebuilt index has changed in rebuild-index output.

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java |  152 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 122 insertions(+), 30 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java
index 0c96c4d..c91e81f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java
@@ -90,6 +90,8 @@
 import org.forgerock.opendj.ldap.ByteSequence;
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.forgerock.opendj.ldap.schema.MatchingRule;
+import org.forgerock.opendj.ldap.spi.Indexer;
 import org.forgerock.util.Reject;
 import org.forgerock.util.Utils;
 import org.forgerock.util.promise.PromiseImpl;
@@ -317,17 +319,12 @@
         logger.info(NOTE_REBUILD_DEGRADED_START, totalEntries);
         break;
       case USER_DEFINED:
-        visitIndexes(entryContainer, visitOnlyAttributesOrIndexes(rebuildConfig.getRebuildList(), selector));
-        final Set<String> indexesToRebuild = selector.getSelectedIndexNames();
-        if (!indexesToRebuild.containsAll(rebuildConfig.getRebuildList()))
-        {
-          final Set<String> unknownIndexes = new HashSet<>(rebuildConfig.getRebuildList());
-          unknownIndexes.removeAll(indexesToRebuild);
-          throw new InitializationException(ERR_ATTRIBUTE_INDEX_NOT_CONFIGURED.get(unknownIndexes.iterator().next()));
-        }
+        // User defined format is attributeType(.indexType)
+        visitIndexes(entryContainer,
+            visitOnlyIndexes(buildUserDefinedIndexNames(entryContainer, rebuildConfig.getRebuildList()), selector));
         if (!rebuildConfig.isClearDegradedState())
         {
-          logger.info(NOTE_REBUILD_START, Utils.joinAsString(", ", selector.getSelectedIndexNames()), totalEntries);
+          logger.info(NOTE_REBUILD_START, Utils.joinAsString(", ", rebuildConfig.getRebuildList()), totalEntries);
         }
         break;
       default:
@@ -342,6 +339,110 @@
       return selector.getSelectedIndexNames();
     }
 
+    /**
+     * Translate attributeType(.indexType|matchingRuleOid) into attributeType.matchingRuleOid index name.
+     *
+     * @throws InitializationException
+     *           if rebuildList contains an invalid/non-existing attribute/index name.
+     **/
+    private static final Set<String> buildUserDefinedIndexNames(EntryContainer entryContainer,
+        Collection<String> rebuildList) throws InitializationException
+    {
+      final Set<String> indexNames = new HashSet<>();
+      for (String name : rebuildList)
+      {
+        final String parts[] = name.split("\\.");
+        final AttributeIndex attribute = findAttribute(entryContainer, parts[0]);
+        if (parts.length == 1)
+        {
+          // Add all indexes of this attribute
+          for (Tree index : attribute.getNameToIndexes().values())
+          {
+            indexNames.add(index.getName().getIndexId());
+          }
+        }
+        else if (parts.length == 2)
+        {
+          // First, assume the supplied name is a valid index name.
+          final SelectIndexName selector = new SelectIndexName();
+          visitIndexes(entryContainer, visitOnlyIndexes(Arrays.asList(name), selector));
+          indexNames.addAll(selector.getSelectedIndexNames());
+          if (selector.getSelectedIndexNames().isEmpty())
+          {
+            // ... if not, assume the supplied name identify an attributeType.indexType
+            try
+            {
+              indexNames.addAll(getIndexNames(IndexType.valueOf(parts[1].toUpperCase()), attribute));
+            }
+            catch (IllegalArgumentException e)
+            {
+              throw new InitializationException(ERR_ATTRIBUTE_INDEX_NOT_CONFIGURED.get(name), e);
+            }
+          }
+        }
+        else
+        {
+          throw new InitializationException(ERR_ATTRIBUTE_INDEX_NOT_CONFIGURED.get(name));
+        }
+      }
+      return indexNames;
+    }
+
+    private static final AttributeIndex findAttribute(EntryContainer entryContainer, String name)
+        throws InitializationException
+    {
+      for (AttributeIndex index : entryContainer.getAttributeIndexes())
+      {
+        if (index.getAttributeType().getNameOrOID().equalsIgnoreCase(name))
+        {
+          return index;
+        }
+      }
+      throw new InitializationException(ERR_ATTRIBUTE_INDEX_NOT_CONFIGURED.get(name));
+    }
+
+    private static Collection<String> getIndexNames(IndexType indexType, AttributeIndex attrIndex)
+    {
+      final Map<String, MatchingRuleIndex> indexes = attrIndex.getNameToIndexes();
+
+      final AttributeType attrType = attrIndex.getAttributeType();
+      final MatchingRule rule;
+      switch (indexType)
+      {
+      case PRESENCE:
+        return Collections.singletonList(IndexType.PRESENCE.toString());
+      case APPROXIMATE:
+        rule = attrType.getApproximateMatchingRule();
+        break;
+      case EQUALITY:
+        rule = attrType.getEqualityMatchingRule();
+        break;
+      case ORDERING:
+        rule = attrType.getOrderingMatchingRule();
+        break;
+      case SUBSTRING:
+        rule = attrType.getSubstringMatchingRule();
+        break;
+      default:
+        throw new IllegalArgumentException("Not implemented for index type " + indexType);
+      }
+      if (rule == null)
+      {
+        throw new IllegalArgumentException("No matching rule for index type " + indexType);
+      }
+      final Set<String> indexNames = new HashSet<>();
+      for (Indexer indexer : rule.createIndexers(attrIndex.getIndexingOptions()))
+      {
+        final Tree indexTree = attrIndex.getNameToIndexes().get(indexer.getIndexID());
+        if (indexTree == null)
+        {
+          throw new IllegalArgumentException("No index found for type " + indexType);
+        }
+        indexNames.add(indexTree.getName().getIndexId());
+      }
+      return indexNames;
+    }
+
     private static File prepareTempDir(PluggableBackendCfg backendCfg, String tmpDirectory)
         throws InitializationException
     {
@@ -3246,7 +3347,7 @@
     {
       for (MatchingRuleIndex index : attribute.getNameToIndexes().values())
       {
-        visitor.visitAttributeIndex(attribute.getAttributeType(), index);
+        visitor.visitAttributeIndex(index);
         nbVisited++;
       }
     }
@@ -3265,7 +3366,7 @@
   /** Visitor pattern allowing to process all type of indexes. */
   private interface IndexVisitor
   {
-    void visitAttributeIndex(AttributeType attribute, DefaultIndex index);
+    void visitAttributeIndex(DefaultIndex index);
 
     void visitVLVIndex(VLVIndex index);
 
@@ -3290,7 +3391,7 @@
     }
 
     @Override
-    public void visitAttributeIndex(AttributeType attribute, DefaultIndex index)
+    public void visitAttributeIndex(DefaultIndex index)
     {
       index.setTrusted(txn, trustValue);
     }
@@ -3324,7 +3425,7 @@
     }
 
     @Override
-    public void visitAttributeIndex(AttributeType attribute, DefaultIndex index)
+    public void visitAttributeIndex(DefaultIndex index)
     {
       clearTree(index);
     }
@@ -3363,11 +3464,11 @@
     }
 
     @Override
-    public void visitAttributeIndex(AttributeType attribute, DefaultIndex index)
+    public void visitAttributeIndex(DefaultIndex index)
     {
       if (!index.isTrusted())
       {
-        delegate.visitAttributeIndex(attribute, index);
+        delegate.visitAttributeIndex(index);
       }
     }
 
@@ -3403,7 +3504,7 @@
     }
 
     @Override
-    public void visitAttributeIndex(AttributeType attribute, DefaultIndex index)
+    public void visitAttributeIndex(DefaultIndex index)
     {
       addIndex(index);
     }
@@ -3428,13 +3529,7 @@
 
   private static final IndexVisitor visitOnlyIndexes(Collection<String> indexNames, IndexVisitor delegate)
   {
-    return new SpecificIndexFilter(delegate, indexNames, false);
-  }
-
-  private static final IndexVisitor visitOnlyAttributesOrIndexes(Collection<String> indexOrAttributeNames,
-      IndexVisitor delegate)
-  {
-    return new SpecificIndexFilter(delegate, indexOrAttributeNames, true);
+    return new SpecificIndexFilter(delegate, indexNames);
   }
 
   /** Visit indexes only if their name match one contained in a list. */
@@ -3442,12 +3537,10 @@
   {
     private final IndexVisitor delegate;
     private final Collection<String> indexNames;
-    private final boolean includeAttributeNames;
 
-    SpecificIndexFilter(IndexVisitor delegate, Collection<String> names, boolean includeAttributeNames)
+    SpecificIndexFilter(IndexVisitor delegate, Collection<String> names)
     {
       this.delegate = delegate;
-      this.includeAttributeNames = includeAttributeNames;
       this.indexNames = new HashSet<>(names.size());
       for(String indexName : names)
       {
@@ -3456,12 +3549,11 @@
     }
 
     @Override
-    public void visitAttributeIndex(AttributeType attribute, DefaultIndex index)
+    public void visitAttributeIndex(DefaultIndex index)
     {
-      if (indexIncluded(index)
-          || (includeAttributeNames && indexNames.contains(attribute.getNameOrOID().toLowerCase())))
+      if (indexIncluded(index))
       {
-        delegate.visitAttributeIndex(attribute, index);
+        delegate.visitAttributeIndex(index);
       }
     }
 

--
Gitblit v1.10.0