o Fix for DIRSERVER_1974 (the piar Cache is updated for each operation
that impacts the Rdn index : add, delete, move, rename, moveAndRename)
o Minor refactoring (commented code removal)
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/modifydn/DIRSERVER_1974_IT.java b/server-integ/src/test/java/org/apache/directory/server/operations/modifydn/DIRSERVER_1974_IT.java
index 1fe942c..a74fd17 100755
--- a/server-integ/src/test/java/org/apache/directory/server/operations/modifydn/DIRSERVER_1974_IT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/modifydn/DIRSERVER_1974_IT.java
@@ -27,6 +27,10 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.IOException;
+
+import org.apache.directory.api.ldap.model.cursor.CursorException;
+import org.apache.directory.api.ldap.model.cursor.EntryCursor;
 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.exception.LdapException;
@@ -36,7 +40,9 @@
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.util.Network;
 import org.apache.directory.ldap.client.api.LdapConnection;
+import org.apache.directory.ldap.client.api.LdapNetworkConnection;
 import org.apache.directory.ldap.client.api.search.FilterBuilder;
 import org.apache.directory.ldap.client.template.ConnectionCallback;
 import org.apache.directory.ldap.client.template.EntryMapper;
@@ -52,12 +58,11 @@
 import org.apache.directory.server.core.annotations.CreatePartition;
 import org.apache.directory.server.core.integ.AbstractLdapTestUnit;
 import org.apache.directory.server.core.integ.CreateLdapConnectionPoolRule;
-import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotIndex;
-import org.apache.directory.server.core.partition.impl.btree.mavibot.MavibotPartition;
+import org.apache.directory.server.core.integ.FrameworkRunner;
 import org.apache.directory.server.integ.ServerIntegrationUtils;
-import org.junit.ClassRule;
 import org.junit.Ignore;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -75,14 +80,11 @@
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-@CreateLdapServer(
-        transports = {
-                @CreateTransport( protocol = "LDAP" )
-        } )
+@RunWith(FrameworkRunner.class)
 @CreateDS( name = "classDS",
         partitions = {
                 @CreatePartition( 
-                        type = MavibotPartition.class,
+                        //type = MavibotPartition.class,
                         name = "example",
                         suffix = "dc=example,dc=com",
                         contextEntry = @ContextEntry(
@@ -94,24 +96,24 @@
                         ),
                         indexes = {
                                 @CreateIndex(
-                                    type = MavibotIndex.class,
                                     attribute = "objectClass" 
                                 ),
                                 @CreateIndex( 
-                                    type = MavibotIndex.class,
                                     attribute = "dc" 
                                 ),
                                 @CreateIndex( 
-                                    type = MavibotIndex.class,
                                     attribute = "ou" 
                                 ),
                                 @CreateIndex( 
-                                    type = MavibotIndex.class,
                                     attribute = "uid" 
                                 )
                         }
                 )
         } )
+@CreateLdapServer(
+    transports = {
+            @CreateTransport( protocol = "LDAP" )
+    } )
 @CreateLdapConnectionPool(
         maxActive = 4,
         maxIdle = 2,
@@ -131,14 +133,128 @@
         }
     };
 
-    @ClassRule
-    public static CreateLdapConnectionPoolRule classCreateDsRule =
-            new CreateLdapConnectionPoolRule();
-
-
     @Test
