directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1387291 - /directory/apacheds/branches/apacheds-mvbt/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
Date Tue, 18 Sep 2012 18:09:10 GMT
Author: elecharny
Date: Tue Sep 18 18:09:10 2012
New Revision: 1387291

URL: http://svn.apache.org/viewvc?rev=1387291&view=rev
Log:
Added a ReadWriteLock and use it to protect the MasterTable and RdnIndex against concurrent
searches and modifications

Modified:
    directory/apacheds/branches/apacheds-mvbt/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java

Modified: directory/apacheds/branches/apacheds-mvbt/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-mvbt/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java?rev=1387291&r1=1387290&r2=1387291&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-mvbt/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
(original)
+++ directory/apacheds/branches/apacheds-mvbt/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
Tue Sep 18 18:09:10 2012
@@ -30,6 +30,8 @@ import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.directory.server.constants.ApacheSchemaConstants;
 import org.apache.directory.server.core.api.entry.ClonedServerEntry;
@@ -169,6 +171,9 @@ public abstract class AbstractBTreeParti
     protected static final boolean ADD_CHILD = true;
     protected static final boolean REMOVE_CHILD = false;
 
+    /** A lock to protect the MasterTable from concurrent access */
+    private ReadWriteLock masterTableLock = new ReentrantReadWriteLock();
+
 
     // ------------------------------------------------------------------------
     // C O N S T R U C T O R S
@@ -584,11 +589,20 @@ public abstract class AbstractBTreeParti
             Dn entryDn = entry.getDn();
 
             // check if the entry already exists
-            if ( getEntryId( entryDn ) != null )
+            try
+            {
+                lockRead();
+
+                if ( getEntryId( entryDn ) != null )
+                {
+                    LdapEntryAlreadyExistsException ne = new LdapEntryAlreadyExistsException(
+                        I18n.err( I18n.ERR_250_ENTRY_ALREADY_EXISTS, entryDn.getName() )
);
+                    throw ne;
+                }
+            }
+            finally
             {
-                LdapEntryAlreadyExistsException ne = new LdapEntryAlreadyExistsException(
-                    I18n.err( I18n.ERR_250_ENTRY_ALREADY_EXISTS, entryDn.getName() ) );
-                throw ne;
+                unlockRead();
             }
 
             String parentId = null;
@@ -609,7 +623,17 @@ public abstract class AbstractBTreeParti
             else
             {
                 parentDn = entryDn.getParent();
-                parentId = getEntryId( parentDn );
+
+                try
+                {
+                    lockRead();
+
+                    parentId = getEntryId( parentDn );
+                }
+                finally
+                {
+                    unlockRead();
+                }
 
                 key = new ParentIdAndRdn( parentId, entryDn.getRdn() );
             }
@@ -634,15 +658,6 @@ public abstract class AbstractBTreeParti
                 id = entryUUID.getString();
             }
 
-            // Update the RDN index
-            rdnIdx.add( key, id );
-
-            // Update the parent's nbChildren and nbDescendants values
-            if ( parentId != Partition.ROOT_ID )
-            {
-                updateRdnIdx( parentId, ADD_CHILD, 0 );
-            }
-
             // Update the ObjectClass index
             Attribute objectClass = entry.get( OBJECT_CLASS_AT );
 
@@ -708,8 +723,26 @@ public abstract class AbstractBTreeParti
             // Add the parentId in the entry
             entry.put( SchemaConstants.ENTRY_PARENT_ID_AT, parentId.toString() );
 
-            // And finally add the entry into the master table
-            master.put( id, entry );
+            try
+            {
+                lockWrite();
+
+                // Update the RDN index
+                rdnIdx.add( key, id );
+
+                // Update the parent's nbChildren and nbDescendants values
+                if ( parentId != Partition.ROOT_ID )
+                {
+                    updateRdnIdx( parentId, ADD_CHILD, 0 );
+                }
+
+                // And finally add the entry into the master table
+                master.put( id, entry );
+            }
+            finally
+            {
+                unlockWrite();
+            }
 
             if ( isSyncOnWrite.get() )
             {
@@ -736,27 +769,43 @@ public abstract class AbstractBTreeParti
      */
     public void delete( DeleteOperationContext deleteContext ) throws LdapException
     {
-        Dn dn = deleteContext.getDn();
+        try
+        {
+            Dn dn = deleteContext.getDn();
+            String id = null;
 
-        String id = getEntryId( dn );
+            try
+            {
+                lockRead();
+                id = getEntryId( dn );
+            }
+            finally
+            {
+                unlockRead();
+            }
 
-        // don't continue if id is null
-        if ( id == null )
-        {
-            throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_699, dn ) );
-        }
+            // don't continue if id is null
+            if ( id == null )
+            {
+                throw new LdapNoSuchObjectException( I18n.err( I18n.ERR_699, dn ) );
+            }
 
-        int childCount = getChildCount( id );
+            int childCount = getChildCount( id );
 
-        if ( childCount > 0 )
+            if ( childCount > 0 )
+            {
+                LdapContextNotEmptyException cnee = new LdapContextNotEmptyException( I18n.err(
I18n.ERR_700, dn ) );
+                //cnee.setRemainingName( dn );
+                throw cnee;
+            }
+
+            // We now defer the deletion to the implementing class
+            delete( id );
+        }
+        catch ( Exception e )
         {
-            LdapContextNotEmptyException cnee = new LdapContextNotEmptyException( I18n.err(
I18n.ERR_700, dn ) );
-            //cnee.setRemainingName( dn );
-            throw cnee;
+            throw new LdapOperationErrorException( e.getMessage() );
         }
