You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2014/02/13 17:01:21 UTC

svn commit: r1567963 - in /directory/apacheds/trunk: core-api/src/main/java/org/apache/directory/server/core/api/ core-api/src/main/java/org/apache/directory/server/core/api/partition/ core-api/src/main/java/org/apache/directory/server/core/api/schema/...

Author: kayyagari
Date: Thu Feb 13 16:01:21 2014
New Revision: 1567963

URL: http://svn.apache.org/r1567963
Log:
o updated to add contextCsn to each partition instead of maintaining one global value for all partitions
o fixed the wrong partition sync() order in DefaultDirectoryService
o moved the cache initialization block in JdbmPartition before checking the context entry
o piggy backed on few tests to verify the context entry

Modified:
    directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java
    directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java
    directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java
    directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java
    directory/apacheds/trunk/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java
    directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/AddIT.java
    directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
    directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
    directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java
    directory/apacheds/trunk/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartitionTest.java
    directory/apacheds/trunk/ldif-partition/src/test/resources/log4j.properties
    directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/SyncReplRequestHandler.java
    directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java

Modified: directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java (original)
+++ directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/DirectoryService.java Thu Feb 13 16:01:21 2014
@@ -545,20 +545,6 @@ public interface DirectoryService extend
 
 
     /**
-     * the highest committed CSN value
-     *
-     * @param lastCommittedCsnVal the CSN value
-     */
-    void setContextCsn( String lastCommittedCsnVal );
-
-
-    /**
-     * @return the current highest committed CSN value
-     */
-    String getContextCsn();
-
-
-    /**
      * the time interval at which the DirectoryService's data is flushed to disk
      * 
      * @param syncPeriodMillis the syncPeriodMillis to set

Modified: directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java (original)
+++ directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/AbstractPartition.java Thu Feb 13 16:01:21 2014
@@ -67,6 +67,11 @@ public abstract class AbstractPartition 
     /** the cache service */
     protected CacheService cacheService;
 
+    /** the value of last successful add/update operation's CSN */
+    private String contextCsn;
+    
+    /** a flag to detect the change in context CSN */
+    protected volatile boolean ctxCsnChanged = false;
 
     /**
      * {@inheritDoc}
@@ -252,4 +257,30 @@ public abstract class AbstractPartition 
     {
         this.cacheService = cacheService;
     }
+
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String getContextCsn()
+    {
+        return contextCsn;
+    }
+
+    
+    /**
+     * Replaces the current context CSN with the given CSN value if they are not same and
+     * sets the ctxCsnChanged flag to true.
+     * 
+     * @param csn the CSN value
+     */
+    protected void setContextCsn( String csn )
+    {
+        if( !csn.equals( contextCsn ) )
+        {
+            contextCsn = csn;
+            ctxCsnChanged = true;
+        }
+    }
 }

Modified: directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java (original)
+++ directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/partition/Partition.java Thu Feb 13 16:01:21 2014
@@ -289,4 +289,17 @@ public interface Partition
      * @param cacheService
      */
     void setCacheService( CacheService cacheService );
+
+    
+    /**
+     * @return the current highest committed CSN value
+     */
+    String getContextCsn();
+
+    
+    /**
+     * saves the context CSN value in the context entry of the partition
+     * @throws Exception
+     */
+    void saveContextCsn() throws Exception;
 }

Modified: directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java (original)
+++ directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/api/schema/SchemaPartition.java Thu Feb 13 16:01:21 2014
@@ -512,6 +512,20 @@ public final class SchemaPartition exten
     }
 
 
+    @Override
+    public String getContextCsn()
+    {
+        return wrapped.getContextCsn();
+    }
+
+
+    @Override
+    public void saveContextCsn() throws Exception
+    {
+        wrapped.saveContextCsn();
+    }
+
+
     /**
      * @see Object#toString()
      */

Modified: directory/apacheds/trunk/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java (original)
+++ directory/apacheds/trunk/core-api/src/test/java/org/apache/directory/server/core/api/MockDirectoryService.java Thu Feb 13 16:01:21 2014
@@ -465,23 +465,12 @@ public class MockDirectoryService implem
     }
 
 
