From 955476b2dd08a2d90413008c658b3dacba8f0899 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Tue, 22 Apr 2008 22:33:23 +0000
Subject: [PATCH] Fixed an issue where deadlocks could occur in the LockManager when the server is in heavy add/mod load. An add operation takes a read lock on the parent DN and a write lock on the target DN in that order. However, mod operations first takes an write lock on the target DN then inadvertantly tries takes an read lock on the parent DN through the entryExists method. This could cause a deadlock in the following case with the fair ordering reentrant read write lock:

---
 opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java |   80 ++++++++++++++++-----------------------
 1 files changed, 33 insertions(+), 47 deletions(-)

diff --git a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
index f172c3d..a9eb1e6 100644
--- a/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
+++ b/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendModifyOperation.java
@@ -399,7 +399,39 @@
         try
         {
           // Get the entry to modify.  If it does not exist, then fail.
-          getEntryToModify();
+          currentEntry = backend.getEntry(entryDN);
+
+          if (currentEntry == null)
+          {
+            setResultCode(ResultCode.NO_SUCH_OBJECT);
+            appendErrorMessage(ERR_MODIFY_NO_SUCH_ENTRY.get(
+                String.valueOf(entryDN)));
+
+            // See if one of the entry's ancestors exists.
+            try
+            {
+              DN parentDN = entryDN.getParentDNInSuffix();
+              while (parentDN != null)
+              {
+                if (DirectoryServer.entryExists(parentDN))
+                {
+                  setMatchedDN(parentDN);
+                  break;
+                }
+
+                parentDN = parentDN.getParentDNInSuffix();
+              }
+            }
+            catch (Exception e)
+            {
+              if (debugEnabled())
+              {
+                TRACER.debugCaught(DebugLogLevel.ERROR, e);
+              }
+            }
+
+            break modifyProcessing;
+          }
 
           // Check to see if there are any controls in the request.  If so, then
           // see if there is any special processing required.
@@ -746,52 +778,6 @@
 
 
   /**
-   * Gets the entry to modify.
-   *
-   *
-   * @throws  DirectoryException  If a problem occurs while trying to get the
-   *                              entry, or if the entry doesn't exist.
-   */
-  private void getEntryToModify()
-          throws DirectoryException
-  {
-    currentEntry = backend.getEntry(entryDN);
-    if (currentEntry == null)
-    {
-      // See if one of the entry's ancestors exists.
-      DN matchedDN = null;
-      DN parentDN = entryDN.getParentDNInSuffix();
-      while (parentDN != null)
-      {
-        try
-        {
-          if (DirectoryServer.entryExists(parentDN))
-          {
-            matchedDN = parentDN;
-            break;
-          }
-        }
-        catch (Exception e)
-        {
-          if (debugEnabled())
-          {
-            TRACER.debugCaught(DebugLogLevel.ERROR, e);
-          }
-          break;
-        }
-
-        parentDN = parentDN.getParentDNInSuffix();
-      }
-
-      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT,
-                     ERR_MODIFY_NO_SUCH_ENTRY.get(String.valueOf(entryDN)),
-                     matchedDN, null);
-    }
-  }
-
-
-
-  /**
    * Processes any controls contained in the modify request.
    *
    * @throws  DirectoryException  If a problem is encountered with any of the

--
Gitblit v1.10.0