I don't see the need of locking in methods like "public boolean
hasSubentry(...)". What's the benefit of locking?
A normal use case is IMO that some time after calling the has... method
one will either read or write the cache. But there's no garantee, that
when now read/write the cache is still in the same state as when calling
the has... method. So isn't it just a waste of time to lock in this case?
Curious Felix
On 01/11/2011 04:57 PM, [email protected] wrote:
Author: elecharny
Date: Tue Jan 11 15:57:56 2011
New Revision: 1057707
URL: http://svn.apache.org/viewvc?rev=1057707&view=rev
Log:
Added synchronization around the cache
Modified:
directory/apacheds/branches/apacheds-AP/core-api/src/main/java/org/apache/directory/server/core/administrative/SubentryCache.java
Modified:
directory/apacheds/branches/apacheds-AP/core-api/src/main/java/org/apache/directory/server/core/administrative/SubentryCache.java
URL:
http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-AP/core-api/src/main/java/org/apache/directory/server/core/administrative/SubentryCache.java?rev=1057707&r1=1057706&r2=1057707&view=diff
==============================================================================
---
directory/apacheds/branches/apacheds-AP/core-api/src/main/java/org/apache/directory/server/core/administrative/SubentryCache.java
(original)
+++
directory/apacheds/branches/apacheds-AP/core-api/src/main/java/org/apache/directory/server/core/administrative/SubentryCache.java
Tue Jan 11 15:57:56 2011
@@ -23,6 +23,7 @@ package org.apache.directory.server.core
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.directory.shared.ldap.exception.LdapException;
import org.apache.directory.shared.ldap.name.DN;
@@ -44,6 +45,49 @@ public class SubentryCache implements It
/** The Subentry DN cache */
private final DnNode<Subentry[]> dnCache;
+ /** A lock to guarantee the Subentry cache consistency */
+ private ReentrantReadWriteLock mutex = new ReentrantReadWriteLock();
+
+ /**
+ * Get a read-lock on the Subentry cache.
+ * No read operation can be done on the AP cache if this
+ * method is not called before.
+ */
+ public void lockRead()
+ {
+ mutex.readLock().lock();
+ }
+
+
+ /**
+ * Get a write-lock on the Subentry cache.
+ * No write operation can be done on the apCache if this
+ * method is not called before.
+ */
+ public void lockWrite()
+ {
+ mutex.writeLock().lock();
+ }
+
+
+ /**
+ * Release the read-write lock on the AP cache.
+ * This method must be called after having read or modified the
+ * AP cache
+ */
+ public void unlock()
+ {
+ if ( mutex.isWriteLockedByCurrentThread() )
+ {
+ mutex.writeLock().unlock();
+ }
+ else
+ {
+ mutex.readLock().unlock();
+ }
+ }
+
+
/**
* Creates a new instance of SubentryCache with a default maximum size.
*/
@@ -63,10 +107,18 @@ public class SubentryCache implements It
*/
public final Subentry getSubentry( String uuid, AdministrativeRoleEnum
role )
{
- Subentry[] subentries = uuidCache.get( uuid );
- Subentry subentry = subentries[role.getValue()];
-
- return subentry;
+ try
+ {
+ lockRead();
+ Subentry[] subentries = uuidCache.get( uuid );
+ Subentry subentry = subentries[role.getValue()];
+
+ return subentry;
+ }
+ finally
+ {
+ unlock();
+ }
}
@@ -78,9 +130,17 @@ public class SubentryCache implements It
*/
public final Subentry[] getSubentries( String uuid )
{
- Subentry[] subentries = uuidCache.get( uuid );
-
- return subentries;
+ try
+ {
+ lockRead();
+ Subentry[] subentries = uuidCache.get( uuid );
+
+ return subentries;
+ }
+ finally
+ {
+ unlock();
+ }
}
@@ -93,10 +153,18 @@ public class SubentryCache implements It
*/
public final Subentry getSubentry( DN dn, AdministrativeRoleEnum role )
{
- Subentry[] subentries = dnCache.getElement( dn );
- Subentry subentry = subentries[role.getValue()];
-
- return subentry;
+ try
+ {
+ lockRead();
+ Subentry[] subentries = dnCache.getElement( dn );
+ Subentry subentry = subentries[role.getValue()];
+
+ return subentry;
+ }
+ finally
+ {
+ unlock();
+ }
}
@@ -108,9 +176,17 @@ public class SubentryCache implements It
*/
public final Subentry[] getSubentries( DN dn )
{
- Subentry[] subentries = dnCache.getElement( dn );
-
- return subentries;
+ try
+ {
+ lockRead();
+ Subentry[] subentries = dnCache.getElement( dn );
+
+ return subentries;
+ }
+ finally
+ {
+ unlock();
+ }
}
@@ -123,9 +199,17 @@ public class SubentryCache implements It
*/
public final Subentry[] removeSubentry( String uuid )
{
- Subentry[] oldSubentry = uuidCache.remove( uuid );
-
- return oldSubentry;
+ try
+ {
+ lockWrite();
+ Subentry[] oldSubentry = uuidCache.remove( uuid );
+
+ return oldSubentry;
+ }
+ finally
+ {
+ unlock();
+ }
}
@@ -138,22 +222,30 @@ public class SubentryCache implements It
*/
public final Subentry[] removeSubentry( DN dn ) throws LdapException
{
- Subentry[] oldSubentry = dnCache.getElement( dn );
- dnCache.remove( dn );
-
- // Update the UUID cache
- if ( oldSubentry != null )
- {
- for ( Subentry subentry : oldSubentry )
- {
- if ( subentry != null )
+ try
+ {
+ lockWrite();
+ Subentry[] oldSubentry = dnCache.getElement( dn );
+ dnCache.remove( dn );
+
+ // Update the UUID cache
+ if ( oldSubentry != null )
+ {
+ for ( Subentry subentry : oldSubentry )
{
- uuidCache.remove( subentry.getUuid() );
+ if ( subentry != null )
+ {
+ uuidCache.remove( subentry.getUuid() );
+ }
}
}
+
+ return oldSubentry;
+ }
+ finally
+ {
+ unlock();
}
-
- return oldSubentry;
}
@@ -166,28 +258,36 @@ public class SubentryCache implements It
*/
public Subentry[] addSubentry( DN dn, Subentry subentry ) throws
LdapException
{
- Subentry[] subentries = uuidCache.get( subentry.getUuid() );
-
- if ( subentries == null )
- {
- subentries = new Subentry[4];
- }
-
- subentries[subentry.getAdministrativeRole().getValue()] = subentry;
- Subentry[] oldSubentry = uuidCache.put( subentry.getUuid(), subentries
);
-
- Subentry[] dnSubentries = dnCache.getElement( dn );
-
- if ( dnSubentries != null )
+ try
{
- dnSubentries[subentry.getAdministrativeRole().getValue()] =
subentry;
+ lockWrite();
+ Subentry[] subentries = uuidCache.get( subentry.getUuid() );
+
+ if ( subentries == null )
+ {
+ subentries = new Subentry[4];
+ }
+
+ subentries[subentry.getAdministrativeRole().getValue()] = subentry;
+ Subentry[] oldSubentry = uuidCache.put( subentry.getUuid(),
subentries );
+
+ Subentry[] dnSubentries = dnCache.getElement( dn );
+
+ if ( dnSubentries != null )
+ {
+ dnSubentries[subentry.getAdministrativeRole().getValue()] =
subentry;
+ }
+ else
+ {
+ dnCache.add( dn, subentries );
+ }
+
+ return oldSubentry;
}
- else
+ finally
{
- dnCache.add( dn, subentries );
+ unlock();
}
-
- return oldSubentry;
}
@@ -198,7 +298,15 @@ public class SubentryCache implements It
*/
public boolean hasSubentry( String uuid )
{
- return uuidCache.containsKey( uuid );
+ try
+ {
+ lockRead();
+ return uuidCache.containsKey( uuid );
+ }
+ finally
+ {
+ unlock();
+ }
}
@@ -209,7 +317,15 @@ public class SubentryCache implements It
*/
public boolean hasSubentry( DN dn )
{
- return dnCache.hasElement( dn );
+ try
+ {
+ lockRead();
+ return dnCache.hasElement( dn );
+ }
+ finally
+ {
+ unlock();
+ }
}
@@ -222,15 +338,23 @@ public class SubentryCache implements It
*/
public boolean hasSubentry( String uuid, AdministrativeRoleEnum role )
{
- Subentry[] subentries = uuidCache.get( uuid );
-
- if ( subentries == null )
+ try
{
- return false;
+ lockRead();
+ Subentry[] subentries = uuidCache.get( uuid );
+
+ if ( subentries == null )
+ {
+ return false;
+ }
+ else
+ {
+ return subentries[ role.getValue() ] != null;
+ }
}
- else
+ finally
{
- return subentries[ role.getValue() ] != null;
+ unlock();
}
}
@@ -243,15 +367,23 @@ public class SubentryCache implements It
*/
public boolean hasSubentry( DN dn, AdministrativeRoleEnum role )
{
- Subentry[] subentries = dnCache.getElement( dn );
-
- if ( subentries == null )
+ try
{
- return false;
+ lockRead();
+ Subentry[] subentries = dnCache.getElement( dn );
+
+ if ( subentries == null )
+ {
+ return false;
+ }
+ else
+ {
+ return subentries[ role.getValue() ] != null;
+ }
}
- else
+ finally
{
- return subentries[ role.getValue() ] != null;
+ unlock();
}
}
@@ -261,6 +393,14 @@ public class SubentryCache implements It
*/
public Iterator<String> iterator()
{
- return uuidCache.keySet().iterator();
+ try
+ {
+ lockRead();
+ return uuidCache.keySet().iterator();
+ }
+ finally
+ {
+ unlock();
+ }
}
}