From e0c5050174a92d35a4bd947515666e3b1bde252a Mon Sep 17 00:00:00 2001
From: Ludovic Poitou <ludovic.poitou@forgerock.com>
Date: Tue, 01 Oct 2013 13:59:28 +0000
Subject: [PATCH] Fix for OPENDJ-1160 : Write operations to non-groups force groups to be reloaded. The refreshToken was updated on each add/mod/delete regardless of the type of entry, causing intensive contention on group membership evaluation. Changes include reduction of the critical section as well as moving the update of refreshToken only when groups are modified. CR-2400, thanks to the nice reviewers.

---
 opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java |   42 +++++++++++++++++++++++++++---------------
 1 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java b/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java
index d671282..c8b1141 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/core/GroupManager.java
@@ -124,7 +124,8 @@
 
   // A mapping between the DNs of all group entries and the corresponding
   // group instances.
-  private DITCacheMap<Group> groupInstances;
+  private DITCacheMap<Group>
+      groupInstances;
 
   // Lock to protect internal data structures.
   private final ReentrantReadWriteLock lock;
@@ -767,16 +768,7 @@
         }
       }
     }
-    lock.writeLock().lock();
-    try
-    {
-      createAndRegisterGroup(entry);
-      refreshToken++;
-    }
-    finally
-    {
-      lock.writeLock().unlock();
-    }
+    createAndRegisterGroup(entry);
   }
 
 
@@ -802,8 +794,10 @@
     lock.writeLock().lock();
     try
     {
-      groupInstances.removeSubtree(entry.getDN(), null);
-      refreshToken++;
+      if (groupInstances.removeSubtree(entry.getDN(), null))
+      {
+        refreshToken++;
+      }
     }
     finally
     {
@@ -834,6 +828,21 @@
       }
     }
 
+    lock.readLock().lock();
+    try
+    {
+      if (!groupInstances.containsKey(oldEntry.getDN()))
+      {
+        // If the modified entry is not in any group instance, it's probably
+        // not a group, exit fast
+        return;
+      }
+    }
+    finally
+    {
+      lock.readLock().unlock();
+    }
+
     lock.writeLock().lock();
     try
     {
@@ -845,7 +854,6 @@
           groupInstances.remove(oldEntry.getDN());
         }
         createAndRegisterGroup(newEntry);
-        refreshToken++;
       }
     }
     finally
@@ -911,7 +919,10 @@
         group.setGroupDN(groupDN);
         groupInstances.put(groupDN, group);
       }
-      refreshToken++;
+      if (!groupSet.isEmpty())
+      {
+        refreshToken++;
+      }
     }
     finally
     {
@@ -1078,6 +1089,7 @@
           try
           {
             groupInstances.put(entry.getDN(), groupInstance);
+            refreshToken++;
           }
           finally
           {

--
Gitblit v1.10.0