+    public void testRenameWithALotOfDummiesAndSomeCustomAttributesAPI() throws LdapException, CursorException, IOException 
+    {
+        LdapConnection connection = new LdapNetworkConnection( Network.LOOPBACK_HOSTNAME, getLdapServer().getPort() );
+        connection.bind( "uid=admin, ou=system", "secret" );
+        
+        Dn peopleDn = new Dn( "ou=people," + BASE );
+            
+        // Add the root entry
+        connection.add( 
+            new DefaultEntry( peopleDn,
+            "objectClass: top",
+            "objectClass: organizationalUnit",
+            "ou: people" ) );
+
+        // Add 1000 children
+        int dummyCount = 1000;
+
+        for ( int i = 0; i < dummyCount; i++ ) 
+        {
+            String dn = "uid=uid-" + i + "," + peopleDn;
+            
+            connection.add( new DefaultEntry( dn,
+                    "objectClass: top",
+                    "objectClass: person",
+                    "objectClass: organizationalPerson",
+                    "objectClass: inetOrgPerson",
+                    "uid", "uid-" + i,
+                    "cn", "cn-" + i,
+                    "sn", "sn-" + i,
+                    "description", i + " is a person." ) );
+            
+            if ( i % 50 == 0 ) 
+            {
+                logger.debug( "Added person {}", i );
+            }
+        }
+        
+        EntryCursor cursor;
+        int count = 0;
+        
+        // Now test the rename
+        for ( int i = 0; i < 100; i++ ) 
+        {
+            String oldDnString = "uid=myra-ellen-amos, " + peopleDn.getName();
+            String newDnString = "uid=tory-amos, " + peopleDn.getName();
+
+            // Add an entry
+            connection.add( new DefaultEntry( oldDnString,
+                "objectClass: top", 
+                "objectClass: person", 
+                "objectClass: organizationalPerson", 
+                "objectClass: inetOrgPerson", 
+                "objectClass: portalPerson",
+                "uid: myra-ellen-amos",
+                "cn: Myra Ellen Amo",
+                "sn: Amos",
+                "active", Boolean.TRUE.toString(),
+                "affiliation: Unknown",
+                "timeZone: America/New_York",
+                "description: Myra Ellen Amos is a person." ) );
+            
+            // Check it has been added
+            Entry result = connection.lookup( oldDnString );
+            
+            assertNotNull (result );
+            
+            // Search for it
+            cursor = connection.search( peopleDn, "(sn=amos)", SearchScope.ONELEVEL );
+            count = 0;
+            
+            while ( cursor.next() )
+            {
+                Entry amos = cursor.get();
+                assertEquals( "myra-ellen-amos", amos.get( "uid" ).getString() );
+                assertEquals( "uid=myra-ellen-amos", amos.getDn().getRdn().getName() );
+                
+                count++;
+            }
+            
+            assertEquals( 1, count );
+
+            cursor.close();
+            
+            // Rename it
+            connection.rename( oldDnString, "uid=tory-amos" );
+
+            // Search for the old and renalme entry
+            assertNull( connection.lookup( oldDnString ) );
+            result = connection.lookup( newDnString );
+            assertNotNull( result );
+
+            // Search for the new entry
+            cursor = connection.search( peopleDn, "(sn=amos)", SearchScope.ONELEVEL );
+            count = 0;
+            
+            while ( cursor.next() )
+            {
+                Entry amos = cursor.get();
+                assertEquals( "tory-amos", amos.get( "uid" ).getString() );
+                assertEquals( "uid=tory-amos", amos.getDn().getRdn().getName() );
+                
+                count++;
+            }
+            
+            assertEquals( 1, count );
+
+            cursor.close();
+            
+            // Finally delete the new entry
+            connection.delete( newDnString );
+        }
+        
+        connection.close();
+    }
+
+    
+    @Test
+    @Ignore
     public void testRenameWithALotOfDummiesAndSomeCustomAttributes() {
-        LdapConnectionTemplate template = classCreateDsRule.getLdapConnectionTemplate();
+        CreateLdapConnectionPoolRule connectionPool = new CreateLdapConnectionPoolRule();
+        LdapConnectionTemplate template = connectionPool.getLdapConnectionTemplate();
         AddResponse response = null;
 
         final String peopleOu = "people";
@@ -215,6 +331,7 @@
 
             Entry found = template.searchFirst( peopleDn, FilterBuilder.equal( "sn", "amos" ),
                     SearchScope.ONELEVEL, DEFAULT_ENTRY_MAPPER );
+            
             assertNotNull( found );
             Rdn foundRdn = found.getDn().getRdn();
             assertEquals( "uid", foundRdn.getType() );
@@ -239,6 +356,8 @@
             foundRdn = found.getDn().getRdn();
             assertEquals( "uid", foundRdn.getType() );
             assertEquals( newUid, foundRdn.getValue() );
+            
+
 
             template.delete( newDn );
         }
@@ -249,7 +368,6 @@
      * Modify Rdn of an entry, delete its old rdn value and search before and
      * after rename.
      */