-
-        // We now defer the deletion to the implementing class
-        delete( id );
     }
 
 
@@ -817,7 +866,17 @@ public abstract class AbstractBTreeParti
         try
         {
             // First get the entry
-            Entry entry = master.get( id );
+            Entry entry = null;
+
+            try
+            {
+                lockRead();
+                entry = master.get( id );
+            }
+            finally
+            {
+                unlockRead();
+            }
 
             if ( entry == null )
             {
@@ -843,10 +902,6 @@ public abstract class AbstractBTreeParti
             updateRdnIdx( parent.getParentId(), REMOVE_CHILD, 0 );
 
             // Update the rdn, oneLevel, subLevel, and entryCsn indexes
-            rdnIdx.drop( id );
-
-            dumpRdnIdx();
-
             entryCsnIdx.drop( entry.get( ENTRY_CSN_AT ).getString(), id );
 
             // Update the user indexes
@@ -870,7 +925,19 @@ public abstract class AbstractBTreeParti
                 }
             }
 
-            master.remove( id );
+            try
+            {
+                lockWrite();
+                rdnIdx.drop( id );
+
+                dumpRdnIdx();
+
+                master.remove( id );
+            }
+            finally
+            {
+                unlockWrite();
+            }
 
             if ( isSyncOnWrite.get() )
             {
@@ -1107,12 +1174,20 @@ public abstract class AbstractBTreeParti
     {
         try
         {
+            lockRead();
             Entry entry = master.get( id );
 
             if ( entry != null )
             {
                 // We have to store the DN in this entry
                 Dn dn = buildEntryDn( id );
+
+                if ( dn == null )
+                {
+                    // No dn : we probably have removed the RDNs for this entry
+                    return null;
+                }
+
                 entry.setDn( dn );
 
                 return new ClonedServerEntry( entry );
@@ -1124,6 +1199,17 @@ public abstract class AbstractBTreeParti
         {
             throw new LdapOperationErrorException( e.getMessage(), e );
         }
+        finally
+        {
+            try
+            {
+                unlockRead();
+            }
+            catch ( Exception e )
+            {
+                throw new LdapOperationErrorException( e.getMessage(), e );
+            }
+        }
     }
 
 
@@ -1138,7 +1224,17 @@ public abstract class AbstractBTreeParti
     {
         try
         {
-            Entry entry = master.get( id );
+            Entry entry = null;
+
+            try
+            {
+                lockRead();
+                entry = master.get( id );
+            }
+            finally
+            {
+                unlockRead();
+            }
 
             if ( entry != null )
             {
@@ -2033,6 +2129,12 @@ public abstract class AbstractBTreeParti
         do
         {
             ParentIdAndRdn cur = rdnIdx.reverseLookup( parentId );
+
+            if ( cur == null )
+            {
+                return null;
+            }
+
             Rdn[] rdns = cur.getRdns();
 
             for ( Rdn rdn : rdns )
@@ -2731,4 +2833,40 @@ public abstract class AbstractBTreeParti
     {
         return master;
     }
+
+
+    /**
+     * Acquire a Read lock
+     */
+    private void lockRead() throws Exception
+    {
+        masterTableLock.readLock().lock();
+    }
+
+
+    /**
+     * Release a Read lock
+     */
+    private void unlockRead() throws Exception
+    {
+        masterTableLock.readLock().unlock();
+    }
+
+
+    /**
+     * Acquire a Write lock
+     */
+    private void lockWrite() throws Exception
+    {
+        masterTableLock.writeLock().lock();
+    }
+
+
+    /**
+     * Release a Write lock
+     */
+    private void unlockWrite() throws Exception
+    {
+        masterTableLock.writeLock().unlock();
+    }
 }



Mime
View raw message