-    public String getContextCsn()
-    {
-        return null;
-    }
-
-
     public long getSyncPeriodMillis()
     {
         return 0;
     }
 
 
-    public void setContextCsn( String lastCommittedCsnVal )
-    {
-    }
-
-
     public void setSyncPeriodMillis( long syncPeriodMillis )
     {
     }

Modified: directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/AddIT.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/AddIT.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/AddIT.java (original)
+++ directory/apacheds/trunk/core-integ/src/test/java/org/apache/directory/server/core/operations/add/AddIT.java Thu Feb 13 16:01:21 2014
@@ -23,6 +23,7 @@ package org.apache.directory.server.core
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
 
+import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.name.Dn;
@@ -84,6 +85,13 @@ public class AddIT extends AbstractLdapT
             "cn: test" );
 
         connection.add( entry );
+        
+        entry = connection.lookup( entry.getDn(), SchemaConstants.ALL_ATTRIBUTES_ARRAY );
+        Entry contextEntry = connection.lookup( "ou=system", SchemaConstants.ALL_ATTRIBUTES_ARRAY );
+        
+        String expectedCsn = entry.get( SchemaConstants.ENTRY_CSN_AT ).getString();
+        String contextCsn = contextEntry.get( SchemaConstants.CONTEXT_CSN_AT ).getString();
+        assertEquals( expectedCsn, contextCsn );
     }
 
 

Modified: directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java (original)
+++ directory/apacheds/trunk/core-shared/src/main/java/org/apache/directory/server/core/shared/partition/DefaultPartitionNexus.java Thu Feb 13 16:01:21 2014
@@ -312,44 +312,11 @@ public class DefaultPartitionNexus exten
     {
         MultiException error = null;
 
-        // store the contextCSN value in the entry ou=system
-        // note that this modification shouldn't change the entryCSN value of ou=system entry
-        try
-        {
-            String currentCtxCsn = directoryService.getContextCsn();
-            // update only if the CSN changes
-            if ( ( currentCtxCsn != null ) && !currentCtxCsn.equals( lastSyncedCtxCsn ) )
-            {
-                lastSyncedCtxCsn = currentCtxCsn;
-
-                Attribute contextCsnAt = mods.get( 0 ).getAttribute();
-                contextCsnAt.clear();
-                contextCsnAt.add( lastSyncedCtxCsn );
-
-                Attribute timeStampAt = mods.get( 1 ).getAttribute();
-                timeStampAt.clear();
-                timeStampAt.add( DateUtils.getGeneralizedTime() );
-
-                ModifyOperationContext csnModContext = new ModifyOperationContext( directoryService.getAdminSession(),
-                    directoryService.getSystemPartition().getSuffixDn(), mods );
-                directoryService.getSystemPartition().modify( csnModContext );
-            }
-        }
-        catch ( Exception e )
-        {
-            LOG.warn( "Failed to save the contextCSN attribute value in ou=system entry.", e );
-            if ( error == null )
-            {
-                error = new MultiException( I18n.err( I18n.ERR_265 ) );
-            }
-
-            error.addThrowable( e );
-        }
-
         for ( Partition partition : this.partitions.values() )
         {
             try
             {
+                partition.saveContextCsn();
                 partition.sync();
             }
             catch ( Exception e )
@@ -383,9 +350,6 @@ public class DefaultPartitionNexus exten
     {
         Partition partition = getPartition( addContext.getDn() );
         partition.add( addContext );
-
-        Attribute at = addContext.getEntry().get( SchemaConstants.ENTRY_CSN_AT );
-        directoryService.setContextCsn( at.getString() );
     }
 
 
@@ -440,15 +404,6 @@ public class DefaultPartitionNexus exten
         Partition partition = getPartition( deleteContext.getDn() );
         Entry deletedEntry = partition.delete( deleteContext );
 
-        Entry entry = deleteContext.getEntry();
-        Attribute csn = entry.get( ENTRY_CSN_AT );
-        // can be null while doing subentry deletion
-        //TODO verify if this gets in the way of replication
-        if ( csn != null )
-        {
-            directoryService.setContextCsn( csn.getString() );
-        }
-
         return deletedEntry;
     }
 
@@ -530,13 +485,6 @@ public class DefaultPartitionNexus exten
         {
             directoryService.getInterceptor( InterceptorEnum.EVENT_INTERCEPTOR.getName() ).modify( modifyContext );
         }
-
-        Entry alteredEntry = modifyContext.getAlteredEntry();
-
-        if ( alteredEntry != null )
-        {
-            directoryService.setContextCsn( alteredEntry.get( ENTRY_CSN_AT ).getString() );
-        }
     }
 
 