-    @Ignore
     @Test
     public void testModifyRdnWithLotsOfDummies() throws Exception
     {
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java b/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
index f4e918b..9164f1b 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/core/partition/impl/btree/AbstractBTreePartition.java
@@ -197,6 +197,9 @@
 
     private static final boolean NO_REVERSE = Boolean.FALSE;
     private static final boolean WITH_REVERSE = Boolean.TRUE;
+    
+    private static final boolean ADD_CACHE = Boolean.TRUE;
+    private static final boolean DEL_CACHE = Boolean.FALSE;
 
     protected static final boolean ADD_CHILD = true;
     protected static final boolean REMOVE_CHILD = false;
@@ -908,6 +911,9 @@
             {
                 // Update the RDN index
                 rdnIdx.add( partitionTxn, parentIdAndRdn, id );
+                
+                // Update the PIAR cache at the same time
+                updatePiarCache( parentIdAndRdn, id, ADD_CACHE );
 
                 // Update the parent's nbChildren and nbDescendants values
                 if ( parentId != Partition.ROOT_ID )
@@ -1005,7 +1011,6 @@
         while ( parent != null )
         {
             rdnIdx.drop( partitionTxn, parentId );
-            ////dumpRdnIdx();
             
             if ( isFirst )
             {
@@ -1144,7 +1149,7 @@
             {
                 rdnIdx.drop( partitionTxn, id );
 
-                ////dumpRdnIdx();
+                updatePiarCache( parent, id, DEL_CACHE );
 
                 entryDnCache.invalidate( id );
                 
@@ -2139,10 +2144,12 @@
         updateRdnIdx( partitionTxn, oldParentId, REMOVE_CHILD, movedEntry.getNbDescendants() );
 
         rdnIdx.drop( partitionTxn, entryId );
+        updatePiarCache( movedEntry, entryId, DEL_CACHE );
 
         // Now, add the new entry at the right position
         movedEntry.setParentId( newParentId );
         rdnIdx.add( partitionTxn, movedEntry, entryId );
+        updatePiarCache( movedEntry, entryId, ADD_CACHE );
 
         updateRdnIdx( partitionTxn, newParentId, ADD_CHILD, movedEntry.getNbDescendants() );
 
@@ -2293,6 +2300,7 @@
         
         // First drop the moved entry from the rdn index
         rdnIdx.drop( partitionTxn, entryId );
+        updatePiarCache( movedEntry, entryId, DEL_CACHE );
 
         //
         // The update the Rdn index. We will remove the ParentIdAndRdn associated with the
@@ -2318,6 +2326,7 @@
         movedEntry.setRdns( new Rdn[]
             { newRdn } );
         rdnIdx.add( partitionTxn, movedEntry, entryId );
+        updatePiarCache( movedEntry, entryId, ADD_CACHE );
 
         updateRdnIdx( partitionTxn, newParentId, ADD_CHILD, movedEntry.getNbDescendants() );
 
@@ -2538,7 +2547,6 @@
                     {
                         presenceIdx.drop( partitionTxn, newRdnAttrType.getOid(), oldId );
                     }
-
                 }
             }
 
@@ -2555,20 +2563,8 @@
             {
                 Index<?, String> userIndex = getUserIndex( newRdnAttrType );
                 
-                /*
-                if ( oldRemoved )
-                {
-                    String normalized = newRdnAttrType.getEquality().getNormalizer().normalize( newNormValue );
-                    ( ( Index ) userIndex ).add( normalized, id );
-                    ( ( Index ) index ).drop( newNormValue, oldId );
-                }
-                */
-                
                 String normalized = newRdnAttrType.getEquality().getNormalizer().normalize( ( String ) newNormValue );
                 ( ( Index ) userIndex ).add( partitionTxn, normalized, oldId );
-                
-                
-                //( ( Index ) index ).add( newNormValue, oldId );
 
                 // Make sure the altered entry shows the existence of the new attrib
                 String normTypeOid = presenceNormalizer.normalize( newNormType );
@@ -2686,6 +2682,8 @@
 
         // Now we can drop it
         rdnIdx.drop( partitionTxn, oldId );
+        
+        updatePiarCache( parentIdAndRdn, oldId, DEL_CACHE );
 
         // Update the descendants
         parentIdAndRdn.setParentId( parentId );
@@ -2693,6 +2691,8 @@
 
         rdnIdx.add( partitionTxn, parentIdAndRdn, oldId );
 
+        updatePiarCache( parentIdAndRdn, oldId, ADD_CACHE );
+
         entryDnCache.invalidateAll();
         
         if ( isSyncOnWrite.get() )
@@ -2761,6 +2761,22 @@
         entryCsnIdx.drop( partitionTxn, id );
         entryCsnIdx.add( partitionTxn, entryCsn, id );
     }
+    
+    
+    /**
+     * Update the ParentIdAndRdn cache, by adding or removing an element
+     */
+    private void updatePiarCache( ParentIdAndRdn piar, String id, boolean add )
+    {
+        if ( add == ADD_CACHE )
+        {
+            piarCache.put( id, piar );
+        }
+        else
+        {
+            piarCache.invalidate( id );
+        }
+    }
 
 
     // ------------------------------------------------------------------------