From 71ee88697d285e8932a8dcab3ebc27c79387dd68 Mon Sep 17 00:00:00 2001
From: Fabio Pistolesi <fabio.pistolesi@forgerock.com>
Date: Mon, 08 Jun 2015 07:58:39 +0000
Subject: [PATCH] OPENDJ-2085 CR-7159 NullPointerException while importing data in an instance containing 2 backends

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Suffix.java                     |   14 ++++++
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java             |   51 ++++++++-----------------
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeStorageImporter.java |   17 +++++---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeBufferImporter.java  |   17 +++++---
 4 files changed, 52 insertions(+), 47 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
index 32eda1c..029d139 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
@@ -2638,28 +2638,22 @@
    * Sets a new tree prefix for this entry container and rename all
    * existing trees in use by this entry container.
    *
+   * @param txn the transaction for renaming Trees
    * @param newBaseDN The new tree prefix to use.
    * @throws StorageRuntimeException If an error occurs in the storage.
    */
-  void setTreePrefix(final String newBaseDN) throws StorageRuntimeException
+  void setTreePrefix(WriteableTransaction txn, final String newBaseDN) throws StorageRuntimeException
   {
     final List<Tree> allTrees = listTrees();
     try
     {
       // Rename in transaction.
-      storage.write(new WriteOperation()
+      for(Tree tree : allTrees)
       {
-        @Override
-        public void run(WriteableTransaction txn) throws Exception
-        {
-          for(Tree tree : allTrees)
-          {
-            TreeName oldName = tree.getName();
-            TreeName newName = oldName.replaceBaseDN(newBaseDN);
-            txn.renameTree(oldName, newName);
-          }
-        }
-      });
+        TreeName oldName = tree.getName();
+        TreeName newName = oldName.replaceBaseDN(newBaseDN);
+        txn.renameTree(oldName, newName);
+      }
       // Only rename the containers if the txn succeeded.
       for (Tree tree : allTrees)
       {
@@ -2677,32 +2671,21 @@
       }
       throw new StorageRuntimeException(ERR_UNCHECKED_EXCEPTION.get(msg).toString(), e);
     }
-    finally
+    try
     {
-      try
+      for(Tree tree : allTrees)
       {
-        storage.write(new WriteOperation()
-        {
-          @Override
-          public void run(WriteableTransaction txn) throws Exception
-          {
-            // Open the containers backup.
-            for(Tree tree : allTrees)
-            {
-              tree.open(txn);
-            }
-          }
-        });
+        tree.open(txn);
       }
-      catch (Exception e)
+    }
+    catch (Exception e)
+    {
+      String msg = e.getMessage();
+      if (msg == null)
       {
-        String msg = e.getMessage();
-        if (msg == null)
-        {
-          msg = stackTraceToSingleLineString(e);
-        }
-        throw new StorageRuntimeException(ERR_UNCHECKED_EXCEPTION.get(msg).toString(), e);
+        msg = stackTraceToSingleLineString(e);
       }
+      throw new StorageRuntimeException(ERR_UNCHECKED_EXCEPTION.get(msg).toString(), e);
     }
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeBufferImporter.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeBufferImporter.java
index 3ecf080..c671611 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeBufferImporter.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeBufferImporter.java
@@ -696,7 +696,11 @@
         sourceEntryContainer = entryContainer;
 
         // Create a temp entry container
-        DN tempDN = baseDN.child(DN.valueOf("dc=importTmp"));
+        DN tempDN = DN.valueOf(baseDN.rdn() + "_importTmp");
+        if (baseDN.size() > 1)
+        {
+          tempDN = baseDN.parent().child(tempDN);
+        }
         entryContainer = rootContainer.openEntryContainer(tempDN, txn);
       }
     }
