From 296090552c8bb9ad83cfa819fbf0bd9d0ba8fac2 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Mon, 18 Apr 2011 15:55:45 +0000
Subject: [PATCH] Fix OpenDJ-117: IllegalMonitorStateException during server shutdown

---
 opends/src/server/org/opends/server/replication/server/ServerHandler.java |  132 +++++++++++++++++++++----------------------
 1 files changed, 65 insertions(+), 67 deletions(-)

diff --git a/opends/src/server/org/opends/server/replication/server/ServerHandler.java b/opends/src/server/org/opends/server/replication/server/ServerHandler.java
index b00939a..c3e2b86 100644
--- a/opends/src/server/org/opends/server/replication/server/ServerHandler.java
+++ b/opends/src/server/org/opends/server/replication/server/ServerHandler.java
@@ -832,13 +832,20 @@
     return (!this.isDataServer());
   }
 
+
+
   /**
    * Lock the domain potentially with a timeout.
-   * @param timedout The provided timeout.
-   * @throws DirectoryException When an exception occurs.
+   *
+   * @param timedout
+   *          The provided timeout.
+   * @throws DirectoryException
+   *           When an exception occurs.
+   * @throws InterruptedException
+   *           If the current thread was interrupted while waiting for the lock.
    */
   protected void lockDomain(boolean timedout)
-  throws DirectoryException
+    throws DirectoryException, InterruptedException
   {
     // The handshake phase must be done by blocking any access to structures
     // keeping info on connected servers, so that one can safely check for
@@ -859,73 +866,64 @@
 
     // If domain already exists, lock it until handshake is finished otherwise
     // it will be created and locked later in the method
-    try
+    if (!timedout)
     {
-      if (!timedout)
-      {
-        // !timedout
-        if (!replicationServerDomain.hasLock())
-          replicationServerDomain.lock();
-      }
-      else
-      {
-        // timedout
-        /**
-         * Take the lock on the domain.
-         * WARNING: Here we try to acquire the lock with a timeout. This
-         * is for preventing a deadlock that may happen if there are cross
-         * connection attempts (for same domain) from this replication
-         * server and from a peer one:
-         * Here is the scenario:
-         * - RS1 connect thread takes the domain lock and starts
-         * connection to RS2
-         * - at the same time RS2 connect thread takes his domain lock and
-         * start connection to RS2
-         * - RS2 listen thread starts processing received
-         * ReplServerStartMsg from RS1 and wants to acquire the lock on
-         * the domain (here) but cannot as RS2 connect thread already has
-         * it
-         * - RS1 listen thread starts processing received
-         * ReplServerStartMsg from RS2 and wants to acquire the lock on
-         * the domain (here) but cannot as RS1 connect thread already has
-         * it
-         * => Deadlock: 4 threads are locked.
-         * So to prevent that in such situation, the listen threads here
-         * will both timeout trying to acquire the lock. The random time
-         * for the timeout should allow on connection attempt to be
-         * aborted whereas the other one should have time to finish in the
-         * same time.
-         * Warning: the minimum time (3s) should be big enough to allow
-         * normal situation connections to terminate. The added random
-         * time should represent a big enough range so that the chance to
-         * have one listen thread timing out a lot before the peer one is
-         * great. When the first listen thread times out, the remote
-         * connect thread should release the lock and allow the peer
-         * listen thread to take the lock it was waiting for and process
-         * the connection attempt.
-         */
-        Random random = new Random();
-        int randomTime = random.nextInt(6); // Random from 0 to 5
-        // Wait at least 3 seconds + (0 to 5 seconds)
-        long timeout = (long) (3000 + ( randomTime * 1000 ) );
-        boolean noTimeout = replicationServerDomain.tryLock(timeout);
-        if (!noTimeout)
-        {
-          // Timeout
-          Message message = WARN_TIMEOUT_WHEN_CROSS_CONNECTION.get(
-              getServiceId(),
-              serverId,
-              session.getReadableRemoteAddress(),
-              replicationServerId);
-          throw new DirectoryException(ResultCode.OTHER, message);
-        }
-      }
+      // !timedout
+      if (!replicationServerDomain.hasLock())
+        replicationServerDomain.lock();
     }
-    catch (InterruptedException e)
+    else
     {
-      // Thread interrupted
-      Message message = ERR_EXCEPTION_LOCKING_RS_DOMAIN.get(e.getMessage());
-      logError(message);
+      // timedout
+      /**
+       * Take the lock on the domain.
+       * WARNING: Here we try to acquire the lock with a timeout. This
+       * is for preventing a deadlock that may happen if there are cross
+       * connection attempts (for same domain) from this replication
+       * server and from a peer one:
+       * Here is the scenario:
+       * - RS1 connect thread takes the domain lock and starts
+       * connection to RS2
+       * - at the same time RS2 connect thread takes his domain lock and
+       * start connection to RS2
+       * - RS2 listen thread starts processing received
+       * ReplServerStartMsg from RS1 and wants to acquire the lock on
+       * the domain (here) but cannot as RS2 connect thread already has
+       * it
+       * - RS1 listen thread starts processing received
+       * ReplServerStartMsg from RS2 and wants to acquire the lock on
+       * the domain (here) but cannot as RS1 connect thread already has
+       * it
+       * => Deadlock: 4 threads are locked.
+       * So to prevent that in such situation, the listen threads here
+       * will both timeout trying to acquire the lock. The random time
+       * for the timeout should allow on connection attempt to be
+       * aborted whereas the other one should have time to finish in the
+       * same time.
+       * Warning: the minimum time (3s) should be big enough to allow
+       * normal situation connections to terminate. The added random
+       * time should represent a big enough range so that the chance to
+       * have one listen thread timing out a lot before the peer one is
+       * great. When the first listen thread times out, the remote
+       * connect thread should release the lock and allow the peer
+       * listen thread to take the lock it was waiting for and process
+       * the connection attempt.
+       */
+      Random random = new Random();
+      int randomTime = random.nextInt(6); // Random from 0 to 5
+      // Wait at least 3 seconds + (0 to 5 seconds)
+      long timeout = (long) (3000 + ( randomTime * 1000 ) );
+      boolean noTimeout = replicationServerDomain.tryLock(timeout);
+      if (!noTimeout)
+      {
+        // Timeout
+        Message message = WARN_TIMEOUT_WHEN_CROSS_CONNECTION.get(
+            getServiceId(),
+            serverId,
+            session.getReadableRemoteAddress(),
+            replicationServerId);
+        throw new DirectoryException(ResultCode.OTHER, message);
+      }
     }
   }
 

--
Gitblit v1.10.0