Merge from trunk

git-svn-id: https://svn.apache.org/repos/asf/directory/apacheds/branches/one-sub-level-index-removal@1180652 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/core-constants/src/main/java/org/apache/directory/server/constants/ApacheSchemaConstants.java b/core-constants/src/main/java/org/apache/directory/server/constants/ApacheSchemaConstants.java
index 5b3373e..80c17f6 100644
--- a/core-constants/src/main/java/org/apache/directory/server/constants/ApacheSchemaConstants.java
+++ b/core-constants/src/main/java/org/apache/directory/server/constants/ApacheSchemaConstants.java
@@ -106,10 +106,6 @@
     public final static String APACHE_PRESENCE_AT = "ApachePresence";
     public final static String APACHE_PRESENCE_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.3";
 
-    // ApacheOneLevel
-    public final static String APACHE_ONE_LEVEL_AT = "apacheOneLevel";
-    public final static String APACHE_ONE_LEVEL_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.4";
-
     // ApacheOneAlias
     public final static String APACHE_ONE_ALIAS_AT = "apacheOneAlias";
     public final static String APACHE_ONE_ALIAS_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.5";
@@ -157,10 +153,6 @@
     public final static String SUBSCHEMA_SUBENTRY_NAME_AT = "subschemaSubentryName";
     public final static String SUBSCHEMA_SUBENTRY_NAME_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.37";
 
-    // apacheSubLevel
-    public final static String APACHE_SUB_LEVEL_AT = "apacheSubLevel";
-    public final static String APACHE_SUB_LEVEL_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.43";
-
     // apacheRdn
     public final static String APACHE_RDN_AT = "apacheRdn";
     public final static String APACHE_RDN_AT_OID = "1.3.6.1.4.1.18060.0.4.1.2.50";
diff --git a/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java b/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
index 564044c..296ecd1 100644
--- a/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
+++ b/jdbm-partition/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
@@ -35,7 +35,6 @@
 import org.apache.commons.io.FileUtils;
 import org.apache.directory.server.constants.ApacheSchemaConstants;
 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
-import org.apache.directory.server.core.interceptor.context.LookupOperationContext;
 import org.apache.directory.server.xdbm.GenericIndex;
 import org.apache.directory.server.xdbm.Index;
 import org.apache.directory.server.xdbm.IndexEntry;
@@ -248,14 +247,6 @@
         jdbmPartition.addIndex( new JdbmIndex<String, Entry>( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID ) );
         assertNotNull( jdbmPartition.getPresenceIndex() );
 
-        assertNull( jdbmPartition.getOneLevelIndex() );
-        ((Store<Entry, Long>)jdbmPartition).addIndex( new JdbmIndex<Long, Entry>( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID ) );
-        assertNotNull( jdbmPartition.getOneLevelIndex() );
-
-        assertNull( jdbmPartition.getSubLevelIndex() );
-        ((Store<Entry, Long>)jdbmPartition).addIndex( new JdbmIndex<Long, Entry>( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID ) );
-        assertNotNull( jdbmPartition.getSubLevelIndex() );
-
         assertNull( jdbmPartition.getId() );
         jdbmPartition.setId( "foo" );
         assertEquals( "foo", jdbmPartition.getId() );
@@ -329,26 +320,6 @@
         {
         }
 