@@ -549,9 +497,6 @@ public class DefaultPartitionNexus exten
         Partition partition = getPartition( moveContext.getDn() );
 
         partition.move( moveContext );
-
-        Entry entry = moveContext.getModifiedEntry();
-        directoryService.setContextCsn( entry.get( ENTRY_CSN_AT ).getString() );
     }
 
 
@@ -562,9 +507,6 @@ public class DefaultPartitionNexus exten
     {
         Partition partition = getPartition( moveAndRenameContext.getDn() );
         partition.moveAndRename( moveAndRenameContext );
-
-        Entry entry = moveAndRenameContext.getModifiedEntry();
-        directoryService.setContextCsn( entry.get( ENTRY_CSN_AT ).getString() );
     }
 
 
@@ -575,9 +517,6 @@ public class DefaultPartitionNexus exten
     {
         Partition partition = getPartition( renameContext.getDn() );
         partition.rename( renameContext );
-
-        Entry entry = renameContext.getModifiedEntry();
-        directoryService.setContextCsn( entry.get( ENTRY_CSN_AT ).getString() );
     }
 
 
@@ -933,6 +872,11 @@ public class DefaultPartitionNexus exten
     {
         Partition parent = null;
 
+        if ( !dn.isSchemaAware() )
+        {
+           dn.apply( schemaManager ); 
+        }
+        
         synchronized ( partitionLookupTree )
         {
             parent = partitionLookupTree.getElement( dn );
@@ -1069,4 +1013,18 @@ public class DefaultPartitionNexus exten
 
         mods.add( timeStampMod );
     }
+
+
+    @Override
+    public String getContextCsn()
+    {
+        // nexus doesn't contain a contextCSN
+        return null;
+    }
+
+
+    @Override
+    public void saveContextCsn() throws Exception
+    {
+    }
 }

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java Thu Feb 13 16:01:21 2014
@@ -263,9 +263,6 @@ public class DefaultDirectoryService imp
     /** The maximum size for an incoming PDU */
     private int maxPDUSize = Integer.MAX_VALUE;
 
-    /** the value of last successful add/update operation's CSN */
-    private String contextCsn;
-
     /** lock file for directory service's working directory */
     private RandomAccessFile lockFile = null;
 
@@ -1247,20 +1244,6 @@ public class DefaultDirectoryService imp
         initialize();
         showSecurityWarnings();
 
-        // load the last stored valid CSN value
-        LookupOperationContext loc = new LookupOperationContext( getAdminSession(), systemPartition.getSuffixDn(),
-            SchemaConstants.ALL_ATTRIBUTES_ARRAY );
-
-        Entry entry = systemPartition.lookup( loc );
-
-        Attribute cntextCsnAt = entry.get( SchemaConstants.CONTEXT_CSN_AT );
-
-        if ( cntextCsnAt != null )
-        {
-            // this is a multivalued attribute but current syncrepl provider implementation stores only ONE value at ou=system
-            contextCsn = cntextCsnAt.getString();
-        }
-
         started = true;
 
         if ( !testEntries.isEmpty() )
@@ -1295,7 +1278,10 @@ public class DefaultDirectoryService imp
         // Shutdown the sync thread
         // --------------------------------------------------------------------
         LOG.debug( "--- Syncing the nexus " );
+        LOG.debug( "--- Flushing everything before quitting" );
+        getOperationManager().lockWrite();
         partitionNexus.sync();
+        getOperationManager().unlockWrite();
 
         // --------------------------------------------------------------------
         // Shutdown the changelog
@@ -1313,19 +1299,14 @@ public class DefaultDirectoryService imp
             journal.destroy();
         }
 
+        
         // --------------------------------------------------------------------
         // Shutdown the partition
         // --------------------------------------------------------------------
 
         LOG.debug( "--- Destroying the nexus" );
         partitionNexus.destroy();
