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

Fabio Pistolesi
08.58.2015 71ee88697d285e8932a8dcab3ebc27c79387dd68
OPENDJ-2085 CR-7159 NullPointerException while importing data in an instance containing 2 backends

When using a temporary entry container for import, do not try to unregister it from its root container.
Also use the passed in transaction instead of a nested txn when renaming trees at the end of import.
4 files modified
99 ■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java 51 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeBufferImporter.java 17 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/OnDiskMergeStorageImporter.java 17 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/Suffix.java 14 ●●●●● patch | view | raw | blame | history
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);
    }
  }
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);
      }
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);
      }
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;