@@ -916,11 +920,12 @@
   {
     for (Suffix suffix : dnSuffixMap.values())
     {
-      DN baseDN = suffix.getBaseDN();
-      EntryContainer entryContainer = suffix.getSrcEntryContainer();
-      if (entryContainer != null)
+      final EntryContainer toDelete = suffix.getSrcEntryContainer();
+      if (toDelete != null)
       {
-        final EntryContainer toDelete = rootContainer.unregisterEntryContainer(baseDN);
+        final DN baseDN = toDelete.getBaseDN();
+
+        rootContainer.unregisterEntryContainer(baseDN);
         toDelete.lock();
         toDelete.close();
         toDelete.delete(txn);
@@ -928,7 +933,7 @@
 
         final EntryContainer replacement = suffix.getEntryContainer();
         replacement.lock();
-        replacement.setTreePrefix(baseDN.toNormalizedUrlSafeString());
+        replacement.setTreePrefix(txn, baseDN.toNormalizedUrlSafeString());
         replacement.unlock();
         rootContainer.registerEntryContainer(baseDN, replacement);
       }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeStorageImporter.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeStorageImporter.java
index 85df3ff..66bf17a 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeStorageImporter.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeStorageImporter.java
@@ -1470,7 +1470,11 @@
         sourceEntryContainer = entryContainer;
 
         // Create a temp entry container
-        DN tempDN = baseDN.child(DN.valueOf("dc=importTmp"));
+        DN tempDN = DN.valueOf(baseDN.rdn() + "_importTmp");
+        if (baseDN.size() > 1)
+        {
+          tempDN = baseDN.parent().child(tempDN);
+        }
         entryContainer = rootContainer.openEntryContainer(tempDN, txn);
       }
     }
@@ -1605,11 +1609,12 @@
   {
     for (Suffix suffix : dnSuffixMap.values())
     {
-      DN baseDN = suffix.getBaseDN();
-      EntryContainer entryContainer = suffix.getSrcEntryContainer();
-      if (entryContainer != null)
+      final EntryContainer toDelete = suffix.getSrcEntryContainer();
+      if (toDelete != null)
       {
-        final EntryContainer toDelete = rootContainer.unregisterEntryContainer(baseDN);
+        final DN baseDN = toDelete.getBaseDN();
+
+        rootContainer.unregisterEntryContainer(baseDN);
         toDelete.lock();
         toDelete.close();
         toDelete.delete(txn);
@@ -1617,7 +1622,7 @@
 
         final EntryContainer replacement = suffix.getEntryContainer();
         replacement.lock();
-        replacement.setTreePrefix(baseDN.toNormalizedUrlSafeString());
+        replacement.setTreePrefix(txn, baseDN.toNormalizedUrlSafeString());
         replacement.unlock();
         rootContainer.registerEntryContainer(baseDN, replacement);
       }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Suffix.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Suffix.java
index 3ec0521..42b2539 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Suffix.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Suffix.java
@@ -53,7 +53,19 @@
 
   private final List<DN> includeBranches, excludeBranches;
   private final DN baseDN;
+ /**
+  * If not null this is the original entry container for the suffix in the backend before the
+  * import begins.
+  * <p>
+  * Then its data is completely deleted only at the very end of the import when calling
+  * *Importer.switchEntryContainers().
+  */
   private final EntryContainer srcEntryContainer;
+  /**
+   * If {@link #srcEntryContainer} is null, it is the original entry container for the suffix in the
+   * backend. Otherwise it is a temporary entry container that will eventually replace the existing
+   * {@link #srcEntryContainer} at the end of the import.
+   */
   private final EntryContainer entryContainer;
   private final Object synchObject = new Object();
   private static final int PARENT_ID_SET_SIZE = 16 * 1024;
@@ -78,7 +90,7 @@
   {
     this.entryContainer = entryContainer;
     this.srcEntryContainer = srcEntryContainer;
-    this.baseDN = entryContainer.getBaseDN();
+    this.baseDN = srcEntryContainer != null ? srcEntryContainer.getBaseDN() : entryContainer.getBaseDN();
     if (includeBranches != null)
     {
       this.includeBranches = includeBranches;

--
Gitblit v1.10.0