-
-        // Last flush...
-        LOG.debug( "--- Flushing everything before quitting" );
-        getOperationManager().lockWrite();
-        partitionNexus.sync();
-        getOperationManager().unlockWrite();
-
+        
         // --------------------------------------------------------------------
         // And shutdown the server
         // --------------------------------------------------------------------
@@ -2159,24 +2140,6 @@ public class DefaultDirectoryService imp
 
 
     /**
-     * {@inheritDoc}
-     */
-    public String getContextCsn()
-    {
-        return contextCsn;
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setContextCsn( String lastKnownCsn )
-    {
-        this.contextCsn = lastKnownCsn;
-    }
-
-
-    /**
      * checks if the working directory is already in use by some other directory service, if yes
      * then throws a runtime exception else will obtain the lock on the working directory
      */

Modified: directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java (original)
+++ directory/apacheds/trunk/jdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmPartition.java Thu Feb 13 16:01:21 2014
@@ -218,6 +218,18 @@ public class JdbmPartition extends Abstr
 
             deleteUnusedIndexFiles( allIndices, allIndexDbFiles );
 
+            if ( cacheService != null )
+            {
+                entryCache = cacheService.getCache( getId() );
+
+                int cacheSizeConfig = entryCache.getCacheConfiguration().getMaxElementsInMemory();
+
+                if ( cacheSizeConfig < cacheSize )
+                {
+                    entryCache.getCacheConfiguration().setMaxElementsInMemory( cacheSize );
+                }
+            }
+
             // Initialization of the context entry
             if ( ( suffixDn != null ) && ( contextEntry != null ) )
             {
@@ -265,18 +277,6 @@ public class JdbmPartition extends Abstr
                 }
             }
 
-            if ( cacheService != null )
-            {
-                entryCache = cacheService.getCache( getId() );
-
-                int cacheSizeConfig = entryCache.getCacheConfiguration().getMaxElementsInMemory();
-
-                if ( cacheSizeConfig < cacheSize )
-                {
-                    entryCache.getCacheConfiguration().setMaxElementsInMemory( cacheSize );
-                }
-            }
-
             // We are done !
             initialized = true;
         }

Modified: directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java (original)
+++ directory/apacheds/trunk/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientAddRequestTest.java Thu Feb 13 16:01:21 2014
@@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
 import org.apache.directory.api.ldap.model.csn.CsnFactory;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
@@ -45,6 +46,7 @@ import org.apache.directory.api.ldap.mod
 import org.apache.directory.api.ldap.model.message.AddRequestImpl;
 import org.apache.directory.api.ldap.model.message.AddResponse;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.message.controls.ManageDsaITImpl;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.util.DateUtils;
@@ -107,6 +109,18 @@ public class ClientAddRequestTest extend
         connection.add( entry );
 
         assertTrue( session.exists( dn ) );
+        
+        EntryCursor cursor = connection.search( entry.getDn(), "(objectClass=*)", SearchScope.OBJECT, SchemaConstants.ALL_ATTRIBUTES_ARRAY );
+        assertTrue( cursor.next() );
+        entry = cursor.get();
+        
+        cursor = connection.search( "ou=system", "(objectClass=*)", SearchScope.OBJECT, SchemaConstants.ALL_ATTRIBUTES_ARRAY );
+        assertTrue( cursor.next() );
+        Entry contextEntry = cursor.get();
+        
+        String expectedCsn = entry.get( SchemaConstants.ENTRY_CSN_AT ).getString();
+        String contextCsn = contextEntry.get( SchemaConstants.CONTEXT_CSN_AT ).getString();
+        assertEquals( expectedCsn, contextCsn );
     }
 
 

Modified: directory/apacheds/trunk/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartitionTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartitionTest.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartitionTest.java (original)
+++ directory/apacheds/trunk/ldif-partition/src/test/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartitionTest.java Thu Feb 13 16:01:21 2014
@@ -269,6 +269,12 @@ public class SingleFileLdifPartitionTest
             fetched.removeAttributes( "entryDn" );
         }
 
+        if ( !entry.containsAttribute( SchemaConstants.CONTEXT_CSN_AT ) )
+        {
+            // Removed the entryDn attribute to be able to compare the entries
+            fetched.removeAttributes( SchemaConstants.CONTEXT_CSN_AT );
+        }
+
         assertEquals( entry, fetched );
     }
 