-        assertNotNull( store.getOneLevelIndex() );
-        try
-        {
-            store.addIndex( new JdbmIndex<Long, Entry>( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID ) );
-            fail();
-        }
-        catch ( IllegalStateException e )
-        {
-        }
-
-        assertNotNull( store.getSubLevelIndex() );
-        try
-        {
-            store.addIndex( new JdbmIndex<Long, Entry>( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID ) );
-            fail();
-        }
-        catch ( IllegalStateException e )
-        {
-        }
-
         assertNotNull( store.getId() );
         try
         {
@@ -403,7 +374,7 @@
 
         Iterator<String> systemIndices = store.getSystemIndices();
 
-        for ( int ii = 0; ii < 10; ii++ )
+        for ( int ii = 0; ii < 8; ii++ )
         {
             assertTrue( systemIndices.hasNext() );
             assertNotNull( systemIndices.next() );
@@ -513,8 +484,12 @@
         assertNotNull( cursor );
         cursor.beforeFirst();
         assertTrue( cursor.next() );
-        assertEquals( 2L, ( long ) cursor.get().getId() );
+        assertEquals( 3L, ( long ) cursor.get().getId() );
         assertTrue( cursor.next() );
+        assertEquals( 4L, ( long ) cursor.get().getId() );
+        assertTrue( cursor.next() );
+        assertEquals( 2L, ( long ) cursor.get().getId() );
+        assertFalse( cursor.next() );
         assertEquals( 3, store.getChildCount( 1L ) );
 
         store.delete( 2L );
@@ -540,117 +515,6 @@
 
 
     @Test
-    public void testSubLevelIndex() throws Exception
-    {
-        Index idx = store.getSubLevelIndex();
-
-        assertEquals( 19, idx.count() );
-
-        Cursor<IndexEntry<Long, Long>> cursor = idx.forwardCursor( 2L );
-
-        assertTrue( cursor.next() );
-        assertEquals( 2, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.next() );
-        assertEquals( 5, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.next() );
-        assertEquals( 6, ( long ) cursor.get().getId() );
-
-        assertFalse( cursor.next() );
-
-        idx.drop( 5L );
-
-        cursor = idx.forwardCursor( 2L );
-
-        assertTrue( cursor.next() );
-        assertEquals( 2, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.next() );
-        assertEquals( 6, ( long ) cursor.get().getId() );
-
-        assertFalse( cursor.next() );
-
-        // dn id 12
-        Dn martinDn = new Dn( schemaManager, "cn=Marting King,ou=Sales,o=Good Times Co." );
-        Entry entry = new DefaultEntry( schemaManager, martinDn );
-        entry.add( "objectClass", "top", "person", "organizationalPerson" );
-        entry.add( "ou", "Sales" );
-        entry.add( "cn", "Martin King" );
-        entry.add( "entryCSN", new CsnFactory( 1 ).newInstance().toString() );
-        entry.add( "entryUUID", UUID.randomUUID().toString() );
-        AddOperationContext addContext = new AddOperationContext( null, entry );
-        store.add( addContext );
-
-        cursor = idx.forwardCursor( 2L );
-        cursor.afterLast();
-        assertTrue( cursor.previous() );
-        assertEquals( 12, ( long ) cursor.get().getId() );
-
-        Dn newParentDn = new Dn( schemaManager, "ou=Board of Directors,o=Good Times Co." );
-
-        Dn newDn = newParentDn.add( martinDn.getRdn() );
-
-        store.move( martinDn, newParentDn, newDn, entry );
-        cursor = idx.forwardCursor( 3L );
-        cursor.afterLast();
-        assertTrue( cursor.previous() );
-        assertEquals( 12, ( long ) cursor.get().getId() );
-
-        // dn id 13
-        Dn marketingDn = new Dn( schemaManager, "ou=Marketing,ou=Sales,o=Good Times Co." );
-        entry = new DefaultEntry( schemaManager, marketingDn );
-        entry.add( "objectClass", "top", "organizationalUnit" );
-        entry.add( "ou", "Marketing" );
-        entry.add( "entryCSN", new CsnFactory( 1 ).newInstance().toString() );
-        entry.add( "entryUUID", UUID.randomUUID().toString() );
-        addContext = new AddOperationContext( null, entry );
-        store.add( addContext );
-
-        // dn id 14
-        Dn jimmyDn = new Dn( schemaManager, "cn=Jimmy Wales,ou=Marketing, ou=Sales,o=Good Times Co." );
-        entry = new DefaultEntry( schemaManager, jimmyDn );
-        entry.add( "objectClass", "top", "person", "organizationalPerson" );
-        entry.add( "ou", "Marketing" );
-        entry.add( "cn", "Jimmy Wales" );
-        entry.add( "entryCSN", new CsnFactory( 1 ).newInstance().toString() );
-        entry.add( "entryUUID", UUID.randomUUID().toString() );
-        addContext = new AddOperationContext( null, entry );
-        store.add( addContext );
-
-        newDn = newParentDn.add( marketingDn.getRdn() );
-
-        store.move( marketingDn, newParentDn, newDn, entry );
-
-        cursor = idx.forwardCursor( 3L );
-        cursor.afterLast();
-
-        assertTrue( cursor.previous() );
-        assertEquals( 14, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 13, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 12, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 10, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 9, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 7, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 3, ( long ) cursor.get().getId() );
-
-        assertFalse( cursor.previous() );
-    }
-
-
-    @Test
     public void testConvertIndex() throws Exception
     {
         // just create the new directory under working directory
@@ -713,7 +577,7 @@
     @Test
     public void testRename() throws Exception
     {
-        Dn dn = new Dn( schemaManager, "cn=Private Ryan,ou=Engineering,o=Good Times Co." );
+        Dn dn = new Dn( schemaManager, "cn=Pivate Ryan,ou=Engineering,o=Good Times Co." );
         Entry entry = new DefaultEntry( schemaManager, dn );
         entry.add( "objectClass", "top", "person", "organizationalPerson" );
         entry.add( "ou", "Engineering" );
@@ -727,18 +591,13 @@
         Rdn rdn = new Rdn( "sn=James" );
 
         store.rename( dn, rdn, true, null );
-        
-        dn = new Dn( schemaManager, "sn=James,ou=Engineering,o=Good Times Co." );
-        Entry renamed = store.lookup( new LookupOperationContext( null, dn ) );
-        assertNotNull( renamed );
-        assertEquals( "James", renamed.getDn().getRdn().getUpValue().getString() );
     }
 
 
     @Test
     public void testRenameEscaped() throws Exception
     {
-        Dn dn = new Dn( schemaManager, "cn=Private Ryan,ou=Engineering,o=Good Times Co." );
+        Dn dn = new Dn( schemaManager, "cn=Pivate Ryan,ou=Engineering,o=Good Times Co." );
         Entry entry = new DefaultEntry( schemaManager, dn );
         entry.add( "objectClass", "top", "person", "organizationalPerson" );
         entry.add( "ou", "Engineering" );
@@ -764,7 +623,7 @@
     @Test
     public void testMove() throws Exception
     {
-        Dn childDn = new Dn( schemaManager, "cn=Private Ryan,ou=Engineering,o=Good Times Co." );
+        Dn childDn = new Dn( schemaManager, "cn=Pivate Ryan,ou=Engineering,o=Good Times Co." );
         Entry childEntry = new DefaultEntry( schemaManager, childDn );
         childEntry.add( "objectClass", "top", "person", "organizationalPerson" );
         childEntry.add( "ou", "Engineering" );
diff --git a/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java b/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java
index 437ab8f..47091dc 100644
--- a/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java
+++ b/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java
@@ -359,7 +359,7 @@
         // Then, if there are some children, move then to the new place
         try
         {
-            IndexCursor<Long, Entry, Long> cursor = getSubLevelIndex().forwardCursor( entryIdOld );
+            IndexCursor<Long, Entry, Long> cursor = getRdnIndexHelper().getSubLevelScopeCursor( entryIdOld );
 
             while ( cursor.next() )
             {
diff --git a/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java b/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java
index f2e3b33..1aa0c39 100644
--- a/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java
+++ b/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/SingleFileLdifPartition.java
@@ -24,9 +24,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.RandomAccessFile;
-import java.util.HashMap;
 import java.util.Iterator;
-import java.util.Map;
 import java.util.UUID;
 
 import javax.naming.InvalidNameException;
@@ -38,7 +36,6 @@
 import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.server.xdbm.IndexCursor;
-import org.apache.directory.server.xdbm.IndexEntry;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.entry.DefaultEntry;
 import org.apache.directory.shared.ldap.model.entry.Entry;
@@ -295,11 +292,8 @@
                 {
                     return;
                 }
-                
-                IndexCursor<Long, Entry, Long> cursor = getOneLevelIndex().forwardCursor( suffixId );
 
-
-                appendLdif( lookup( suffixId ) );
+                IndexCursor<Long, Entry, Long> cursor = getRdnIndexHelper().getSubLevelScopeCursor( suffixId );
 
                 while ( cursor.next() )
                 {
@@ -308,8 +302,6 @@
                     Entry entry = lookup( childId );
 
                     appendLdif( entry );
-
-                    appendRecursive( childId, null );
                 }
 
                 cursor.close();
@@ -328,59 +320,6 @@
 
 
     /**
-     * appends all the entries present under a given entry, recursively
-     *
-     * @param entryId the base entry's id
-     * @param cursorMap the open cursor map
-     * @throws Exception
-     */
-    private void appendRecursive( Long entryId, Map<Long, IndexCursor<Long, Entry, Long>> cursorMap ) throws Exception
-    {
-        synchronized ( lock )
-        {
-
-            IndexCursor<Long, Entry, Long> cursor = null;
-            if ( cursorMap == null )
-            {
-                cursorMap = new HashMap<Long, IndexCursor<Long, Entry, Long>>();
-            }
-
-            cursor = cursorMap.get( entryId );
-
-            if ( cursor == null )
-            {
-                cursor = getOneLevelIndex().forwardCursor( entryId );
-                cursor.beforeFirst();
-                cursorMap.put( entryId, cursor );
-            }
-
-            if ( !cursor.next() ) // if this is a leaf entry's Dn
-            {
-                cursorMap.remove( entryId );
-                cursor.close();
-            }
-            else
-            {
-                do
-                {
-                    IndexEntry<Long, Long> idxEntry = cursor.get();
-                    Entry entry = lookup( idxEntry.getId() );
-
-                    Long childId = getEntryId( entry.getDn() );
-
-                    appendLdif( entry );
-
-                    appendRecursive( childId, cursorMap );
-                }
-                while ( cursor.next() );
-                cursorMap.remove( entryId );
-                cursor.close();
-            }
-        }
-    }
-
-
-    /**
      * append data to the LDIF file
      *
      * @param entry the entry to be written
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 6bd01de..dd9e3a7 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
@@ -23,11 +23,9 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URI;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -63,8 +61,8 @@
 import org.apache.directory.server.xdbm.Store;
 import org.apache.directory.server.xdbm.search.Optimizer;
 import org.apache.directory.server.xdbm.search.SearchEngine;
+import org.apache.directory.server.xdbm.search.impl.RdnIndexHelper;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
-import org.apache.directory.shared.ldap.model.cursor.Cursor;
 import org.apache.directory.shared.ldap.model.entry.Attribute;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.entry.Modification;
@@ -143,16 +141,13 @@
 
     /** the relative distinguished name index */
     protected Index<ParentIdAndRdn<ID>, Entry, ID> rdnIdx;
+    
+    /** the relative distinguished name index helper */
+    protected RdnIndexHelper<Entry, ID> rdnIndexHelper;
 
     /** a system index on objectClass attribute*/
     protected Index<String, Entry, ID> objectClassIdx;
 
-    /** the parent child relationship index */
-    protected Index<ID, Entry, ID> oneLevelIdx;
-
-    /** a system index on the entries of descendants of root Dn */
-    protected Index<ID, Entry, ID> subLevelIdx;
-
     /** the attribute presence index */
     protected Index<String, Entry, ID> presenceIdx;
 
@@ -290,20 +285,6 @@
             addIndex( index );
         }
 
-        if ( getOneLevelIndex() == null )
-        {
-            Index<ID, Entry, ID> index = new GenericIndex<ID, Entry, ID>( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID );
-            index.setWkDirPath( partitionPath );
-            addIndex( index );
-        }
-
-        if ( getSubLevelIndex() == null )
-        {
-            Index<ID, Entry, ID> index = new GenericIndex<ID, Entry, ID>( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID );
-            index.setWkDirPath( partitionPath );
-            addIndex( index );
-        }
-
         if ( getRdnIndex() == null )
         {
             Index<ParentIdAndRdn<ID>, Entry, ID> index = new GenericIndex<ParentIdAndRdn<ID>, Entry, ID>( ApacheSchemaConstants.APACHE_RDN_AT_OID );
@@ -363,9 +344,8 @@
 
         // set index shortcuts
         rdnIdx = ( Index<ParentIdAndRdn<ID>, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+        rdnIndexHelper = new RdnIndexHelper<Entry, ID>( rdnIdx, getRootId() ); 
         presenceIdx = ( Index<String, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID );
-        oneLevelIdx = ( Index<ID, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID );
-        subLevelIdx = ( Index<ID, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID );
         aliasIdx = ( Index<String, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
         oneAliasIdx = ( Index<ID, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_ONE_ALIAS_AT_OID );
         subAliasIdx = ( Index<ID, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_SUB_ALIAS_AT_OID );
@@ -581,8 +561,10 @@
             // Get a new ID for the added entry
             ID id = master.getNextId( entry );
     
-            // Update the RDN index
+            // Update the RDN index including one-level and sub-level counter
+            // TODO: move logic to RdnIndexHelper
             rdnIdx.add( key, id );
+            updateOneAndSubLevelCounters(parentId, true);
     
             // Update the ObjectClass index
             Attribute objectClass = entry.get( OBJECT_CLASS_AT );
@@ -606,22 +588,7 @@
                 Attribute aliasAttr = entry.get( ALIASED_OBJECT_NAME_AT );
                 addAliasIndices( id, entryDn, aliasAttr.getString() );
             }
-    
-            // Update the OneLevel index
-            oneLevelIdx.add( parentId, id );
-    
-            // Update the SubLevel index
-            ID tempId = parentId;
-    
-            while ( ( tempId != null ) && ( !tempId.equals( getRootId() ) ) && ( !tempId.equals( getSuffixId() ) ) )
-            {
-                subLevelIdx.add( tempId, id );
-                tempId = getParentId( tempId );
-            }
-    
-            // making entry an ancestor/descendent of itself in sublevel index
-            subLevelIdx.add( id, id );
-    
+
             // Update the EntryCsn index
             Attribute entryCsn = entry.get( ENTRY_CSN_AT );
     
@@ -764,10 +731,10 @@
                 objectClassIdx.drop( value.getString(), id );
             }
 
-            // Update the rdn, oneLevel, subLevel, entryCsn and entryUuid indexes
+            // Update the rdn, entryCsn and entryUuid indexes
+            // TODO: move logic to RdnIndexHelper
+            updateOneAndSubLevelCounters(getParentId( id ), false);
             rdnIdx.drop( id );
-            oneLevelIdx.drop( id );
-            subLevelIdx.drop( id );
             entryCsnIdx.drop( id );
             entryUuidIdx.drop( id );
 
@@ -833,10 +800,9 @@
     {
         try
         {
-            // We use the OneLevel index to get all the entries from a starting point
+            // We use the RDN index to get all the entries from a starting point
             // and below
-            IndexCursor<ID, Entry, ID> cursor = oneLevelIdx.forwardCursor( id );
-            cursor.beforeValue( id, null );
+            IndexCursor<ID, Entry, ID> cursor = rdnIndexHelper.getOneLevelScopeCursor( id );
             
             return cursor;
          }
@@ -983,7 +949,7 @@
      * @return The found Entry, or null if not found
      * @throws Exception If the lookup failed for any reason (except a not found entry)
      */
-    public Entry lookup( ID id ) throws LdapException
+    public final Entry lookup( ID id ) throws LdapException
     {
         try
         {
@@ -1408,10 +1374,8 @@
          * Drop the old parent child relationship and add the new one
          * Set the new parent id for the child replacing the old parent id
          */
-        oneLevelIdx.drop( oldParentId, entryId );
-        oneLevelIdx.add( newParentId, entryId );
-
-        updateSubLevelIndex( entryId, oldParentId, newParentId );
+        updateOneAndSubLevelCounters( oldParentId, false );
+        updateOneAndSubLevelCounters( newParentId, true );
 
         // Update the Rdn index
         rdnIdx.drop( entryId );
@@ -1578,10 +1542,8 @@
          * Drop the old parent child relationship and add the new one
          * Set the new parent id for the child replacing the old parent id
          */
-        oneLevelIdx.drop( oldParentId, childId );
-        oneLevelIdx.add( newParentId, childId );
-
-        updateSubLevelIndex( childId, oldParentId, newParentId );
+        updateOneAndSubLevelCounters( oldParentId, false );
+        updateOneAndSubLevelCounters( newParentId, true );
 
         /*
          * Update the Rdn index
@@ -1661,9 +1623,9 @@
 
         if ( entry == null )
         {
-            entry = master.get( id );
+            entry = lookup( id );
         }
-        
+
         Dn updn = entry.getDn();
 
         newRdn.apply( schemaManager );
@@ -1799,7 +1761,7 @@
      * if it returns an entry by default.  Please override this method if
      * there is more effective way for your implementation.
      */
-    public boolean hasEntry( EntryOperationContext entryContext ) throws LdapException
+    public final boolean hasEntry( EntryOperationContext entryContext ) throws LdapException
     {
         try
         {
@@ -1833,69 +1795,6 @@
     }
 
 
-    /**
-     * Updates the SubLevel Index as part of a move operation.
-     *
-     * @param entryId child id to be moved
-     * @param oldParentId old parent's id
-     * @param newParentId new parent's id
-     * @throws Exception
-     */
-    private void updateSubLevelIndex( ID entryId, ID oldParentId, ID newParentId ) throws Exception
-    {
-        ID tempId = oldParentId;
-        List<ID> parentIds = new ArrayList<ID>();
-
-        // find all the parents of the oldParentId
-        while ( ( tempId != null ) && !tempId.equals( getRootId() ) && !tempId.equals( getSuffixId() ) )
-        {
-            parentIds.add( tempId );
-            tempId = getParentId( tempId );
-        }
-
-        // find all the children of the childId
-        Cursor<IndexEntry<ID, ID>> cursor = subLevelIdx.forwardCursor( entryId );
-
-        List<ID> childIds = new ArrayList<ID>();
-        childIds.add( entryId );
-
-        while ( cursor.next() )
-        {
-            childIds.add( cursor.get().getId() );
-        }
-
-        cursor.close();
-        
-        // detach the childId and all its children from oldParentId and all it parents excluding the root
-        for ( ID pid : parentIds )
-        {
-            for ( ID cid : childIds )
-            {
-                subLevelIdx.drop( pid, cid );
-            }
-        }
-
-        parentIds.clear();
-        tempId = newParentId;
-
-        // find all the parents of the newParentId
-        while ( ( tempId != null)  && !tempId.equals( getRootId() ) && !tempId.equals( getSuffixId() ) )
-        {
-            parentIds.add( tempId );
-            tempId = getParentId( tempId );
-        }
-
-        // attach the childId and all its children to newParentId and all it parents excluding the root
-        for ( ID id : parentIds )
-        {
-            for ( ID cid : childIds )
-            {
-                subLevelIdx.add( id, cid );
-            }
-        }
-    }
-
-
     // ------------------------------------------------------------------------
     // Index and master table Operations
     // ------------------------------------------------------------------------
@@ -1959,7 +1858,9 @@
     {
         try
         {
-            return oneLevelIdx.count( id );
+            long count = rdnIdx.reverseLookup( id ).getOneLevelCount();
+            // TODO: avoid cast
+            return (int)count;
         }
         catch ( Exception e )
         {
@@ -2200,26 +2101,6 @@
      * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    public Index<ID, Entry, ID> getOneLevelIndex()
-    {
-        return ( Index<ID, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @SuppressWarnings("unchecked")
-    public Index<ID, Entry, ID> getSubLevelIndex()
-    {
-        return ( Index<ID, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @SuppressWarnings("unchecked")
     public Index<String, Entry, ID> getAliasIndex()
     {
         return ( Index<String, Entry, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_ALIAS_AT_OID );
@@ -2299,6 +2180,16 @@
     /**
      * {@inheritDoc}
      */
+    @Override
+    public RdnIndexHelper<Entry, ID> getRdnIndexHelper()
+    {
+        return rdnIndexHelper;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public boolean hasUserIndexOn( AttributeType attributeType ) throws LdapException
     {
         return userIndices.containsKey( attributeType.getOid() );
@@ -2564,7 +2455,50 @@
         }
     }
 
-    
+
+    private void updateOneAndSubLevelCounters( ID parentId, boolean increment ) throws Exception
+    {
+        if ( parentId == null )
+        {
+            return;
+        }
+
+        ID rootId = getRootId();
+
+        // update parent one-level count
+        if ( !parentId.equals( rootId ) )
+        {
+            ParentIdAndRdn<ID> piar = rdnIdx.reverseLookup( parentId );
+            if ( increment )
+            {
+                piar.incrementOneLevelCount();
+            }
+            else
+            {
+                piar.decrementOneLevelCount();
+            }
+            rdnIdx.add( piar, parentId );
+        }
+
+        // update sub-level count of all parents
+        while ( !parentId.equals( rootId ) )
+        {
+            ParentIdAndRdn<ID> piar = rdnIdx.reverseLookup( parentId );
+            if ( increment )
+            {
+                piar.incrementSubLevelCount();
+            }
+            else
+            {
+                piar.decrementSubLevelCount();
+            }
+            rdnIdx.add( piar, parentId );
+
+            parentId = piar.getParentId();
+        }
+    }
+
+
     //---------------------------------------------------------------------------------------------
     // Debug methods
     //---------------------------------------------------------------------------------------------
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/ParentIdAndRdn.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/ParentIdAndRdn.java
index 96c3dc2..90971e6 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/ParentIdAndRdn.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/ParentIdAndRdn.java
@@ -26,6 +26,7 @@
 import java.io.ObjectOutput;
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.directory.shared.ldap.model.name.Rdn;
 
@@ -45,12 +46,16 @@
     /** The list of Rdn for this instance */
     protected Rdn[] rdns;
 
+    protected AtomicLong oneLevelCount;
+    protected AtomicLong subLevelCount;
 
     /**
      * Serializable constructor.
      */
     public ParentIdAndRdn()
     {
+        this.oneLevelCount = new AtomicLong();
+        this.subLevelCount = new AtomicLong();
     }
 
 
@@ -62,6 +67,7 @@
      */
     public ParentIdAndRdn( ID parentId, Rdn... rdns )
     {
+        this();
         this.parentId = parentId;
         this.rdns = rdns;
     }
@@ -75,6 +81,7 @@
      */
     public ParentIdAndRdn( ID parentId, List<Rdn> rdns )
     {
+        this();
         this.parentId = parentId;
         this.rdns = rdns.toArray( new Rdn[rdns.size()] );
     }
@@ -124,6 +131,54 @@
     }
 
 
+    public long getOneLevelCount()
+    {
+        return oneLevelCount.get();
+    }
+
+
+    public void setOneLevelCount( long oneLevelCount )
+    {
+        this.oneLevelCount.set( oneLevelCount );
+    }
+
+
+    public void incrementOneLevelCount()
+    {
+        oneLevelCount.incrementAndGet();
+    }
+
+
+    public void decrementOneLevelCount()
+    {
+        oneLevelCount.decrementAndGet();
+    }
+
+
+    public long getSubLevelCount()
+    {
+        return subLevelCount.get();
+    }
+
+
+    public void setSubLevelCount( long subLevelCount )
+    {
+        this.subLevelCount.set( subLevelCount );
+    }
+
+
+    public void incrementSubLevelCount()
+    {
+        subLevelCount.incrementAndGet();
+    }
+
+
+    public void decrementSubLevelCount()
+    {
+        subLevelCount.decrementAndGet();
+    }
+
+
     @Override
     public int hashCode()
     {
@@ -151,7 +206,12 @@
         }
 
         ParentIdAndRdn<ID> that = (ParentIdAndRdn<ID>) obj;
-        
+
+        if ( !parentId.equals( that.parentId ) )
+        {
+            return false;
+        }
+
         if ( rdns == null )
         {
             return that.rdns == null;
@@ -183,7 +243,18 @@
      */
     public int compareTo( ParentIdAndRdn<ID> that )
     {
-        int val = this.rdns.length - that.rdns.length;
+        // Compare the parent id first so that all entries with the same parent
+        // are grouped together in the index. Required for proper function of
+        // RdnIndexTreeCursor.
+        int val = this.getParentId().compareTo( that.getParentId() );
+        
+        if ( val != 0 )
+        {
+            return val;
+        }
+        
+        // Now compare the RDNs
+        val = this.rdns.length - that.rdns.length;
         
         if ( val != 0 )
         {
@@ -199,10 +270,8 @@
                 return val;
             }
         }
-
-        val = this.getParentId().compareTo( that.getParentId() );
         
-        return val;
+        return 0;
     }
 
 
@@ -215,6 +284,8 @@
         {
             rdn.writeExternal( out );
         }
+        out.writeLong( oneLevelCount.get() );
+        out.writeLong( subLevelCount.get() );
     }
 
 
@@ -231,6 +302,9 @@
             rdn.readExternal( in );
             rdns[i] = rdn;
         }
+        
+        oneLevelCount.set( in.readLong() );
+        subLevelCount.set( in.readLong() );
     }
     
     
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Store.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Store.java
index 8c80467..7942f8b 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Store.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/Store.java
@@ -28,6 +28,7 @@
 import java.util.Set;
 
 import org.apache.directory.server.constants.ApacheSchemaConstants;
+import org.apache.directory.server.xdbm.search.impl.RdnIndexHelper;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.entry.Modification;
@@ -91,8 +92,6 @@
     public static final String[] SYS_INDEX_OID_ARRAY =
         { 
             ApacheSchemaConstants.APACHE_PRESENCE_AT_OID,
-            ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID,
-            ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID,
             ApacheSchemaConstants.APACHE_RDN_AT_OID,
             ApacheSchemaConstants.APACHE_N_DN_AT_OID,
             ApacheSchemaConstants.APACHE_ALIAS_AT_OID,
@@ -180,18 +179,6 @@
 
 
     /**
-     * @return The OneLevel system index
-     */
-    Index<ID, E, ID> getOneLevelIndex();
-
-
-    /**
-     * @return The SubLevel system index
-     */
-    Index<ID, E, ID> getSubLevelIndex();
-
-
-    /**
      * @return The Alias system index
      */
     Index<String, E, ID> getAliasIndex();
@@ -213,6 +200,12 @@
      * @return The Rdn system index
      */
     Index<ParentIdAndRdn<ID>, E, ID> getRdnIndex();
+    
+    
+    /**
+     * @return The Rdn index helper
+     */
+    RdnIndexHelper<E, ID> getRdnIndexHelper();
 
 
     /**
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultOptimizer.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultOptimizer.java
index c09968b..d462742 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultOptimizer.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultOptimizer.java
@@ -388,7 +388,7 @@
                 }
                 else
                 {
-                    return db.getSubLevelIndex().count( id );
+                    return db.getRdnIndexHelper().getSubLevelCount( id );
                 }
 
             default:
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeCursor.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeCursor.java
index 17f08c3..a6abc20 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeCursor.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeCursor.java
@@ -46,7 +46,7 @@
 
     /** A onelevel ScopeNode Evaluator */
     @SuppressWarnings("unchecked")
-    private final OneLevelScopeEvaluator evaluator;
+    private final OneLevelScopeEvaluator<Entry, ID> evaluator;
 
     /** A Cursor over the entries in the scope of the search base */
     private final IndexCursor<ID, Entry, ID> scopeCursor;
@@ -71,7 +71,7 @@
     {
         this.db = db;
         this.evaluator = evaluator;
-        scopeCursor = db.getOneLevelIndex().forwardCursor( evaluator.getBaseId() );
+        scopeCursor = db.getRdnIndexHelper().getOneLevelScopeCursor( evaluator.getBaseId() );
 
         if ( evaluator.isDereferencing() )
         {
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeEvaluator.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeEvaluator.java
index b9d87b4..2804284 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeEvaluator.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeEvaluator.java
@@ -81,7 +81,7 @@
      */
     public boolean evaluateId( ID candidate ) throws Exception
     {
-        boolean isChild = db.getOneLevelIndex().forward( baseId, candidate );
+        boolean isChild = db.getRdnIndexHelper().isDirectDescendantOf( baseId, candidate );
 
         /*
          * The candidate id could be any entry in the db.  If search
@@ -152,7 +152,7 @@
      */
     public boolean evaluate( IndexEntry<?, ID> candidate ) throws Exception
     {
-        boolean isChild = db.getOneLevelIndex().forward( baseId, candidate.getId() );
+        boolean isChild = db.getRdnIndexHelper().isDirectDescendantOf( baseId, candidate.getId() );
 
         /*
          * The candidate id could be any entry in the db.  If search
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/RdnIndexHelper.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/RdnIndexHelper.java
new file mode 100644
index 0000000..2817fd7
--- /dev/null
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/RdnIndexHelper.java
@@ -0,0 +1,143 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.xdbm.search.impl;
+
+
+import org.apache.directory.server.xdbm.Index;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.server.xdbm.ParentIdAndRdn;
+
+
+/**
+ * Wrapper around the RDN index with helper functions.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class RdnIndexHelper<E, ID extends Comparable<ID>>
+{
+    private final Index<ParentIdAndRdn<ID>, E, ID> rdnIndex;
+    private final ID rootId;
+
+
+    public RdnIndexHelper( Index<ParentIdAndRdn<ID>, E, ID> rdnIndex, ID rootId )
+    {
+        this.rdnIndex = rdnIndex;
+        this.rootId = rootId;
+    }
+
+
+    /**
+     * Checks if the <code>descendantId</code> is a <em>direct</em> descendant
+     * of the <code>ancestorId</code>.
+     *
+     * @param ancestorId the ancestor
+     * @param descendantId the descendant
+     * @return <code>true</code> if <code>descendantId</code> is a <em>direct</em> descendant 
+     *         of <code>ancestorId</code>
+     * @throws Exception
+     */
+    public boolean isDirectDescendantOf( ID ancestorId, ID descendantId ) throws Exception
+    {
+        if ( descendantId.equals( rootId ) )
+        {
+            return false;
+        }
+
+        ParentIdAndRdn<ID> parentIdAndRdn = rdnIndex.reverseLookup( descendantId );
+
+        if ( parentIdAndRdn == null )
+        {
+            throw new IllegalArgumentException( "ID " + descendantId + " not found in RDN index." );
+        }
+
+        boolean isParent = ancestorId.equals( parentIdAndRdn.getParentId() );
+        return isParent;
+    }
+
+
+    /**
+     * Checks if the <code>descendantId</code> is a descendant of the <code>ancestorId</code>.
+     *
+     * @param ancestorId the ancestor
+     * @param descendantId the descendant
+     * @return <code>true</code> if <code>descendantId</code> is a descendant 
+     *         of <code>ancestorId</code>
+     * @throws Exception
+     */
+    public boolean isDescendantOf( ID ancestorId, ID descendantId ) throws Exception
+    {
+        if ( descendantId.equals( rootId ) )
+        {
+            return false;
+        }
+
+        ID id = descendantId;
+
+        while ( !id.equals( rootId ) )
+        {
+            ParentIdAndRdn<ID> parentIdAndRdn = rdnIndex.reverseLookup( id );
+
+            if ( parentIdAndRdn == null )
+            {
+                throw new IllegalArgumentException( "ID " + descendantId + " not found in RDN index." );
+            }
+
+            boolean isParent = ancestorId.equals( parentIdAndRdn.getParentId() );
+
+            if ( isParent )
+            {
+                return true;
+            }
+
+            id = parentIdAndRdn.getParentId();
+        }
+
+        return false;
+    }
+
+
+    public long getOneLevelCount( ID id ) throws Exception
+    {
+        long count = rdnIndex.reverseLookup( id ).getOneLevelCount();
+        return count;
+    }
+
+
+    public long getSubLevelCount( ID id ) throws Exception
+    {
+        long count = rdnIndex.reverseLookup( id ).getSubLevelCount();
+        return count;
+    }
+
+
+    public IndexCursor<ID, E, ID> getOneLevelScopeCursor( ID id ) throws Exception
+    {
+        RdnIndexTreeCursor<E, ID> cursor = new RdnIndexTreeCursor<E, ID>( rdnIndex, id, true );
+        return cursor;
+    }
+
+
+    public IndexCursor<ID, E, ID> getSubLevelScopeCursor( ID id ) throws Exception
+    {
+        RdnIndexTreeCursor<E, ID> cursor = new RdnIndexTreeCursor<E, ID>( rdnIndex, id, false );
+        return cursor;
+    }
+
+}
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/RdnIndexTreeCursor.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/RdnIndexTreeCursor.java
new file mode 100644
index 0000000..dffb287
--- /dev/null
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/RdnIndexTreeCursor.java
@@ -0,0 +1,492 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.directory.server.xdbm.search.impl;
+
+
+import java.util.Deque;
+import java.util.LinkedList;
+
+import org.apache.directory.server.xdbm.AbstractIndexCursor;
+import org.apache.directory.server.xdbm.ForwardIndexEntry;
+import org.apache.directory.server.xdbm.Index;
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.server.xdbm.IndexEntry;
+import org.apache.directory.server.xdbm.ParentIdAndRdn;
+import org.apache.directory.shared.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.shared.ldap.model.name.Rdn;
+
+
+/**
+ * A Cursor that traverses the RDN index as a tree.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class RdnIndexTreeCursor<E, ID extends Comparable<ID>> extends AbstractIndexCursor<ID, E, ID>
+{
+
+    /** Special RDN used as end marker of a tree level. Also used as marker afterLast()/last() operations */
+    private static final Rdn STOP_ELEMENT;
+    static
+    {
+        try
+        {
+            STOP_ELEMENT = new Rdn( "zzz=zzz" );
+        }
+        catch ( LdapInvalidDnException e )
+        {
+            throw new RuntimeException( "Error initializing stop element", e );
+        }
+    }
+
+    private final Index<ParentIdAndRdn<ID>, E, ID> rdnIndex;
+    private final ID startId;
+    private final boolean oneLevel;
+
+    /** 
+     * A stack containing all cursors. On construction the root cursor is added. 
+     * While the tree is traversed in depth-first order more cursors are added and removed.
+     * The root cursor is never removed.
+     */
+    private final CursorStack cursors;
+
+    /** Whether or not this Cursor is positioned so an entry is available */
+    private boolean available;
+
+
+    public RdnIndexTreeCursor( Index<ParentIdAndRdn<ID>, E, ID> rdnIndex, ID startId, boolean oneLevel )
+        throws Exception
+    {
+        this.rdnIndex = rdnIndex;
+        this.startId = startId;
+        this.oneLevel = oneLevel;
+
+        this.cursors = new CursorStack();
+
+        if ( oneLevel )
+        {
+            this.cursors.createChildCursor( startId );
+        }
+        else
+        {
+            this.cursors.createChildCursor( rdnIndex.reverseLookup( startId ) );
+        }
+
+        beforeFirst();
+    }
+
+
+    public boolean available()
+    {
+        return available;
+    }
+
+
+    public void before( IndexEntry<ID, ID> element ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void beforeValue( ID id, ID value ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void afterValue( ID id, ID value ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void after( IndexEntry<ID, ID> element ) throws Exception
+    {
+        throw new UnsupportedOperationException();
+    }
+
+
+    public void beforeFirst() throws Exception
+    {
+        checkNotClosed( "beforeFirst()" );
+
+        // remove and close all but the root cursors in the stack
+        while ( cursors.size() > 1 )
+        {
+            cursors.closeCurrentCursor();
+        }
+
+        // position the root cursor
+        cursors.getCurrentCursor().before( cursors.getCurrentCursorStartElement() );
+        available = false;
+    }
+
+
+    public void afterLast() throws Exception
+    {
+        checkNotClosed( "afterLast()" );
+
+        // remove and close all but the root cursors in the stack
+        while ( cursors.size() > 1 )
+        {
+            cursors.closeCurrentCursor();
+        }
+
+        // position the root cursor
+        cursors.getCurrentCursor().after( cursors.getCurrentCursorStopElement() );
+        available = false;
+    }
+
+
+    public boolean first() throws Exception
+    {
+        checkNotClosed( "first()" );
+        beforeFirst();
+        return next();
+    }
+
+
+    public boolean last() throws Exception
+    {
+        checkNotClosed( "last()" );
+        afterLast();
+        return previous();
+    }
+
+
+    public boolean previous() throws Exception
+    {
+        checkNotClosed( "previous()" );
+        if ( oneLevel )
+        {
+            return previousOneLevel();
+        }
+        else
+        {
+            return previousSubLevel();
+        }
+    }
+
+
+    private boolean previousOneLevel() throws Exception
+    {
+        return previousCurrentLevel();
+    }
+
+
+    private boolean previousSubLevel() throws Exception
+    {
+        if ( previousCurrentLevel() )
+        {
+            // depth first traversal: check if previous index entry has children
+            do
+            {
+                ID id = cursors.getCurrentCursor().get().getId();
+                cursors.createChildCursor( id );
+                cursors.getCurrentCursor().after( cursors.getCurrentCursorStopElement() );
+            }
+            while ( previousCurrentLevel() );
+
+            cursors.closeCurrentCursor();
+
+            available = true;
+            return true;
+        }
+
+        // back one level
+        if ( cursors.size() > 1 )
+        {
+            cursors.closeCurrentCursor();
+            available = true;
+            return true;
+        }
+
+        return false;
+    }
+
+
+    private boolean previousCurrentLevel() throws Exception
+    {
+        if ( cursors.getCurrentCursor().previous() )
+        {
+            // Compare the previous index entry's parent with the start element
+            IndexEntry<ParentIdAndRdn<ID>, ID> indexEntry = cursors.getCurrentCursor().get();
+            ParentIdAndRdn<ID> currentParentIdAndRdn = indexEntry.getValue();
+            ParentIdAndRdn<ID> startParentIdAndRdn = cursors.getCurrentCursorStartElement().getValue();
+            if ( currentParentIdAndRdn.getParentId().equals( startParentIdAndRdn.getParentId() )
+                && currentParentIdAndRdn.compareTo( startParentIdAndRdn ) >= 0 )
+            {
+                available = true;
+                return true;
+            }
+            else
+            {
+                cursors.getCurrentCursor().next();
+                available = false;
+                return false;
+            }
+        }
+        else
+        {
+            available = false;
+            return false;
+        }
+    }
+
+
+    public boolean next() throws Exception
+    {
+        checkNotClosed( "next()" );
+        if ( oneLevel )
+        {
+            return nextOneLevel();
+        }
+        else
+        {
+            return nextSubLevel();
+        }
+    }
+
+
+    private boolean nextOneLevel() throws Exception
+    {
+        return nextCurrentLevel();
+    }
+
+
+    private boolean nextSubLevel() throws Exception
+    {
+        // depth first traversal: check if current index entry has children
+        // TODO: use one-level count for optimization
+        if ( available )
+        {
+            ID id = cursors.getCurrentCursor().get().getId();
+            cursors.createChildCursor( id );
+            cursors.getCurrentCursor().before( cursors.getCurrentCursorStartElement() );
+            if ( nextCurrentLevel() )
+            {
+                return true;
+            }
+            else
+            {
+                cursors.closeCurrentCursor();
+            }
+        }
+
+        // next element at current level
+        if ( nextCurrentLevel() )
+        {
+            return true;
+        }
+
+        // back one level
+        while ( cursors.size() > 1 )
+        {
+            cursors.closeCurrentCursor();
+            if ( nextCurrentLevel() )
+            {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+
+    private boolean nextCurrentLevel() throws Exception
+    {
+        if ( cursors.getCurrentCursor().next() )
+        {
+            // Compare the next index entry's parent with the stop element
+            IndexEntry<ParentIdAndRdn<ID>, ID> indexEntry = cursors.getCurrentCursor().get();
+            ParentIdAndRdn<ID> currentParentIdAndRdn = indexEntry.getValue();
+            ParentIdAndRdn<ID> stopParentIdAndRdn = cursors.getCurrentCursorStopElement().getValue();
+            if ( currentParentIdAndRdn.getParentId().equals( stopParentIdAndRdn.getParentId() )
+                && currentParentIdAndRdn.compareTo( stopParentIdAndRdn ) <= 0 )
+            {
+                available = true;
+                return true;
+            }
+            else
+            {
+                cursors.getCurrentCursor().previous();
+                available = false;
+                return false;
+            }
+        }
+        else
+        {
+            available = false;
+            return false;
+        }
+    }
+
+
+    @Override
+    public IndexEntry<ID, ID> get() throws Exception
+    {
+        IndexEntry<ParentIdAndRdn<ID>, ID> wrappedEntry = cursors.getCurrentCursor().get();
+        IndexEntry<ID, ID> entry = new ForwardIndexEntry<ID, ID>();
+        entry.setValue( startId );
+        //entry.setValue( wrappedEntry.getValue().getParentId() );
+        entry.setId( wrappedEntry.getId() );
+        return entry;
+    }
+
+
+    @Override
+    public void close() throws Exception
+    {
+        super.close();
+        while ( cursors.size() > 0 )
+        {
+            cursors.closeCurrentCursor();
+        }
+    }
+
+
+    @Override
+    public void close( Exception cause ) throws Exception
+    {
+        super.close( cause );
+        while ( cursors.size() > 0 )
+        {
+            cursors.closeCurrentCursor();
+        }
+    }
+
+
+    @Override
+    protected String getUnsupportedMessage()
+    {
+        return "Unsupported operation";
+    }
+
+    private class CursorStack
+    {
+        private final Deque<CursorStackEntry> cursorStack;
+
+
+        public CursorStack()
+        {
+            this.cursorStack = new LinkedList<CursorStackEntry>();
+        }
+
+
+        public void createChildCursor( ID startId ) throws Exception
+        {
+            CursorStackEntry entry = new CursorStackEntry( startId );
+            cursorStack.addFirst( entry );
+        }
+
+
+        public void createChildCursor( ParentIdAndRdn<ID> parentIdAndRdn ) throws Exception
+        {
+            CursorStackEntry entry = new CursorStackEntry( parentIdAndRdn );
+            cursorStack.addFirst( entry );
+        }
+
+
+        /**
+         * @return the current cursor from the cursor stack
+         */
+        public IndexCursor<ParentIdAndRdn<ID>, E, ID> getCurrentCursor()
+        {
+            IndexCursor<ParentIdAndRdn<ID>, E, ID> cursor = cursorStack.getFirst().cursor;
+            return cursor;
+        }
+
+
+        /**
+         * @return the current cursor's start element from the cursor stack
+         */
+        public IndexEntry<ParentIdAndRdn<ID>, ID> getCurrentCursorStartElement()
+        {
+            IndexEntry<ParentIdAndRdn<ID>, ID> startElement = cursorStack.getFirst().startElement;
+            return startElement;
+        }
+
+
+        /**
+         * @return the current cursor's stop element from the cursor stack
+         */
+        public IndexEntry<ParentIdAndRdn<ID>, ID> getCurrentCursorStopElement()
+        {
+            IndexEntry<ParentIdAndRdn<ID>, ID> startElement = cursorStack.getFirst().stopElement;
+            return startElement;
+        }
+
+
+        public void closeCurrentCursor() throws Exception
+        {
+            cursorStack.removeFirst().cursor.close();
+        }
+
+
+        public int size()
+        {
+            return cursorStack.size();
+        }
+
+
+        @Override
+        public String toString()
+        {
+            return "CursorStack [cursorStack=" + cursorStack + "]";
+        }
+
+        private class CursorStackEntry
+        {
+            private final IndexCursor<ParentIdAndRdn<ID>, E, ID> cursor;
+            private final IndexEntry<ParentIdAndRdn<ID>, ID> startElement;
+            private final IndexEntry<ParentIdAndRdn<ID>, ID> stopElement;
+
+
+            public CursorStackEntry( ID startId ) throws Exception
+            {
+                this.cursor = rdnIndex.forwardCursor();
+                this.startElement = createElement( new ParentIdAndRdn<ID>( startId ) );
+                this.stopElement = createElement( new ParentIdAndRdn<ID>( startId, STOP_ELEMENT ) );
+            }
+
+
+            public CursorStackEntry( ParentIdAndRdn<ID> parentIdAndRdn ) throws Exception
+            {
+                this.cursor = rdnIndex.forwardCursor();
+                this.startElement = createElement( parentIdAndRdn );
+                this.stopElement = createElement( parentIdAndRdn );
+            }
+
+
+            private IndexEntry<ParentIdAndRdn<ID>, ID> createElement( ParentIdAndRdn<ID> parentIdAndRdn )
+            {
+                IndexEntry<ParentIdAndRdn<ID>, ID> startElement = new ForwardIndexEntry<ParentIdAndRdn<ID>, ID>();
+                startElement.setValue( parentIdAndRdn );
+                return startElement;
+            }
+
+
+            @Override
+            public String toString()
+            {
+                //return "CSE:" + startElement.getValue().getParentId();
+                return "CSE:" + startElement;
+            }
+        }
+    }
+}
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeCursor.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeCursor.java
index 04e8717..a5b366e 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeCursor.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeCursor.java
@@ -77,7 +77,7 @@
         }
         else
         {
-            scopeCursor = db.getSubLevelIndex().forwardCursor( evaluator.getBaseId() );
+            scopeCursor = db.getRdnIndexHelper().getSubLevelScopeCursor( evaluator.getBaseId() );
         }
 
         if ( evaluator.isDereferencing() )
diff --git a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeEvaluator.java b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeEvaluator.java
index 1327454..93e6182 100644
--- a/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeEvaluator.java
+++ b/xdbm-partition/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeEvaluator.java
@@ -134,7 +134,8 @@
          * to all it's subordinates since that would be the entire set of 
          * entries in the db.
          */
-        boolean isDescendant = baseIsContextEntry || baseId.equals( id ) || db.getSubLevelIndex().forward( baseId, id );
+        boolean isDescendant = baseIsContextEntry || baseId.equals( id )
+            || db.getRdnIndexHelper().isDescendantOf( baseId, id );
 
         /*
          * The candidate id could be any entry in the db.  If search
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/PartitionTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/PartitionTest.java
index 9bc8d7b..68b8d90 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/PartitionTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/PartitionTest.java
@@ -147,8 +147,6 @@
     public void testExampleDataIndices() throws Exception
     {
         assertEquals( 11, partition.getRdnIndex().count() );
-        assertEquals( 11, partition.getOneLevelIndex().count() );
-        assertEquals( 19, partition.getSubLevelIndex().count() );
         assertEquals( 3, partition.getAliasIndex().count() );
         assertEquals( 3, partition.getOneAliasIndex().count() );
         assertEquals( 3, partition.getSubAliasIndex().count() );
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/impl/avl/AvlPartitionTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/impl/avl/AvlPartitionTest.java
index 2fbbff3..5f89747 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/impl/avl/AvlPartitionTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/impl/avl/AvlPartitionTest.java
@@ -173,14 +173,6 @@
         avlPartition.addIndex( new AvlIndex<String, Entry>( ApacheSchemaConstants.APACHE_PRESENCE_AT_OID ) );
         assertNotNull( avlPartition.getPresenceIndex() );
 
-        assertNull( avlPartition.getOneLevelIndex() );
-        avlPartition.addIndex( new AvlIndex<Long, Entry>( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID ) );
-        assertNotNull( avlPartition.getOneLevelIndex() );
-
-        assertNull( avlPartition.getSubLevelIndex() );
-        avlPartition.addIndex( new AvlIndex<Long, Entry>( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID ) );
-        assertNotNull( avlPartition.getSubLevelIndex() );
-
         assertNull( avlPartition.getId() );
         avlPartition.setId( "foo" );
         assertEquals( "foo", avlPartition.getId() );
@@ -247,28 +239,6 @@
         {
         }
 
-        assertNotNull( partition.getOneLevelIndex() );
-        
-        try
-        {
-            partition.addIndex( new AvlIndex<Long, Entry>( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID ) );
-            //fail();
-        }
-        catch ( IllegalStateException e )
-        {
-        }
-
-        assertNotNull( partition.getSubLevelIndex() );
-        
-        try
-        {
-            partition.addIndex( new AvlIndex<Long, Entry>( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID ) );
-            //fail();
-        }
-        catch ( IllegalStateException e )
-        {
-        }
-
         assertNotNull( partition.getId() );
         
         try
@@ -318,7 +288,7 @@
         
         Iterator<String> systemIndices = partition.getSystemIndices();
 
-        for ( int i = 0; i < 10; i++ )
+        for ( int i = 0; i < 8; i++ )
         {
             assertTrue( systemIndices.hasNext() );
             assertNotNull( systemIndices.next() );
@@ -419,8 +389,12 @@
         assertNotNull( cursor );
         cursor.beforeFirst();
         assertTrue( cursor.next() );
-        assertEquals( 2L, ( long ) cursor.get().getId() );
+        assertEquals( 3L, ( long ) cursor.get().getId() );
         assertTrue( cursor.next() );
+        assertEquals( 4L, ( long ) cursor.get().getId() );
+        assertTrue( cursor.next() );
+        assertEquals( 2L, ( long ) cursor.get().getId() );
+        assertFalse( cursor.next() );
         assertEquals( 3, partition.getChildCount( 1L ) );
 
         partition.delete( 2L );
@@ -446,119 +420,6 @@
 
 
     @Test
-    public void testSubLevelIndex() throws Exception
-    {
-        Index idx = partition.getSubLevelIndex();
-
-        assertEquals( 19, idx.count() );
-
-        Cursor<IndexEntry<Long, Long>> cursor = idx.forwardCursor( 2L );
-
-        assertTrue( cursor.next() );
-        assertEquals( 2, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.next() );
-        assertEquals( 5, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.next() );
-        assertEquals( 6, ( long ) cursor.get().getId() );
-
-        assertFalse( cursor.next() );
-
-        idx.drop( 5L );
-
-        cursor = idx.forwardCursor( 2L );
-
-        assertTrue( cursor.next() );
-        assertEquals( 2, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.next() );
-        assertEquals( 6, ( long ) cursor.get().getId() );
-
-        assertFalse( cursor.next() );
-
-        // dn id 12
-        Dn martinDn = new Dn( schemaManager, "cn=Marting King,ou=Sales,o=Good Times Co." );
-        DefaultEntry entry = new DefaultEntry( schemaManager, martinDn );
-        entry.add( "objectClass", "top", "person", "organizationalPerson" );
-        entry.add( "ou", "Sales" );
-        entry.add( "cn", "Martin King" );
-        entry.add( "entryCSN", new CsnFactory( 1 ).newInstance().toString() );
-        entry.add( "entryUUID", UUID.randomUUID().toString() );
-
-        AddOperationContext addContext = new AddOperationContext( null, entry );
-        partition.add( addContext );
-
-        cursor = idx.forwardCursor( 2L );
-        cursor.afterLast();
-        assertTrue( cursor.previous() );
-        assertEquals( 12, ( long ) cursor.get().getId() );
-
-        Dn newParentDn = new Dn( schemaManager, "ou=Board of Directors,o=Good Times Co." );
-
-        Dn newDn = newParentDn.add( martinDn.getRdn() );
-        partition.move( martinDn, newParentDn, newDn, new ClonedServerEntry( entry ) );
-
-        cursor = idx.forwardCursor( 3L );
-        cursor.afterLast();
-        assertTrue( cursor.previous() );
-        assertEquals( 12, ( long ) cursor.get().getId() );
-
-        // dn id 13
-        Dn marketingDn = new Dn( schemaManager, "ou=Marketing,ou=Sales,o=Good Times Co." );
-        entry = new DefaultEntry( schemaManager, marketingDn );
-        entry.add( "objectClass", "top", "organizationalUnit" );
-        entry.add( "ou", "Marketing" );
-        entry.add( "entryCSN", new CsnFactory( 1 ).newInstance().toString() );
-        entry.add( "entryUUID", UUID.randomUUID().toString() );
-
-        addContext = new AddOperationContext( null, entry );
-        partition.add( addContext );
-
-        // dn id 14
-        Dn jimmyDn = new Dn( schemaManager, "cn=Jimmy Wales,ou=Marketing, ou=Sales,o=Good Times Co." );
-        entry = new DefaultEntry( schemaManager, jimmyDn );
-        entry.add( "objectClass", "top", "person", "organizationalPerson" );
-        entry.add( "ou", "Marketing" );
-        entry.add( "cn", "Jimmy Wales" );
-        entry.add( "entryCSN", new CsnFactory( 1 ).newInstance().toString() );
-        entry.add( "entryUUID", UUID.randomUUID().toString() );
-
-        addContext = new AddOperationContext( null, entry );
-        partition.add( addContext );
-
-        newDn = newParentDn.add( marketingDn.getRdn() );
-        partition.move( marketingDn, newParentDn, newDn, new ClonedServerEntry( entry ) );
-
-        cursor = idx.forwardCursor( 3L );
-        cursor.afterLast();
-
-        assertTrue( cursor.previous() );
-        assertEquals( 14, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 13, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 12, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 10, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 9, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 7, ( long ) cursor.get().getId() );
-
-        assertTrue( cursor.previous() );
-        assertEquals( 3, ( long ) cursor.get().getId() );
-
-        assertFalse( cursor.previous() );
-    }
-
-
-    @Test
     public void testConvertIndex() throws Exception
     {
         Index nonAvlIndex = new GenericIndex( "ou", 10, new File( "." ).toURI() );
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/AndCursorTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/AndCursorTest.java
index bf27566..ac3f9e2 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/AndCursorTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/AndCursorTest.java
@@ -25,20 +25,12 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
 import org.apache.directory.server.xdbm.IndexCursor;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.server.xdbm.search.Evaluator;
-import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.filter.AndNode;
@@ -46,19 +38,8 @@
 import org.apache.directory.shared.ldap.model.filter.FilterParser;
 import org.apache.directory.shared.ldap.model.filter.PresenceNode;
 import org.apache.directory.shared.ldap.model.filter.SubstringNode;
-import org.apache.directory.shared.ldap.model.name.Dn;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -67,104 +48,17 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class AndCursorTest
+public class AndCursorTest extends TestBase
 {
-    private static final Logger LOG = LoggerFactory.getLogger( AndCursorTest.class.getSimpleName() );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    EvaluatorBuilder evaluatorBuilder;
-    CursorBuilder cursorBuilder;
-    private static SchemaManager schemaManager;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        // setup the standard registries
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = AndCursorTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( "collective" );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
-
-
-    public AndCursorTest() throws Exception
-    {
-    }
+    EvaluatorBuilder<Long> evaluatorBuilder;
+    CursorBuilder<Long> cursorBuilder;
 
 
     @Before
-    public void createStore() throws Exception
+    public void createBuilder() throws Exception
     {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( false );
-
-        store.addIndex( new AvlIndex( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.CN_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        ((Partition)store).initialize();
-        
-        StoreUtils.loadExampleData( store, schemaManager );
-
-        evaluatorBuilder = new EvaluatorBuilder( store, schemaManager );
-        cursorBuilder = new CursorBuilder( store, evaluatorBuilder );
-
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
+        evaluatorBuilder = new EvaluatorBuilder<Long>( store, schemaManager );
+        cursorBuilder = new CursorBuilder<Long>( store, evaluatorBuilder );
     }
 
 
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/GreaterEqTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/GreaterEqTest.java
index 1c070de..8b2afa3 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/GreaterEqTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/GreaterEqTest.java
@@ -26,21 +26,15 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
-import org.apache.commons.io.FileUtils;
 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
 import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.csn.CsnFactory;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
@@ -53,20 +47,9 @@
 import org.apache.directory.shared.ldap.model.schema.AttributeType;
 import org.apache.directory.shared.ldap.model.schema.LdapSyntax;
 import org.apache.directory.shared.ldap.model.schema.MatchingRule;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
 import org.apache.directory.shared.ldap.model.schema.comparators.StringComparator;
 import org.apache.directory.shared.ldap.model.schema.parsers.SyntaxCheckerDescription;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -74,94 +57,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class GreaterEqTest
+public class GreaterEqTest extends TestBase
 {
-    public static final Logger LOG = LoggerFactory.getLogger( GreaterEqTest.class );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        // setup the standard registries
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = GreaterEqTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
-
-
-    @Before
-    public void createStore() throws Exception
-    {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( false );
-
-        store.addIndex( new AvlIndex( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.CN_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.POSTALCODE_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        StoreUtils.loadExampleData( store, schemaManager );
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
-    }
-
 
     @Test
     public void testCursorIndexed() throws Exception
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/LessEqTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/LessEqTest.java
index 3422bc3..f5d6378 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/LessEqTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/LessEqTest.java
@@ -26,21 +26,15 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.UUID;
 
-import org.apache.commons.io.FileUtils;
 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
 import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.csn.CsnFactory;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
@@ -53,20 +47,9 @@
 import org.apache.directory.shared.ldap.model.schema.AttributeType;
 import org.apache.directory.shared.ldap.model.schema.LdapSyntax;
 import org.apache.directory.shared.ldap.model.schema.MatchingRule;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
 import org.apache.directory.shared.ldap.model.schema.comparators.StringComparator;
 import org.apache.directory.shared.ldap.model.schema.parsers.SyntaxCheckerDescription;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -74,96 +57,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class LessEqTest
+public class LessEqTest extends TestBase
 {
-    public static final Logger LOG = LoggerFactory.getLogger( LessEqTest.class );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        // setup the standard registries
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = AndCursorTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
-
-
-    @Before
-    public void createStore() throws Exception
-    {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( false );
-
-        store.addIndex( new AvlIndex( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.CN_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.POSTALCODE_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        ((Partition)store).initialize();
-
-        StoreUtils.loadExampleData( store, schemaManager );
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
-    }
-
 
     @Test
     public void testCursorIndexed() throws Exception
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/NotCursorTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/NotCursorTest.java
index a841c14..fcb5f48 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/NotCursorTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/NotCursorTest.java
@@ -25,40 +25,21 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
 import org.apache.directory.server.xdbm.IndexCursor;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.server.xdbm.search.Evaluator;
-import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.filter.ExprNode;
 import org.apache.directory.shared.ldap.model.filter.FilterParser;
 import org.apache.directory.shared.ldap.model.filter.NotNode;
 import org.apache.directory.shared.ldap.model.filter.SubstringNode;
-import org.apache.directory.shared.ldap.model.name.Dn;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
 import org.apache.directory.shared.ldap.model.schema.syntaxCheckers.UuidSyntaxChecker;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -67,102 +48,19 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class NotCursorTest
+public class NotCursorTest extends TestBase
 {
-    private static final Logger LOG = LoggerFactory.getLogger( NotCursorTest.class.getSimpleName() );
-
     UuidSyntaxChecker uuidSynChecker = new UuidSyntaxChecker();
 
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-    EvaluatorBuilder evaluatorBuilder;
-    CursorBuilder cursorBuilder;
-
-
-    @BeforeClass
-    static public void setup() throws Exception
-    {
-        // setup the standard registries
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = NotCursorTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
+    EvaluatorBuilder<Long> evaluatorBuilder;
+    CursorBuilder<Long> cursorBuilder;
 
 
     @Before
-    public void createStore() throws Exception
+    public void createBuilders() throws Exception
     {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( false );
-
-        store.addIndex( new AvlIndex( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.CN_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        ((Partition)store).initialize();
-        
-        StoreUtils.loadExampleData( store, schemaManager );
-
-        evaluatorBuilder = new EvaluatorBuilder( store, schemaManager );
-        cursorBuilder = new CursorBuilder( store, evaluatorBuilder );
-
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
+        evaluatorBuilder = new EvaluatorBuilder<Long>( store, schemaManager );
+        cursorBuilder = new CursorBuilder<Long>( store, evaluatorBuilder );
     }
 
 
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeTest.java
index 0442e7d..74b0a79 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeTest.java
@@ -24,20 +24,13 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.UUID;
 
-import org.apache.commons.io.FileUtils;
 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
 import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
 import org.apache.directory.server.xdbm.IndexEntry;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.csn.CsnFactory;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
@@ -47,18 +40,7 @@
 import org.apache.directory.shared.ldap.model.message.AliasDerefMode;
 import org.apache.directory.shared.ldap.model.message.SearchScope;
 import org.apache.directory.shared.ldap.model.name.Dn;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -66,95 +48,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class OneLevelScopeTest
+public class OneLevelScopeTest extends TestBase
 {
-    public static final Logger LOG = LoggerFactory.getLogger( OneLevelScopeTest.class );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        // setup the standard registries
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = OneLevelScopeTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
-
-
-    @Before
-    public void createStore() throws Exception
-    {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( true );
-
-        store.addIndex( new AvlIndex<String, Entry>( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex<String, Entry>( SchemaConstants.CN_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        ((Partition)store).initialize();
-
-        StoreUtils.loadExampleData( store, schemaManager );
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
-    }
-
 
     @Test
     public void testCursorNoDeref() throws Exception
@@ -174,14 +69,14 @@
         assertTrue( cursor.available() );
         IndexEntry<Long, Long> indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.next() );
@@ -196,14 +91,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.next() );
@@ -219,14 +114,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.previous() );
@@ -241,14 +136,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.previous() );
@@ -263,14 +158,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.previous() );
@@ -285,14 +180,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.next() );
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OrCursorTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OrCursorTest.java
index cc63249..5236d57 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OrCursorTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/OrCursorTest.java
@@ -25,21 +25,13 @@
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
 import org.apache.directory.server.xdbm.IndexCursor;
 import org.apache.directory.server.xdbm.IndexEntry;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.server.xdbm.search.Evaluator;
-import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.cursor.Cursor;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
 import org.apache.directory.shared.ldap.model.entry.Entry;
@@ -47,19 +39,8 @@
 import org.apache.directory.shared.ldap.model.filter.FilterParser;
 import org.apache.directory.shared.ldap.model.filter.OrNode;
 import org.apache.directory.shared.ldap.model.filter.SubstringNode;
-import org.apache.directory.shared.ldap.model.name.Dn;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
 import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -72,98 +53,17 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class OrCursorTest
+public class OrCursorTest extends TestBase
 {
-    private static final Logger LOG = LoggerFactory.getLogger( OrCursorTest.class.getSimpleName() );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-    EvaluatorBuilder evaluatorBuilder;
-    CursorBuilder cursorBuilder;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = OrCursorTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
+    EvaluatorBuilder<Long> evaluatorBuilder;
+    CursorBuilder<Long> cursorBuilder;
 
 
     @Before
-    public void createStore() throws Exception
+    public void createBuilder() throws Exception
     {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( false );
-
-        store.addIndex( new AvlIndex( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.CN_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        ((Partition)store).initialize();
-
-        StoreUtils.loadExampleData( store, schemaManager );
-
-        evaluatorBuilder = new EvaluatorBuilder( store, schemaManager );
-        cursorBuilder = new CursorBuilder( store, evaluatorBuilder );
-
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
+        evaluatorBuilder = new EvaluatorBuilder<Long>( store, schemaManager );
+        cursorBuilder = new CursorBuilder<Long>( store, evaluatorBuilder );
     }
 
 
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/PresenceTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/PresenceTest.java
index 21fd033..ad30ca4 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/PresenceTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/PresenceTest.java
@@ -23,38 +23,18 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
-import org.apache.commons.io.FileUtils;
-import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.filter.PresenceNode;
-import org.apache.directory.shared.ldap.model.name.Dn;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -62,95 +42,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class PresenceTest
+public class PresenceTest extends TestBase
 {
-    private static final Logger LOG = LoggerFactory.getLogger( PresenceTest.class.getSimpleName() );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = PresenceTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
-
-
-    @Before
-    public void createStore() throws Exception
-    {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( false );
-
-        store.addIndex( new AvlIndex( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.CN_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        ((Partition)store).initialize();
-
-        StoreUtils.loadExampleData( store, schemaManager );
-        
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
-    }
-
 
     @Test
     public void testIndexedServerEntry() throws Exception
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/RdnIndexHelperTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/RdnIndexHelperTest.java
new file mode 100644
index 0000000..f29617e
--- /dev/null
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/RdnIndexHelperTest.java
@@ -0,0 +1,147 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.xdbm.search.impl;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.junit.Test;
+
+
+/**
+ * Tests {@link RdnIndexHelper}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class RdnIndexHelperTest extends TestBase
+{
+
+    @Test
+    public void test_isDirectDescendantOf_directDescendants() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertTrue( helper.isDirectDescendantOf( 0L, 1L ) );
+        assertTrue( helper.isDirectDescendantOf( 1L, 3L ) );
+        assertTrue( helper.isDirectDescendantOf( 3L, 7L ) );
+        assertTrue( helper.isDirectDescendantOf( 7L, 9L ) );
+    }
+
+
+    @Test
+    public void test_isDirectDescendantOf_indirectDescendants() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertFalse( helper.isDirectDescendantOf( 0L, 3L ) );
+        assertFalse( helper.isDirectDescendantOf( 0L, 7L ) );
+        assertFalse( helper.isDirectDescendantOf( 0L, 9L ) );
+        assertFalse( helper.isDirectDescendantOf( 1L, 7L ) );
+        assertFalse( helper.isDirectDescendantOf( 1L, 9L ) );
+        assertFalse( helper.isDirectDescendantOf( 3L, 9L ) );
+    }
+
+
+    @Test
+    public void test_isDirectDescendantOf_same() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertFalse( helper.isDirectDescendantOf( 0L, 0L ) );
+        assertFalse( helper.isDirectDescendantOf( 1L, 1L ) );
+    }
+
+
+    @Test
+    public void test_isDirectDescendantOf_noDescendants() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertFalse( helper.isDirectDescendantOf( 3L, 4L ) );
+        assertFalse( helper.isDirectDescendantOf( 10L, 11L ) );
+    }
+
+
+    @Test(expected = IllegalArgumentException.class)
+    public void test_isDirectDescendantOf_nonExistingIds() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertFalse( helper.isDirectDescendantOf( -99L, -999L ) );
+    }
+
+
+    @Test
+    public void test_isDescendantOf_directDescendants() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertTrue( helper.isDescendantOf( 0L, 1L ) );
+        assertTrue( helper.isDescendantOf( 1L, 3L ) );
+        assertTrue( helper.isDescendantOf( 3L, 7L ) );
+        assertTrue( helper.isDescendantOf( 7L, 9L ) );
+    }
+
+
+    @Test
+    public void test_isDescendantOf_indirectDescendants() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertTrue( helper.isDescendantOf( 0L, 3L ) );
+        assertTrue( helper.isDescendantOf( 0L, 7L ) );
+        assertTrue( helper.isDescendantOf( 0L, 9L ) );
+        assertTrue( helper.isDescendantOf( 1L, 7L ) );
+        assertTrue( helper.isDescendantOf( 1L, 9L ) );
+        assertTrue( helper.isDescendantOf( 3L, 9L ) );
+    }
+
+
+    @Test
+    public void test_isDescendantOf_same() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertFalse( helper.isDescendantOf( 0L, 0L ) );
+        assertFalse( helper.isDescendantOf( 1L, 1L ) );
+    }
+
+
+    @Test
+    public void test_isDescendantOf_noDescendants() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertFalse( helper.isDescendantOf( 3L, 4L ) );
+        assertFalse( helper.isDescendantOf( 10L, 11L ) );
+    }
+
+
+    @Test(expected = IllegalArgumentException.class)
+    public void test_isDescendantOf_nonExistingIds() throws Exception
+    {
+        RdnIndexHelper<Entry, Long> helper = new RdnIndexHelper<Entry, Long>( store.getRdnIndex(), store.getRootId() );
+
+        assertFalse( helper.isDescendantOf( -99L, -999L ) );
+    }
+
+}
\ No newline at end of file
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/RdnIndexTreeCursorTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/RdnIndexTreeCursorTest.java
new file mode 100644
index 0000000..bb0a87f
--- /dev/null
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/RdnIndexTreeCursorTest.java
@@ -0,0 +1,289 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.xdbm.search.impl;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.apache.directory.server.xdbm.IndexCursor;
+import org.apache.directory.server.xdbm.IndexEntry;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.junit.Test;
+
+
+/**
+ * Tests {@link RdnIndexTreeCursor}.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class RdnIndexTreeCursorTest extends TestBase
+{
+
+    // This is how the test data looks like
+    //   ForwardIndexEntry[ ParentIdAndRdn<0, 'o=Good Times Co.'>, 1 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<1, 'ou=Board of Directors'>, 3 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<1, 'ou=Engineering'>, 4 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<1, 'ou=Sales'>, 2 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<2, 'cn=JIM BEAN'>, 6 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<2, 'cn=JOhnny WAlkeR'>, 5 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<3, 'ou=Apache'>, 7 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<3, 'commonName=Jim Bean'>, 10 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<4, 'cn=Jack Daniels'>, 8 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<4, '2.5.4.3=Johnny Walker'>, 11 ]
+    //   ForwardIndexEntry[ ParentIdAndRdn<7, 'commonName=Jim Bean'>, 9 ]
+
+    @Test
+    public void testOneLevelFromContextEntry() throws Exception
+    {
+        IndexCursor<Long, Entry, Long> cursor = store.getRdnIndexHelper().getOneLevelScopeCursor( 1L );
+
+        // --------- Test beforeFirst() ---------
+
+        cursor.beforeFirst();
+        assertFalse( cursor.available() );
+
+        assertHasNext( cursor, 1L, 3L );
+
+        assertHasNext( cursor, 1L, 4L );
+
+        assertHasNext( cursor, 1L, 2L );
+
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        // --------- Test first() ---------
+
+        assertHasFirst( cursor, 1L, 3L );
+
+        assertHasNext( cursor, 1L, 4L );
+
+        assertHasNext( cursor, 1L, 2L );
+
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        // --------- Test afterLast() ---------
+
+        cursor.afterLast();
+        assertFalse( cursor.available() );
+
+        assertHasPrevious( cursor, 1L, 2L );
+
+        assertHasPrevious( cursor, 1L, 4L );
+
+        assertHasPrevious( cursor, 1L, 3L );
+
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // --------- Test last() ---------
+
+        assertHasLast( cursor, 1L, 2L );
+
+        assertHasPrevious( cursor, 1L, 4L );
+
+        assertHasPrevious( cursor, 1L, 3L );
+
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+    }
+
+
+    @Test
+    public void testOneLevelFromApache() throws Exception
+    {
+        IndexCursor<Long, Entry, Long> cursor = store.getRdnIndexHelper().getOneLevelScopeCursor( 7L );
+
+        // --------- Test beforeFirst() ---------
+
+        cursor.beforeFirst();
+        assertFalse( cursor.available() );
+
+        assertHasNext( cursor, 7L, 9L );
+
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        // --------- Test first() ---------
+
+        assertHasFirst( cursor, 7L, 9L );
+
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        // --------- Test afterLast() ---------
+
+        cursor.afterLast();
+        assertFalse( cursor.available() );
+
+        assertHasPrevious( cursor, 7L, 9L );
+
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // --------- Test last() ---------
+
+        assertHasLast( cursor, 7L, 9L );
+
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+    }
+
+
+    @Test
+    public void testSubLevelFromContextEntry() throws Exception
+    {
+        IndexCursor<Long, Entry, Long> cursor = store.getRdnIndexHelper().getSubLevelScopeCursor( 1L );
+
+        // --------- Test beforeFirst() ---------
+
+        cursor.beforeFirst();
+        assertFalse( cursor.available() );
+
+        assertHasNext( cursor, 1L, 1L );
+        assertHasNext( cursor, 1L, 3L );
+        assertHasNext( cursor, 1L, 7L );
+        assertHasNext( cursor, 1L, 9L );
+        assertHasNext( cursor, 1L, 10L );
+        assertHasNext( cursor, 1L, 4L );
+        assertHasNext( cursor, 1L, 8L );
+        assertHasNext( cursor, 1L, 11L );
+        assertHasNext( cursor, 1L, 2L );
+        assertHasNext( cursor, 1L, 6L );
+        assertHasNext( cursor, 1L, 5L );
+
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        // --------- Test first() ---------
+
+        assertHasFirst( cursor, 1L, 1L );
+
+        // --------- Test afterLast() ---------
+
+        cursor.afterLast();
+        assertFalse( cursor.available() );
+
+        assertHasPrevious( cursor, 1L, 5L );
+        assertHasPrevious( cursor, 1L, 6L );
+        assertHasPrevious( cursor, 1L, 2L );
+        assertHasPrevious( cursor, 1L, 11L );
+        assertHasPrevious( cursor, 1L, 8L );
+        assertHasPrevious( cursor, 1L, 4L );
+        assertHasPrevious( cursor, 1L, 10L );
+        assertHasPrevious( cursor, 1L, 9L );
+        assertHasPrevious( cursor, 1L, 7L );
+        assertHasPrevious( cursor, 1L, 3L );
+        assertHasPrevious( cursor, 1L, 1L );
+
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // --------- Test last() ---------
+
+        assertHasLast( cursor, 1L, 5L );
+    }
+
+
+    @Test
+    public void testSubLevelFromApache() throws Exception
+    {
+        IndexCursor<Long, Entry, Long> cursor = store.getRdnIndexHelper().getSubLevelScopeCursor( 7L );
+
+        // --------- Test beforeFirst() ---------
+
+        cursor.beforeFirst();
+        assertFalse( cursor.available() );
+
+        assertHasNext( cursor, 7L, 7L );
+        assertHasNext( cursor, 7L, 9L );
+
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        // --------- Test first() ---------
+
+        assertHasFirst( cursor, 7L, 7L );
+
+        // --------- Test afterLast() ---------
+
+        cursor.afterLast();
+        assertFalse( cursor.available() );
+
+        assertHasPrevious( cursor, 7L, 9L );
+        assertHasPrevious( cursor, 7L, 7L );
+
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // --------- Test last() ---------
+
+        assertHasLast( cursor, 7L, 9L );
+
+    }
+
+
+    private void assertHasNext( IndexCursor<Long, Entry, Long> cursor, Long value, Long id ) throws Exception
+    {
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        IndexEntry<Long, Long> indexEntry = cursor.get();
+        assertNotNull( indexEntry );
+        assertEquals( value, indexEntry.getValue() );
+        assertEquals( id, indexEntry.getId() );
+    }
+
+
+    private void assertHasPrevious( IndexCursor<Long, Entry, Long> cursor, Long value, Long id ) throws Exception
+    {
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        IndexEntry<Long, Long> indexEntry = cursor.get();
+        assertNotNull( indexEntry );
+        assertEquals( value, indexEntry.getValue() );
+        assertEquals( id, indexEntry.getId() );
+    }
+
+
+    private void assertHasFirst( IndexCursor<Long, Entry, Long> cursor, Long value, Long id ) throws Exception
+    {
+        assertTrue( cursor.first() );
+        assertTrue( cursor.available() );
+        IndexEntry<Long, Long> indexEntry = cursor.get();
+        assertNotNull( indexEntry );
+        assertEquals( value, indexEntry.getValue() );
+        assertEquals( id, indexEntry.getId() );
+    }
+
+
+    private void assertHasLast( IndexCursor<Long, Entry, Long> cursor, Long value, Long id ) throws Exception
+    {
+        assertTrue( cursor.last() );
+        assertTrue( cursor.available() );
+        IndexEntry<Long, Long> indexEntry = cursor.get();
+        assertNotNull( indexEntry );
+        assertEquals( value, indexEntry.getValue() );
+        assertEquals( id, indexEntry.getId() );
+    }
+
+}
\ No newline at end of file
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubstringTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubstringTest.java
index 91d3a12..bbd1c2b 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubstringTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubstringTest.java
@@ -23,34 +23,13 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
-import java.io.File;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
 import org.apache.directory.shared.ldap.model.entry.Entry;
 import org.apache.directory.shared.ldap.model.filter.SubstringNode;
-import org.apache.directory.shared.ldap.model.name.Dn;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -58,96 +37,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class SubstringTest
+public class SubstringTest extends TestBase
 {
-    private static final Logger LOG = LoggerFactory.getLogger( SubstringTest.class.getSimpleName() );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = SubstringTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
-
-
-    @Before
-    public void createStore() throws Exception
-    {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( false );
-
-        store.addIndex( new AvlIndex( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex( SchemaConstants.CN_AT_OID ) );
-        
-        Dn suffixDn = new Dn( schemaManager, "o=Good Times Co." );
-        ((Partition)store).setSuffixDn( suffixDn );
-
-        ((Partition)store).initialize();
-
-        StoreUtils.loadExampleData( store, schemaManager );
-        
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destroyStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
-    }
-
 
     @Test
     public void testIndexedCnStartsWithJ() throws Exception
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeTest.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeTest.java
index a3707df..2371a4e 100644
--- a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeTest.java
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeTest.java
@@ -25,20 +25,13 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
 
-import java.io.File;
 import java.util.UUID;
 
-import org.apache.commons.io.FileUtils;
 import org.apache.directory.server.core.interceptor.context.AddOperationContext;
 import org.apache.directory.server.core.partition.Partition;
-import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
 import org.apache.directory.server.xdbm.ForwardIndexEntry;
 import org.apache.directory.server.xdbm.IndexEntry;
-import org.apache.directory.server.xdbm.Store;
-import org.apache.directory.server.xdbm.StoreUtils;
-import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
 import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.model.csn.CsnFactory;
 import org.apache.directory.shared.ldap.model.cursor.InvalidCursorPositionException;
@@ -48,18 +41,7 @@
 import org.apache.directory.shared.ldap.model.message.AliasDerefMode;
 import org.apache.directory.shared.ldap.model.message.SearchScope;
 import org.apache.directory.shared.ldap.model.name.Dn;
-import org.apache.directory.shared.ldap.model.schema.SchemaManager;
-import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
-import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
-import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
-import org.apache.directory.shared.util.exception.Exceptions;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.BeforeClass;
 import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 
 /**
@@ -67,95 +49,8 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class SubtreeScopeTest
+public class SubtreeScopeTest extends TestBase
 {
-    public static final Logger LOG = LoggerFactory.getLogger( SubtreeScopeTest.class );
-
-    File wkdir;
-    Store<Entry, Long> store;
-    static SchemaManager schemaManager = null;
-
-
-    @BeforeClass
-    public static void setup() throws Exception
-    {
-        String workingDirectory = System.getProperty( "workingDirectory" );
-
-        if ( workingDirectory == null )
-        {
-            String path = SubtreeScopeTest.class.getResource( "" ).getPath();
-            int targetPos = path.indexOf( "target" );
-            workingDirectory = path.substring( 0, targetPos + 6 );
-        }
-
-        File schemaRepository = new File( workingDirectory, "schema" );
-        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
-        extractor.extractOrCopy( true );
-        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
-        schemaManager = new DefaultSchemaManager( loader );
-
-        boolean loaded = schemaManager.loadAllEnabled();
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-
-        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
-
-        if ( !loaded )
-        {
-            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
-        }
-    }
-
-
-    @Before
-    public void createStore() throws Exception
-    {
-        // setup the working directory for the store
-        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
-        wkdir.delete();
-        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
-        wkdir.mkdirs();
-
-        // initialize the store
-        store = new AvlPartition( schemaManager );
-        ((Partition)store).setId( "example" );
-        store.setCacheSize( 10 );
-        store.setPartitionPath( wkdir.toURI() );
-        store.setSyncOnWrite( true );
-
-        store.addIndex( new AvlIndex<String, Entry>( SchemaConstants.OU_AT_OID ) );
-        store.addIndex( new AvlIndex<String, Entry>( SchemaConstants.CN_AT_OID ) );
-        ((Partition)store).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
-        ((Partition)store).initialize();
-
-        ((Partition)store).initialize();
-
-        StoreUtils.loadExampleData( store, schemaManager );
-        
-        LOG.debug( "Created new store" );
-    }
-
-
-    @After
-    public void destryStore() throws Exception
-    {
-        if ( store != null )
-        {
-            ((Partition)store).destroy();
-        }
-
-        store = null;
-        if ( wkdir != null )
-        {
-            FileUtils.deleteDirectory( wkdir );
-        }
-
-        wkdir = null;
-    }
-
 
     @Test
     public void testCursorNoDeref() throws Exception
@@ -181,14 +76,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.next() );
@@ -210,14 +105,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertFalse( cursor.next() );
@@ -233,14 +128,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
@@ -262,14 +157,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
@@ -291,14 +186,14 @@
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 6L, ( long ) indexEntry.getId() );
+        assertEquals( 5L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
         indexEntry = cursor.get();
         assertNotNull( indexEntry );
-        assertEquals( 5L, ( long ) indexEntry.getId() );
+        assertEquals( 6L, ( long ) indexEntry.getId() );
         assertEquals( 2L, ( long ) indexEntry.getValue() );
 
         assertTrue( cursor.previous() );
diff --git a/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/TestBase.java b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/TestBase.java
new file mode 100644
index 0000000..f850aff
--- /dev/null
+++ b/xdbm-partition/src/test/java/org/apache/directory/server/xdbm/search/impl/TestBase.java
@@ -0,0 +1,139 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *  
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *  
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License. 
+ *  
+ */
+package org.apache.directory.server.xdbm.search.impl;
+
+
+import static org.junit.Assert.fail;
+
+import java.io.File;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.directory.server.core.partition.Partition;
+import org.apache.directory.server.core.partition.impl.avl.AvlPartition;
+import org.apache.directory.server.xdbm.Store;
+import org.apache.directory.server.xdbm.StoreUtils;
+import org.apache.directory.server.xdbm.impl.avl.AvlIndex;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
+import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
+import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.shared.util.exception.Exceptions;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+
+/**
+ * Base test class to setup and teardown the store.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public abstract class TestBase
+{
+    protected File wkdir;
+    protected Store<Entry, Long> store;
+    protected static SchemaManager schemaManager = null;
+
+
+    @BeforeClass
+    public static void setup() throws Exception
+    {
+        // setup the standard registries
+        String workingDirectory = System.getProperty( "workingDirectory" );
+
+        if ( workingDirectory == null )
+        {
+            String path = TestBase.class.getResource( "" ).getPath();
+            int targetPos = path.indexOf( "target" );
+            workingDirectory = path.substring( 0, targetPos + 6 );
+        }
+
+        File schemaRepository = new File( workingDirectory, "schema" );
+        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
+        extractor.extractOrCopy( true );
+        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
+        schemaManager = new DefaultSchemaManager( loader );
+
+        boolean loaded = schemaManager.loadAllEnabled();
+
+        if ( !loaded )
+        {
+            fail( "Schema load failed : " + Exceptions.printErrors( schemaManager.getErrors() ) );
+        }
+
+        loaded = schemaManager.loadWithDeps( loader.getSchema( "collective" ) );
+
+        if ( !loaded )
+        {
+            fail( "Schema load failed : " + Exceptions.printErrors( schemaManager.getErrors() ) );
+        }
+    }
+
+
+    @Before
+    public void createStore() throws Exception
+    {
+        // setup the working directory for the store
+        wkdir = File.createTempFile( getClass().getSimpleName(), "db" );
+        wkdir.delete();
+        wkdir = new File( wkdir.getParentFile(), getClass().getSimpleName() );
+        wkdir.mkdirs();
+
+        // initialize the store
+        store = new AvlPartition( schemaManager );
+        ( ( Partition ) store ).setId( "example" );
+        store.setCacheSize( 10 );
+        store.setPartitionPath( wkdir.toURI() );
+        store.setSyncOnWrite( true );
+
+        store.addIndex( new AvlIndex<String, Entry>( SchemaConstants.OU_AT_OID ) );
+        store.addIndex( new AvlIndex<String, Entry>( SchemaConstants.CN_AT_OID ) );
+        store.addIndex( new AvlIndex<String, Entry>( SchemaConstants.POSTALCODE_AT_OID ) );
+        ( ( Partition ) store ).setSuffixDn( new Dn( schemaManager, "o=Good Times Co." ) );
+        ( ( Partition ) store ).initialize();
+
+        ( ( Partition ) store ).initialize();
+
+        StoreUtils.loadExampleData( store, schemaManager );
+    }
+
+
+    @After
+    public void destroyStore() throws Exception
+    {
+        if ( store != null )
+        {
+            ( ( Partition ) store ).destroy();
+        }
+
+        store = null;
+        if ( wkdir != null )
+        {
+            FileUtils.deleteDirectory( wkdir );
+        }
+
+        wkdir = null;
+    }
+
+}
\ No newline at end of file