From caef6ed626aa6ab49fa569a61307d0febdc798b6 Mon Sep 17 00:00:00 2001
From: Jean-Noel Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Thu, 05 Dec 2013 09:50:44 +0000
Subject: [PATCH] Fixed a readWriteLock deadlock happening on calling ChangelogDB.removeDB() which then calls ReplicationDB.shutdown(). Code is blocked acquiring a writeLock on the dbCloseLock, but a readLock is never unlocked. Debugging showed that the ChangeNumberIndexDB is holding a cursor on a ReplicationDB, said cursor holds the readLock. The solution is to not try to call ReplicationDB.shutdown() in ReplicationServerDomain.shutdownDomain() because it will be closed by JEChangelogDB.shutdownDB().

---
 opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEChangelogDB.java        |   36 ++++--------------------------------
 opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEReplicaDBCursor.java    |    5 +++--
 opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ReplicationDomainDB.java |    8 --------
 opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java           |    3 ++-
 4 files changed, 9 insertions(+), 43 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
index 8349e18..e85f730 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/ReplicationServerDomain.java
@@ -45,6 +45,7 @@
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.loggers.debug.DebugTracer;
 import org.opends.server.replication.common.*;
+import org.opends.server.replication.plugin.MultimasterReplication;
 import org.opends.server.replication.protocol.*;
 import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.replication.server.changelog.api.DBCursor;
@@ -1720,7 +1721,7 @@
 
     stopAllServers(true);
 
-    domainDB.shutdownDomain(baseDN);
+    MultimasterReplication.deleteDomain(baseDN);
   }
 
   /**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ReplicationDomainDB.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ReplicationDomainDB.java
index b92dc07..786dc64 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ReplicationDomainDB.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/api/ReplicationDomainDB.java
@@ -84,14 +84,6 @@
   long getDomainLatestTrimDate(DN baseDN);
 
   /**
-   * Shutdown all the replica databases for the specified replication domain.
-   *
-   * @param baseDN
-   *          the replication domain baseDN
-   */
-  void shutdownDomain(DN baseDN);
-
-  /**
    * Removes all the data relating to the specified replication domain and
    * shutdown all its replica databases. In particular, it will:
    * <ol>
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEChangelogDB.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEChangelogDB.java
index a1ce54f..d5c78b3 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEChangelogDB.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEChangelogDB.java
@@ -397,7 +397,10 @@
       synchronized (domainMap)
       {
         it.remove();
-        innerShutdownDomain(domainMap);
+        for (JEReplicaDB replicaDB : domainMap.values())
+        {
+          replicaDB.shutdown();
+        }
       }
     }
 
@@ -513,37 +516,6 @@
 
   /** {@inheritDoc} */
   @Override
-  public void shutdownDomain(DN baseDN)
-  {
-    if (this.shutdown.get())
-    { // shutdown has already been initiated
-      return;
-    }
-
-    final Map<Integer, JEReplicaDB> domainMap = domainToReplicaDBs.get(baseDN);
-    if (domainMap != null)
-    {
-      synchronized (domainMap)
-      {
-        innerShutdownDomain(domainToReplicaDBs.remove(baseDN));
-      }
-    }
-  }
-
-  /**
-   * This method assumes the domainMap is synchronized by calling code and that
-   * the domainMap is not null.
-   */
-  private void innerShutdownDomain(final Map<Integer, JEReplicaDB> domainMap)
-  {
-    for (JEReplicaDB replicaDB : domainMap.values())
-    {
-      replicaDB.shutdown();
-    }
-  }
-
-  /** {@inheritDoc} */
-  @Override
   public ServerState getDomainOldestCSNs(DN baseDN)
   {
     final ServerState result = new ServerState();
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEReplicaDBCursor.java b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEReplicaDBCursor.java
index 4402947..d6a520b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEReplicaDBCursor.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/server/changelog/je/JEReplicaDBCursor.java
@@ -96,9 +96,10 @@
   @Override
   public boolean next() throws ChangelogException
   {
-    if (cursor != null)
+    final ReplServerDBCursor localCursor = cursor;
+    if (localCursor != null)
     {
-      currentChange = cursor.next();
+      currentChange = localCursor.next();
     }
     else
     {

--
Gitblit v1.10.0