Modified: directory/apacheds/trunk/ldif-partition/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldif-partition/src/test/resources/log4j.properties?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/ldif-partition/src/test/resources/log4j.properties (original)
+++ directory/apacheds/trunk/ldif-partition/src/test/resources/log4j.properties Thu Feb 13 16:01:21 2014
@@ -20,3 +20,8 @@ log4j.appender.stdout=org.apache.log4j.C
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
 
+#log4j.logger.org.apache.directory.api.ldap.model.schema.registries=warn
+#log4j.logger.org.apache.directory.api.ldap.model.schema=warn
+#log4j.logger.org.apache.directory.api.util=warn
+#log4j.logger.org.apache.directory.api.ldap.model=warn
+#log4j.logger.org.apache.directory.CURSOR_LOG=warn
\ No newline at end of file

Modified: directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/SyncReplRequestHandler.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/SyncReplRequestHandler.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/SyncReplRequestHandler.java (original)
+++ directory/apacheds/trunk/protocol-ldap/src/main/java/org/apache/directory/server/ldap/replication/provider/SyncReplRequestHandler.java Thu Feb 13 16:01:21 2014
@@ -97,6 +97,7 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.api.interceptor.context.DeleteOperationContext;
 import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
 import org.apache.directory.server.core.api.interceptor.context.OperationContext;
+import org.apache.directory.server.core.api.partition.Partition;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.server.ldap.LdapProtocolUtils;
 import org.apache.directory.server.ldap.LdapServer;
@@ -507,7 +508,8 @@ public class SyncReplRequestHandler impl
 
         ExprNode modifiedFilter = modifyFilter( session, request );
 
-        String contextCsn = dirService.getContextCsn();
+        Partition partition = dirService.getPartitionNexus().getPartition( request.getBase() );
+        String contextCsn = partition.getContextCsn();
 
         boolean refreshNPersist = isRefreshNPersist( request );
 

Modified: directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java?rev=1567963&r1=1567962&r2=1567963&view=diff
==============================================================================
--- directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java (original)
+++ directory/apacheds/trunk/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java Thu Feb 13 16:01:21 2014
@@ -179,6 +179,7 @@ public abstract class AbstractBTreeParti
     protected AttributeType ENTRY_UUID_AT;
     protected AttributeType ALIASED_OBJECT_NAME_AT;
     protected AttributeType ADMINISTRATIVE_ROLE_AT;
+    protected AttributeType CONTEXT_CSN_AT;
 
     private static final boolean NO_REVERSE = Boolean.FALSE;
     private static final boolean WITH_REVERSE = Boolean.TRUE;
@@ -238,7 +239,7 @@ public abstract class AbstractBTreeParti
         ENTRY_DN_AT = schemaManager.getAttributeType( SchemaConstants.ENTRY_DN_AT );
         ENTRY_UUID_AT = schemaManager.getAttributeType( SchemaConstants.ENTRY_UUID_AT );
         ADMINISTRATIVE_ROLE_AT = schemaManager.getAttributeType( SchemaConstants.ADMINISTRATIVE_ROLE_AT );
-
+        CONTEXT_CSN_AT = schemaManager.getAttributeType( SchemaConstants.CONTEXT_CSN_AT );
     }
 
 
@@ -835,6 +836,9 @@ public abstract class AbstractBTreeParti
                 // Remove the EntryDN attribute
                 entry.removeAttributes( ENTRY_DN_AT );
 
+                Attribute at = entry.get( SchemaConstants.ENTRY_CSN_AT );
+                setContextCsn( at.getString() );
+
                 // And finally add the entry into the master table
                 master.put( id, entry );
             }
@@ -1066,6 +1070,13 @@ public abstract class AbstractBTreeParti
 
                 entryDnCache.remove( id );
                 
+                Attribute csn = entry.get( ENTRY_CSN_AT );
+                // can be null while doing subentry deletion
+                if ( csn != null )
+                {
+                    setContextCsn( csn.getString() );
+                }
+
                 master.remove( id );
             }
             finally
