From 4e47cc1e8ce6f654769127249a363cf0e9a64eec Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <ylecaillez@forgerock.com>
Date: Fri, 16 Oct 2015 15:14:57 +0000
Subject: [PATCH] OPENDJ-2361: rebuild-index ClearDegradedState option online mode generates an error.

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeImporter.java |   98 +++++++++++++++++++++++++++++++------------------
 1 files changed, 62 insertions(+), 36 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 13f762c..8c491f8 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
@@ -106,11 +106,13 @@
 import org.opends.server.backends.pluggable.OnDiskMergeImporter.ExternalSortChunk.InMemorySortedChunk;
 import org.opends.server.backends.pluggable.spi.Cursor;
 import org.opends.server.backends.pluggable.spi.Importer;
+import org.opends.server.backends.pluggable.spi.ReadOperation;
 import org.opends.server.backends.pluggable.spi.ReadableTransaction;
 import org.opends.server.backends.pluggable.spi.SequentialCursor;
 import org.opends.server.backends.pluggable.spi.StorageRuntimeException;
 import org.opends.server.backends.pluggable.spi.TreeName;
 import org.opends.server.backends.pluggable.spi.UpdateFunction;
+import org.opends.server.backends.pluggable.spi.WriteOperation;
 import org.opends.server.backends.pluggable.spi.WriteableTransaction;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ServerContext;
@@ -252,45 +254,64 @@
     @Override
     public void rebuildIndex(final RebuildConfig rebuildConfig) throws Exception
     {
-      final long availableMemory = calculateAvailableMemory();
+      final EntryContainer entryContainer = rootContainer.getEntryContainer(rebuildConfig.getBaseDN());
+      final long totalEntries = rootContainer.getStorage().read(new ReadOperation<Long>()
+      {
+        @Override
+        public Long run(ReadableTransaction txn) throws Exception
+        {
+          return entryContainer.getID2Entry().getRecordCount(txn);
+        }
+      });
 
-      // Rebuild indexes
-      final OnDiskMergeImporter importer;
+      final Set<String> indexesToRebuild = selectIndexesToRebuild(entryContainer, rebuildConfig, totalEntries);
+      if (rebuildConfig.isClearDegradedState())
+      {
+        clearDegradedState(entryContainer, indexesToRebuild);
+        logger.info(NOTE_REBUILD_CLEARDEGRADEDSTATE_FINAL_STATUS, rebuildConfig.getRebuildList());
+      }
+      else
+      {
+        rebuildIndex(entryContainer, rebuildConfig.getTmpDirectory(), indexesToRebuild, totalEntries);
+      }
+    }
+
+    private void clearDegradedState(final EntryContainer entryContainer, final Set<String> indexes) throws Exception
+    {
+      rootContainer.getStorage().write(new WriteOperation()
+      {
+        @Override
+        public void run(WriteableTransaction txn) throws Exception
+        {
+          visitIndexes(entryContainer, visitOnlyIndexes(indexes, setTrust(true, txn)));
+        }
+      });
+    }
+
+    private void rebuildIndex(EntryContainer entryContainer, String tmpDirectory, Set<String> indexesToRebuild,
+        long totalEntries) throws Exception
+    {
+      rootContainer.getStorage().close();
+      final long availableMemory = calculateAvailableMemory();
+      final int threadCount = Runtime.getRuntime().availableProcessors();
+      final int nbBuffer = 2 * indexesToRebuild.size() * threadCount;
+      final int bufferSize = computeBufferSize(nbBuffer, availableMemory);
+      final File tempDir = prepareTempDir(backendCfg, tmpDirectory);
+
       final ExecutorService sorter = Executors.newFixedThreadPool(
           Runtime.getRuntime().availableProcessors(),
           newThreadFactory(null, SORTER_THREAD_NAME, true));
-      try (final Importer dbStorage = rootContainer.getStorage().startImport())
+
+      final OnDiskMergeImporter importer;
+      try (final Importer dbStorage = rootContainer.getStorage().startImport();
+           final BufferPool bufferPool = new BufferPool(nbBuffer, bufferSize))
       {
-        final EntryContainer entryContainer = rootContainer.getEntryContainer(rebuildConfig.getBaseDN());
-        final long totalEntries = entryContainer.getID2Entry().getRecordCount(asWriteableTransaction(dbStorage));
-        final Set<String> indexesToRebuild = selectIndexesToRebuild(entryContainer, rebuildConfig, totalEntries);
-        if (rebuildConfig.isClearDegradedState())
-        {
-          visitIndexes(entryContainer, visitOnlyIndexes(indexesToRebuild, setTrust(true, dbStorage)));
-          logger.info(NOTE_REBUILD_CLEARDEGRADEDSTATE_FINAL_STATUS, indexesToRebuild);
-          return;
-        }
+        final AbstractTwoPhaseImportStrategy strategy = new RebuildIndexStrategy(
+            rootContainer.getEntryContainers(), dbStorage, tempDir, bufferPool, sorter, indexesToRebuild);
 
-        if (indexesToRebuild.isEmpty())
-        {
-          // Early exit in case there is no index to rebuild.
-          return;
-        }
-
-        final int threadCount = Runtime.getRuntime().availableProcessors();
-        final int nbBuffer = 2 * indexesToRebuild.size() * threadCount;
-        final int bufferSize = computeBufferSize(nbBuffer, availableMemory);
-        try (final BufferPool bufferPool = new BufferPool(nbBuffer, bufferSize))
-        {
-          final File tempDir = prepareTempDir(backendCfg, rebuildConfig.getTmpDirectory());
-          final AbstractTwoPhaseImportStrategy strategy =
-              new RebuildIndexStrategy(rootContainer.getEntryContainers(), dbStorage, tempDir, bufferPool, sorter,
-                  indexesToRebuild);
-
-          importer = new OnDiskMergeImporter(PHASE2_REBUILDER_THREAD_NAME, strategy);
-          importer.doImport(
-              new ID2EntrySource(entryContainer, dbStorage, PHASE1_REBUILDER_THREAD_NAME, threadCount, totalEntries));
-        }
+        importer = new OnDiskMergeImporter(PHASE2_REBUILDER_THREAD_NAME, strategy);
+        importer.doImport(
+            new ID2EntrySource(entryContainer, dbStorage, PHASE1_REBUILDER_THREAD_NAME, threadCount, totalEntries));
       }
       finally
       {
@@ -3356,7 +3377,12 @@
 
   private static final IndexVisitor setTrust(boolean trustValue, Importer importer)
   {
-    return new TrustModifier(importer, trustValue);
+    return setTrust(trustValue, asWriteableTransaction(importer));
+  }
+
+  private static final IndexVisitor setTrust(boolean trustValue, WriteableTransaction txn)
+  {
+    return new TrustModifier(txn, trustValue);
   }
 
   /** Update the trust state of the visited indexes. */
@@ -3365,9 +3391,9 @@
     private final WriteableTransaction txn;
     private final boolean trustValue;
 
-    TrustModifier(Importer importer, boolean trustValue)
+    TrustModifier(WriteableTransaction txn, boolean trustValue)
     {
-      this.txn = asWriteableTransaction(importer);
+      this.txn = txn;
       this.trustValue = trustValue;
     }
 

--
Gitblit v1.10.0