From 0bd15da0682c55a6f3e3da8535fc2ce891488961 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.

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

diff --git a/opends/src/server/org/opends/server/core/GroupManager.java b/opends/src/server/org/opends/server/core/GroupManager.java
index d671282..c8b1141 100644
--- a/opends/src/server/org/opends/server/core/GroupManager.java
+++ b/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