@@ -1099,6 +1110,11 @@ public abstract class AbstractBTreeParti
         {
             setRWLock( searchContext );
 
+            if ( ctxCsnChanged && getSuffixDn().getNormName().equals( searchContext.getDn().getNormName() ) )
+            {
+                saveContextCsn();
+            }
+            
             PartitionSearchResult searchResult = searchEngine.computeResult( schemaManager, searchContext );
 
             Cursor<Entry> result = new EntryCursorAdaptor( this, searchResult );
@@ -1133,6 +1149,11 @@ public abstract class AbstractBTreeParti
             return null;
         }
 
+        if ( ctxCsnChanged && getSuffixDn().getNormName().equals( lookupContext.getDn().getNormName() ) )
+        {
+            saveContextCsn();
+        }
+
         Entry entry = fetch( id, lookupContext.getDn() );
 
         return entry;
@@ -1302,6 +1323,8 @@ public abstract class AbstractBTreeParti
         // Remove the EntryDN
         entry.removeAttributes( ENTRY_DN_AT );
 
+        setContextCsn( entry.get( ENTRY_CSN_AT ).getString() );
+        
         master.put( id, entry );
 
         if ( isSyncOnWrite.get() )
@@ -1837,6 +1860,8 @@ public abstract class AbstractBTreeParti
 
         entryDnCache.clear();
         
+        setContextCsn( modifiedEntry.get( ENTRY_CSN_AT ).getString() );
+
         master.put( entryId, modifiedEntry );
 
         if ( isSyncOnWrite.get() )
@@ -2159,6 +2184,8 @@ public abstract class AbstractBTreeParti
         // Remove the EntryDN
         entry.removeAttributes( ENTRY_DN_AT );
 
+        setContextCsn( entry.get( ENTRY_CSN_AT ).getString() );
+
         // And save the modified entry
         master.put( oldId, entry );
     }
@@ -3203,4 +3230,105 @@ public abstract class AbstractBTreeParti
     {
         return aliasCache;
     }
+    
+    
+    @Override
+    public String getContextCsn()
+    {
+        if ( super.getContextCsn() == null )
+        {
+           loadContextCsn(); 
+        }
+        
+        return super.getContextCsn();
+    }
+
+
+    /**
+     * Loads the current context CSN present in the context entry of the partition
+     *
+     * @throws LdapException
+     */
+    protected void loadContextCsn()
+    {
+        try
+        {
+            if( rwLock == null )
+            {
+                // Create a ReadWrite lock from scratch
+                rwLock = new ReentrantReadWriteLock();
+            }
+
+            // load the last stored valid CSN value
+            String contextEntryId = getEntryId( getSuffixDn() );
+            
+            if( contextEntryId == null )
+            {
+                return;
+            }
+            
+            Entry entry = fetch( contextEntryId );
+            
+            Attribute ctxCsnAt = entry.get( CONTEXT_CSN_AT );
+            
+            if ( ctxCsnAt != null )
+            {
+                setContextCsn( ctxCsnAt.getString() );
+                ctxCsnChanged = false; // this is just loaded, not new
+            }
+        }
+        catch( LdapException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    // store the contextCSN value in the context entry 
+    // note that this modification shouldn't change the entryCSN value of the context entry
+    public void saveContextCsn() throws LdapException
+    {
+        if( !ctxCsnChanged )
+        {
+            return;
+        }
+        
+        String contextCsn = super.getContextCsn();
+        
+        if ( contextCsn == null )
+        {
+            return;
+        }
+        
+        if( rwLock == null )
+        {
+            // Create a ReadWrite lock from scratch
+            rwLock = new ReentrantReadWriteLock();
+        }
+        
+        try
+        {
+            String contextEntryId = getEntryId( getSuffixDn() );
+            Entry origEntry = fetch( contextEntryId );
+            
+            origEntry = ( ( ClonedServerEntry ) origEntry ).getOriginalEntry();
+            
+            origEntry.removeAttributes( CONTEXT_CSN_AT, ENTRY_DN_AT );
+            
+            origEntry.add( CONTEXT_CSN_AT, contextCsn );
+            
+            master.put( contextEntryId, origEntry );
+            
+            ctxCsnChanged = false;
+            
+            LOG.debug( "Saved context CSN {} for the partition {}", contextCsn, suffixDn );
+        }
+        catch ( Exception e )
+        {
+            throw new LdapOperationErrorException( e.getMessage(), e );
+        }
+    }
 }