You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2017/10/09 20:33:00 UTC

svn commit: r1811602 [6/6] - in /directory/mavibot/branches/single-value/mavibot: ./ src/main/java/org/apache/directory/mavibot/btree/ src/main/java/org/apache/directory/mavibot/btree/exception/ src/test/java/org/apache/directory/mavibot/btree/

Modified: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java Mon Oct  9 20:32:59 2017
@@ -21,6 +21,7 @@ package org.apache.directory.mavibot.btr
 
 
 import java.io.Closeable;
+import java.io.IOException;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
@@ -86,7 +87,7 @@ public class TupleCursor<K, V> implement
      * rightmost page for each level, and the position to the rightmost element
      * of each page.
      */
-    public void afterLast()
+    public void afterLast() throws IOException
     {
         // First check that we have elements in the B-tree
         if ( ( stack == null ) || ( stack.length == 0 ) )
@@ -99,8 +100,8 @@ public class TupleCursor<K, V> implement
         // to BEFORE_FIRST
         for ( int i = 0; i < depth; i++ )
         {
-            stack[i].pos = stack[i].page.getNbPageElems();
-            stack[i+1].page = ( ( Node<K, V> ) stack[i].page ).getPage( stack[i].pos );
+            stack[i].pos = stack[i].page.getPageNbElems();
+            stack[i+1].page = ( ( Node<K, V> ) stack[i].page ).getPage( transaction, stack[i].pos );
         }
 
         stack[depth].pos = AFTER_LAST;
@@ -128,7 +129,7 @@ public class TupleCursor<K, V> implement
     /**
      * Positions this cursor before the first element.
      */
-    public void beforeFirst()
+    public void beforeFirst() throws IOException
     {
         // First check that we have elements in the B-tree
         if ( ( stack == null ) || ( stack.length == 0 ) )
@@ -142,7 +143,7 @@ public class TupleCursor<K, V> implement
         for ( int i = 0; i < depth; i++ )
         {
             stack[i].pos = 0;
-            stack[i+1].page = ( ( Node<K, V> ) stack[i].page ).getPage( 0 );
+            stack[i+1].page = ( ( Node<K, V> ) stack[i].page ).getPage( transaction, 0 );
         }
 
         stack[depth].pos = BEFORE_FIRST;
@@ -165,7 +166,7 @@ public class TupleCursor<K, V> implement
         }
 
         // Take the leaf and check if we have no mare values
-        if ( ( stack[depth].pos + 1 < stack[depth].page.getNbPageElems() ) || ( stack[depth].pos == BEFORE_FIRST ) )
+        if ( ( stack[depth].pos + 1 < stack[depth].page.getPageNbElems() ) || ( stack[depth].pos == BEFORE_FIRST ) )
         {
             // get out, we have values on the right
             return true;
@@ -174,7 +175,7 @@ public class TupleCursor<K, V> implement
         // Check that we are not at position 0 for all the pages in the stack 
         for ( int i = depth - 1; i >= 0; i-- )
         {
-            if ( stack[i].pos < stack[i].page.getNbPageElems() )
+            if ( stack[i].pos < stack[i].page.getPageNbElems() )
             {
                 return true;
             }
@@ -226,14 +227,14 @@ public class TupleCursor<K, V> implement
                 stack[depth].pos++;
                 parentPos = stack[depth];
 
-                if ( stack[depth].pos == stack[depth].page.getNbPageElems() )
+                if ( stack[depth].pos == stack[depth].page.getPageNbElems() )
                 {
                     boolean hasNext = false;
 
                     // Move up to find the next leaf
                     for ( int i = depth; i >= 0; i-- )
                     {
-                        if ( stack[i].pos != stack[i].page.getNbPageElems() )
+                        if ( stack[i].pos != stack[i].page.getPageNbElems() )
                         {
                             // We have some more children on the right, move forward
                             stack[i].pos++;
@@ -241,12 +242,28 @@ public class TupleCursor<K, V> implement
                             // and go down the stack if we weren't already at the bottom, setting the pos to 0
                             for ( int j = i + 1; j < depth; j++ )
                             {
-                                stack[j].page = ((Node<K, V>)stack[j - 1].page).getPage( stack[j - 1].pos );
+                                try
+                                {
+                                    stack[j].page = ((Node<K, V>)stack[j - 1].page).getPage( transaction, stack[j - 1].pos );
+                                }
+                                catch ( IOException ioe )
+                                {
+                                    throw new RuntimeException( ioe );
+                                }
+                                
                                 stack[j].pos = 0;
                             }
                             
                             // The last page is a leaf
-                            stack[depth].page = ((Node<K, V>)stack[depth - 1].page).getPage( stack[depth - 1].pos );
+                            try
+                            {
+                                stack[depth].page = ((Node<K, V>)stack[depth - 1].page).getPage( transaction, stack[depth - 1].pos );
+                            }
+                            catch ( IOException ioe )
+                            {
+                                throw new RuntimeException( ioe );
+                            }
+                        
                             stack[depth].pos = 0;
                             
                             parentPos = stack[depth];
@@ -319,7 +336,7 @@ public class TupleCursor<K, V> implement
      * @throws NoSuchElementException When we have reached the beginning of the B-tree, or if 
      * the B-tree is empty
      */
-    public Tuple<K, V> prev()
+    public Tuple<K, V> prev() throws IOException
     {
         // First check that we have elements in the B-tree
         if ( ( stack == null ) || ( stack.length == 0 ) )
@@ -342,7 +359,7 @@ public class TupleCursor<K, V> implement
 
             case AFTER_LAST :
                 // Move to the last element
-                parentPos.pos = parentPos.page.getNbPageElems() - 1;
+                parentPos.pos = parentPos.page.getPageNbElems() - 1;
                 break;
             
             case 0 :
@@ -360,13 +377,13 @@ public class TupleCursor<K, V> implement
                         // and go down the stack if we weren't already at the bottom, setting the pos to nbElems
                         for ( int j = i + 1; j < depth; j++ )
                         {
-                            stack[j].page = ((Node<K, V>)stack[j - 1].page).getPage( stack[j - 1].pos );
-                            stack[j].pos = stack[j].page.getNbPageElems();
+                            stack[j].page = ((Node<K, V>)stack[j - 1].page).getPage( transaction, stack[j - 1].pos );
+                            stack[j].pos = stack[j].page.getPageNbElems();
                         }
 
                         // The last page is a leaf
-                        stack[depth].page = ((Node<K, V>)stack[depth - 1].page).getPage( stack[depth - 1].pos );
-                        stack[depth].pos = stack[depth].page.getNbPageElems() - 1;
+                        stack[depth].page = ((Node<K, V>)stack[depth - 1].page).getPage( transaction, stack[depth - 1].pos );
+                        stack[depth].pos = stack[depth].page.getPageNbElems() - 1;
                         
                         hasPrev = true;
                         break;

Modified: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java Mon Oct  9 20:32:59 2017
@@ -29,7 +29,7 @@ import org.slf4j.LoggerFactory;
 
 
 /**
- * A holder to store the Value
+ * A holder to store the Value.
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @param <V> The value type
@@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory;
     protected static final Logger LOG = LoggerFactory.getLogger( ValueHolder.class );
 
     /** The parent BTree */
-    protected BTreeImpl parentBtree;
+    protected BTreeInfo<V, V> btreeInfo;
 
     /** The serialized value */
     private byte[] raw;
@@ -65,10 +65,10 @@ import org.slf4j.LoggerFactory;
      * @param nbValues the number of stored values
      * @param raw the byte[] containing either the serialized array of values or the sub-btree offset
      */
-    ValueHolder( BTree<?, V> parentBtree, byte[] raw )
+    ValueHolder( BTreeInfo<?, V> btreeInfo, byte[] raw )
     {
-        this.parentBtree = ( BTreeImpl<V, V> ) parentBtree;
-        this.valueSerializer = parentBtree.getValueSerializer();
+        this.btreeInfo = ( BTreeInfo<V, V> ) btreeInfo;
+        this.valueSerializer = btreeInfo.getValueSerializer();
         this.raw = raw;
         isRawUpToDate = true;
     }
@@ -81,10 +81,10 @@ import org.slf4j.LoggerFactory;
      * @param parentBtree The parent BTree
      * @param values The Value stored in the ValueHolder
      */
-    public ValueHolder( BTree parentBtree, V value )
+    public ValueHolder( BTreeInfo<?, V> btreeInfo, V value )
     {
-        this.parentBtree = ( BTreeImpl ) parentBtree;
-        this.valueSerializer = parentBtree.getValueSerializer();
+        this.btreeInfo = ( BTreeInfo<V, V> ) btreeInfo;
+        this.valueSerializer = btreeInfo.getValueSerializer();
         set( value );
 
         isDeserialized = true;

Modified: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java Mon Oct  9 20:32:59 2017
@@ -20,19 +20,33 @@
 package org.apache.directory.mavibot.btree;
 
 import java.io.IOException;
-import java.nio.ByteBuffer;
 
 /**
- * A WALObject is an object stored in the TransactionContext before weing written on disk.
+ * A WALObject is an object stored in a {@link Transaction} before being written on disk. 
+ * <p>
+ * The <strong>WAL</strong> (aka Write Ahead Log) is a temporary storage where updates are
+ * kept until the transaction is committed on disk, or rolled back.
+ * <p> 
+ * The following elements are WalObjects :
+ * <ul>
+ *   <li>Leaf</li>
+ *   <li>Node</li>
+ *   <li>BtreeHeader</li>
+ *   <li>BtreeInfo</li>
+ * </ul>
+ * <p>
+ * In order to save useless writes, when a WALObject is already present in the WAL, it's replaced by the new version. That
+ * means the element will not be written twice on disk.
+ * @see <a href="https://en.wikipedia.org/wiki/Write-ahead_logging">https://en.wikipedia.org/wiki/Write-ahead_logging</a>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public interface WALObject<K, V>
 {
     /**
-     * @return the B-tree
+     * @return the B-tree information
      */
-    public BTree<K, V> getBtree();
+    public BTreeInfo<K, V> getBtreeInfo();
 
     
     /**
@@ -53,7 +67,7 @@ public interface WALObject<K, V>
     
     
     /**
-     * @param pageIOs Store teh PageIOs for this object
+     * @param pageIOs Set the PageIOs for this object
      */
     void setPageIOs( PageIO[] pageIOs );
     
@@ -67,18 +81,6 @@ public interface WALObject<K, V>
      * @throws IOException If we got an error while serializing
      */
     PageIO[] serialize( WriteTransaction transaction ) throws IOException;
-    
-    
-    /**
-     * Deserialize a WALObject from a PageIO[]
-     * 
-     * @param transaction The Read Transaction in use
-     * @param byteBuffer The byteBuffer containing the page data
-     * @return The read page
-     * 
-     * @throws IOException If we got an error while serializing
-     */
-    WALObject<K, V> deserialize( Transaction transaction, ByteBuffer byteBuffer ) throws IOException;
 
     
     /**
@@ -98,4 +100,13 @@ public interface WALObject<K, V>
      * @return The pretty print for this instance
      */
     String prettyPrint();
+
+    
+    /**
+     * Tells if the B-tree is a user B-tree or not
+     * 
+     * @return <code>false</code> if the B-tree is a <em>BtreeOfBtrees</em> or a <em>CopiedPagesBTree</em>, 
+     * <code>true</code> otherwise
+     */
+    boolean isBTreeUser();
 }

Modified: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java Mon Oct  9 20:32:59 2017
@@ -20,10 +20,9 @@
 package org.apache.directory.mavibot.btree;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.List;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -41,12 +40,8 @@ import java.util.Set;
 public class WriteTransaction extends AbstractTransaction
 {
     /** The List containing all the user modified pages, in the order they have been created */
-    //private List<WALObject<?, ?>> newUserPages = new ArrayList<WALObject<?, ?>>();
-    private List<WALObject<?, ?>> newPages = new ArrayList<WALObject<?, ?>>();
+    private Map<Long, WALObject<?, ?>> newPages = new LinkedHashMap<>();
     
-    /** The List containing all the BOB/CPB modified pages, in the order they have been created */
-    //private List<WALObject<?, ?>> newAdminPages = new ArrayList<WALObject<?, ?>>();
-
     /** The map containing all the copied pages, using their offset as a key */
     private Map<Long, WALObject<?, ?>> copiedPageMap = new HashMap<>();
     
@@ -59,6 +54,10 @@ public class WriteTransaction extends Ab
     {
         super( recordManager );
         
+        
+        // Get a copy of the RMH
+        recordManagerHeader = recordManager.getRecordManagerHeaderCopy();
+        
         //System.out.println( "---> Write transaction started, " + this );
         
         // We have to increment the revision
@@ -79,13 +78,25 @@ public class WriteTransaction extends Ab
         }
         else
         {
-            //newUserPages.clear();
-            //newAdminPages.clear();
             newPages.clear();
             copiedPageMap.clear();
             super.close();
         }
     }
+    
+    
+    private <K, V> void updateRefs( Node<K, V> node )
+    {
+        for ( int i = 0; i < node.pageNbElems + 1; i++ )
+        {
+            if ( node.children[i] < 0L )
+            {
+                // This is a Page ID, replace it with the page offset
+                WALObject child = newPages.get( -node.children[i] );
+                node.children[i] = child.getOffset();
+            }
+        }
+    }
 
 
     /**
@@ -97,56 +108,55 @@ public class WriteTransaction extends Ab
         if ( !isClosed() )
         {
             // First, find the modified users B-trees, and flush the user's pages 
-            Set<BTree<?, ?>> btrees = new HashSet<>();
+            Set<BTreeInfo<?, ?>> btreeInfos = new HashSet<>();
             
-            //for ( WALObject<?, ?> walObject : newUserPages )
-            for ( WALObject<?, ?> walObject : newPages )
+            //System.out.println( "-----User BTree----" );
+            for ( WALObject<?, ?> walObject : newPages.values() )
             {
-                BTree<?, ?> btree = walObject.getBtree();
+                //System.out.println( "WALObject" + walObject );
+                BTreeInfo<?, ?> btreeInfo = walObject.getBtreeInfo();
                 
                 // Flush the page
+                if ( walObject instanceof Node )
+                {
+                    updateRefs( ( Node ) walObject );
+                }
+                
                 walObject.serialize( this );
                 recordManager.flushPages( recordManagerHeader, walObject.getPageIOs() );
                 
                 // and update the B-tree list if needed
-                btrees.add( btree );
+                if ( walObject.isBTreeUser() )
+                {
+                    btreeInfos.add( btreeInfo );
+                }
             }
             
             // We can clean the user's list
-            //newUserPages.clear();
             newPages.clear();
 
             // Update the BOB, if we aren't already processing the BOB
-            for ( BTree<?, ?> btree : btrees )
+            for ( BTreeInfo<?, ?> btreeInfo : btreeInfos )
             {
-                recordManager.insertInBtreeOfBtrees( this, btree );
+                recordManager.insertInBtreeOfBtrees( this, recordManagerHeader.btreeMap.get( btreeInfo.getName() ) );
             }
             
-            //for ( WALObject<?, ?> walObject : newAdminPages )
-            for ( WALObject<?, ?> walObject : newPages )
-            {
-                // Flush the page
-                walObject.serialize( this );
-                recordManager.flushPages( recordManagerHeader, walObject.getPageIOs() );
-            }
+            // Flush the newly updated pages 
+            //System.out.println( "-----BOB----" );
+            flushNewPages();
 
             // BOB done, clear the list
-            //newAdminPages.clear();
             newPages.clear();
             
             // Add the copied pages in the CPB
             recordManager.insertInCopiedPagesBtree( this );
             
             // Last not least, Flush the CPB pages
-            //for ( WALObject<?, ?> walObject : newAdminPages )
-            for ( WALObject<?, ?> walObject : newPages )
-            {
-                walObject.serialize( this );
-                recordManager.flushPages( recordManagerHeader, walObject.getPageIOs() );
-            }
+            //System.out.println( "-----CPB BTree----" );
+            flushNewPages();
             
-            long newBtreeOfBtreesOffet = ((BTreeImpl<NameRevision, Long>)recordManagerHeader.btreeOfBtrees).getBtreeHeader().offset;
-            long newCopiedPagesBtreeOffset = ((BTreeImpl<RevisionName, long[]>)recordManagerHeader.copiedPagesBtree).getBtreeHeader().offset;
+            long newBtreeOfBtreesOffet = ((BTree<NameRevision, Long>)recordManagerHeader.btreeOfBtrees).getBtreeHeader().offset;
+            long newCopiedPagesBtreeOffset = ((BTree<RevisionName, long[]>)recordManagerHeader.copiedPagesBtree).getBtreeHeader().offset;
 
             // And update the RecordManagerHeader
             recordManager.updateRecordManagerHeader( recordManagerHeader, newBtreeOfBtreesOffet, newCopiedPagesBtreeOffset );
@@ -159,6 +169,22 @@ public class WriteTransaction extends Ab
             super.close();
         }
     }
+    
+    
+    private void flushNewPages() throws IOException
+    {
+        for ( WALObject<?, ?> walObject : newPages.values() )
+        {
+            //System.out.println( "WALObject" + walObject );
+            if ( walObject instanceof Node )
+            {
+                updateRefs( ( Node ) walObject );
+            }
+
+            walObject.serialize( this );
+            recordManager.flushPages( recordManagerHeader, walObject.getPageIOs() );
+        }
+    }
 
 
     /**
@@ -168,8 +194,6 @@ public class WriteTransaction extends Ab
     public void abort() throws IOException
     {
         // We just have to empty the maps
-        //newUserPages.clear();
-        //newAdminPages.clear();
         newPages.clear();
         copiedPageMap.clear();
         super.close();
@@ -224,60 +248,44 @@ public class WriteTransaction extends Ab
      *  
      * @param walObject The {@link WALObject} to store
      */
-    /* No qualifier */void addWALObject( WALObject walObject ) throws IOException
+    /* No qualifier */void addWALObject( WALObject walObject )
     {
+        // Only add the page if it's not already there
         if ( walObject != null )
         {
-            newPages.add( walObject );
-            /*
-            if ( walObject.getBtree().getType() == BTreeTypeEnum.PERSISTED )
-            {
-                newUserPages.add( walObject );
-            }
-            else
-            {
-                newAdminPages.add( walObject );
-            }
-            */
+            WALObject oldPage = newPages.put( walObject.getId(), walObject );
+            recordManager.putPage( walObject );
         }
     }
     
     
     /**
-     * Add a page in the list of modified {@link WALObject}s. If there is an existing 
-     * {@link WALObject}, it will be replaced with the new content. Note that a {@link WALObject} 
-     * is associated to one to many {@link PageIO}s.
-     *  
-     * @param walObject The {@link WALObject} to store
+     * {@inheritDoc}
      */
-    /* No qualifier */WALObject removeWALObject( long id ) throws IOException
+    @Override
+    public <K, V> Page<K, V> getPage( BTreeInfo<K, V> btreeInfo, long offset ) throws IOException
     {
-        for ( int i = 0; i < newPages.size(); i++ )
+        if ( offset >= 0 )
         {
-            if ( newPages.get( i ).getId() == id )
-            {
-                return newPages.remove( i );
-            }
+            return ( Page<K, V> ) recordManager.getPage( btreeInfo, recordManagerHeader.pageSize, offset );
         }
-        /*
-        for ( int i = 0; i < newUserPages.size(); i++ )
+        else
         {
-            if ( newUserPages.get( i ).getId() == id )
-            {
-                return newUserPages.remove( i );
-            }
+            return ( Page<K, V> )newPages.get( -offset );
         }
+    }
 
-        for ( int i = 0; i < newAdminPages.size(); i++ )
-        {
-            if ( newAdminPages.get( i ).getId() == id )
-            {
-                return newAdminPages.remove( i );
-            }
-        }
-        */
-        
-        return null;
+    
+    /**
+     * Add a page in the list of modified {@link WALObject}s. If there is an existing 
+     * {@link WALObject}, it will be replaced with the new content. Note that a {@link WALObject} 
+     * is associated to one to many {@link PageIO}s.
+     *  
+     * @param walObject The {@link WALObject} to store
+     */
+    /* No qualifier */WALObject removeWALObject( long id )
+    {
+        return newPages.remove( id );
     }
     
     
@@ -288,11 +296,11 @@ public class WriteTransaction extends Ab
      *  
      * @param walObject The {@link WALObject} to store
      */
-    /* No qualifier */void addCopiedWALObject( WALObject walObject )
+    /* No qualifier */<K, V> void addCopiedWALObject( WALObject<K, V> walObject )
     {
-        if ( walObject != null )
+        if ( ( walObject != null ) && !copiedPageMap.containsKey( walObject.getId() ) )
         {
-            copiedPageMap.put( Long.valueOf( walObject.getOffset() ), walObject );
+            copiedPageMap.put( walObject.getId(), walObject );
         }
     }
     
@@ -306,42 +314,115 @@ public class WriteTransaction extends Ab
      */
     public WALObject<?, ?> getWALObject( long id )
     {
-        for ( WALObject walObject : newPages )
-        {
-            if ( walObject.getId() == id )
-            {
-                return walObject;
-            }
-        }
-        /*
-        for ( WALObject walObject : newUserPages )
-        {
-            if ( walObject.getId() == id )
-            {
-                return walObject;
-            }
-        }
+        return newPages.get( id );
+    }
+    
+    
+    /* No qualifier */ Map<Long, WALObject<?, ?>> getCopiedPageMap()
+    {
+        return copiedPageMap;
+    }
+    
+    
+    /**
+     * Update the WAL
+     * 
+     * @param revision The previous revision
+     * @param oldPage The previous page
+     * @param newPage The new page
+     * @throws IOException If we had an error storing the 
+     **/
+    /* No qualifier */ <K, V> void updateWAL( long previousRevision, WALObject<K, V> oldPage, WALObject<K, V> newPage )
+    {
+        addWALObject( newPage );
 
-        for ( WALObject walObject : newAdminPages )
+        if ( ( previousRevision != getRevision() ) && newPage.isBTreeUser() )
         {
-            if ( walObject.getId() == id )
-            {
-                return walObject;
-            }
+            // Now, move the new child into the copied pages if needed
+            addCopiedWALObject( oldPage );
         }
-        */
+    }
+    
+    
+    /**
+     * Creates a new {@link Leaf}, with a valid offset.
+     * 
+     * @param btreeInfo The {@link BTreeInfo} reference
+     * @return A new {@link Leaf} instance
+     */
+    /* No qualifier */ <K, V> Leaf<K, V> newLeaf( BTreeInfo<K, V> btreeInfo, int nbElems )
+    {
+        Leaf<K, V> leaf = new Leaf<>( btreeInfo, getRevision(), nbElems );
+        leaf.initId( recordManagerHeader );
         
-        return null;
+        return leaf;
     }
     
     
-    /* No qualifier */ Map<Long, WALObject<?, ?>> getCopiedPageMap()
+    /**
+     * Creates a new {@link Leaf}, with a valid offset.
+     * 
+     * @param btreeInfo The {@link BTreeInfo} reference
+     * @return A new {@link Leaf} instance
+     */
+    /* No qualifier */ <K, V> Leaf<K, V> newLeaf( BTreeInfo<K, V> btreeInfo, long id, int nbElems )
     {
-        return copiedPageMap;
+        Leaf<K, V> leaf = new Leaf<>( btreeInfo, getRevision(), nbElems );
+        leaf.setId( id );
+        
+        return leaf;
     }
     
     
     /**
+     * Creates a new {@link Node}, with a valid offset.
+     * 
+     * @param btreeInfo The {@link BTreeInfo} reference
+     * @return A new {@link Leaf} instance
+     */
+    /* No qualifier */ <K, V> Node<K, V> newNode( BTreeInfo<K, V> btreeInfo, int nbElems )
+    {
+        Node<K, V> node = new Node<>( btreeInfo, getRevision(), nbElems );
+        node.initId( recordManagerHeader );
+
+        return node;
+    }
+    
+    
+    /**
+     * Creates a new {@link Node}, with a valid offset.
+     * 
+     * @param btreeInfo The {@link BTreeInfo} reference
+     * @return A new {@link Leaf} instance
+     */
+    /* No qualifier */ <K, V> Node<K, V> newNode( BTreeInfo<K, V> btreeInfo, long id, int nbElems )
+    {
+        Node<K, V> node = new Node<>( btreeInfo, getRevision(), nbElems );
+        node.setId( id );
+        
+        return node;
+    }
+    
+    
+    /**
+     * Creates a new Node which will contain only one key, with references to
+     * a left and right page. This is a specific constructor used by the btree
+     * when the root was full when we added a new value.
+     *
+     * @param btreeInfo the {@link BTreeInfo} reference
+     * @param key The new key
+     * @param leftPage The left page offset
+     * @param rightPage The right page offset
+     */
+    /* No qualifier */ <K, V> Node<K, V> newNode( BTreeInfo<K, V> btreeInfo, K key, long leftPage, long rightPage )
+    {
+        Node<K, V> node = new Node<>( btreeInfo, getRevision(), key, leftPage, rightPage );
+        node.initId( recordManagerHeader );
+        
+        return node;
+    }
+    
+    /**
      * {@inheritDoc}
      */
     @Override
@@ -359,7 +440,7 @@ public class WriteTransaction extends Ab
             sb.append( "    pageList :[\n        " );
             boolean isFirst = true;
             
-            for ( WALObject walObject : newPages )
+            for ( WALObject walObject : newPages.values() )
             {
                 if ( isFirst )
                 {
@@ -375,72 +456,12 @@ public class WriteTransaction extends Ab
             
             sb.append( '\n' );
             
-            /*
-            for ( Entry<Long, WALObject<?, ?>> entry : pageMap.entrySet() )
-            {
-                if ( isFirst )
-                {
-                    isFirst = false;
-                }
-                else
-                {
-                    sb.append( ", " );
-                }
-                
-                sb.append( String.format( "%x", entry.getKey() ) );
-                sb.append(  ':' );
-                sb.append( '<' );
-                sb.append( entry.getValue().getName() );
-                sb.append( ':' );
-                
-                if ( entry.getValue().getRevision() == RecordManager.NO_PAGE )
-                {
-                    sb.append( "info" );
-                }
-                else
-                {
-                    sb.append( entry.getValue().getRevision() );
-                }
-                sb.append( '>' );
-                sb.append( entry.getValue().getClass().getSimpleName() );
-            }
-            
-            sb.append( "]\n" );
-            */
         }
         else
         {
             sb.append( "    UserPageList empty\n" );
         }
         
-        /*
-        if ( newAdminPages.size() > 0 )
-        {
-            sb.append( "    AdminPageList :[\n        " );
-            boolean isFirst = true;
-            
-            for ( WALObject walObject : newAdminPages )
-            {
-                if ( isFirst )
-                {
-                    isFirst = false;
-                }
-                else
-                {
-                    sb.append( ",\n        " );
-                }
-
-                sb.append( walObject.prettyPrint() );
-            }
-            
-            sb.append( '\n' );
-        }
-        else
-        {
-            sb.append( "    AdminPageList empty\n" );
-        }
-        */
-
         if ( copiedPageMap.size() > 0 )
         {
             sb.append( "    CopiedPagesMap :[\n        " );

Added: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/BTreeNotFoundException.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/BTreeNotFoundException.java?rev=1811602&view=auto
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/BTreeNotFoundException.java (added)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/BTreeNotFoundException.java Mon Oct  9 20:32:59 2017
@@ -0,0 +1,72 @@
+/*
+ *  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.mavibot.btree.exception;
+
+
+/**
+ * An exception thrown when we weren't able to find a B-tree in the transaction
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class BTreeNotFoundException extends RuntimeException
+{
+    /** The serial version UUID */
+    private static final long serialVersionUID = 1L;
+
+
+    /**
+     * Creates a new instance of BTreeNotFoundException.
+     */
+    public BTreeNotFoundException()
+    {
+    }
+
+
+    /**
+     * Creates a new instance of BTreeNotFoundException.
+     *
+     * @param explanation The message associated with the exception
+     */
+    public BTreeNotFoundException( String explanation )
+    {
+        super( explanation );
+    }
+
+
+    /**
+     * Creates a new instance of BTreeNotFoundException.
+     */
+    public BTreeNotFoundException( Throwable cause )
+    {
+        super( cause );
+    }
+
+
+    /**
+     * Creates a new instance of BTreeNotFoundException.
+     *
+     * @param explanation The message associated with the exception
+     * @param cause The root cause for this exception
+     */
+    public BTreeNotFoundException( String explanation, Throwable cause )
+    {
+        super( explanation, cause );
+    }
+}

Modified: directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBrowseTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBrowseTest.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBrowseTest.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBrowseTest.java Mon Oct  9 20:32:59 2017
@@ -32,7 +32,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.NoSuchElementException;
 import java.util.Random;
-import java.util.TreeMap;
 import java.util.UUID;
 
 import org.apache.commons.io.FileUtils;
@@ -73,7 +72,7 @@ public class BTreeBrowseTest
      * Create a BTree for this test
      */
     @Before
-    public void startup() throws IOException
+    public void startup() throws Exception
     {
         dataDir = tempFolder.newFolder( UUID.randomUUID().toString() );
 
@@ -89,6 +88,11 @@ public class BTreeBrowseTest
             transaction.abort();
             throw new RuntimeException( e );
         }
+
+        try ( Transaction transaction = recordManager.beginReadTransaction() )
+        {
+            //MavibotInspector.dumpInfos( recordManager, transaction.getRecordManagerHeader() );
+        }
     }
 
 
@@ -121,12 +125,17 @@ public class BTreeBrowseTest
             // Now, try to reload the file back
             recordManager = new RecordManager( dataDir.getAbsolutePath() );
 
+            try ( Transaction transaction = recordManager.beginReadTransaction() )
+            {
+                //MavibotInspector.dumpInfos( recordManager, transaction.getRecordManagerHeader() );
+            }
+
             // load the last created btree
-            try (Transaction transaction = recordManager.beginReadTransaction() )
+            try ( Transaction transaction = recordManager.beginReadTransaction() )
             {
                 if ( btree != null )
                 {
-                    btree = recordManager.getBtree( transaction, btree.getName() );
+                    btree = transaction.getBTree( btree.getName() );
                 }
             }
             catch ( Exception e )
@@ -220,7 +229,7 @@ public class BTreeBrowseTest
     {
         try ( Transaction transaction  = recordManager.beginReadTransaction() )
         {
-            btree = recordManager.getBtree( transaction, "test" );
+            btree = transaction.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( transaction );
     
             assertFalse( cursor.hasNext() );
@@ -260,22 +269,19 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             btree.insert( writeTxn, 1L, "1" );
             btree.insert( writeTxn, 4L, "4" );
             btree.insert( writeTxn, 2L, "2" );
             btree.insert( writeTxn, 3L, "3" );
             btree.insert( writeTxn, 5L, "5" );
         }
-        
-        try ( Transaction transaction = recordManager.beginReadTransaction() )
-        {
-            MavibotInspector.dumpInfos( recordManager, transaction.getRecordManagerHeader() );
-        }
 
         // Create the cursor
-        try ( Transaction transaction = recordManager.beginReadTransaction() )
+        try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
-            TupleCursor<Long, String> cursor = btree.browse( transaction );
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
+            TupleCursor<Long, String> cursor = btree.browse( readTxn );
     
             // Move forward
             cursor.beforeFirst();
@@ -301,6 +307,7 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             btree.insert( writeTxn, 1L, "1" );
             btree.insert( writeTxn, 4L, "4" );
             btree.insert( writeTxn, 2L, "2" );
@@ -311,6 +318,7 @@ public class BTreeBrowseTest
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
     
             // Move backward
@@ -335,6 +343,7 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             btree.insert( writeTxn, 1L, "1" );
             btree.insert( writeTxn, 4L, "4" );
             btree.insert( writeTxn, 2L, "2" );
@@ -345,6 +354,7 @@ public class BTreeBrowseTest
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
     
             // We should not be able to move backward
@@ -423,6 +433,7 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             btree.insert( writeTxn, 1L, "1" );
             btree.insert( writeTxn, 4L, "4" );
             btree.insert( writeTxn, 2L, "2" );
@@ -433,6 +444,7 @@ public class BTreeBrowseTest
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
     
             // We should not be able to move backward
@@ -472,7 +484,34 @@ public class BTreeBrowseTest
     }
     
     
+    /**
+     * Shuffle a set of longs
+     * @param nbElems
+     * @return
+     */
+    private void shuffle( long[] values )
+    {
+        Random r = new Random( System.nanoTime() );
+        
+        for ( int i = 0; i < values.length; i++ )
+        {
+            values[i] = i;
+        }
+        
+        for ( int i = 0; i < values.length*10; i++ )
+        {
+            int i1 = r.nextInt( values.length ) ;
+            int i2 = r.nextInt( values.length ) ;
+            
+            long tmp = values[i1];
+            values[i1] = values[i2];
+            values[i2] = tmp;
+        }
+    }
+    
+    
     @Test
+    @Ignore
     public void testPerf()
     {
         Random r = new Random( System.nanoTime() );
@@ -530,14 +569,17 @@ public class BTreeBrowseTest
     public void testBrowseBTreeNodesNext() throws Exception
     {
         // Inject some data
-        long increment = 10L;
+        long increment = 100L;
         long nbRound = 100_000L;
         long t0 = System.currentTimeMillis();
+        
         for ( long i = 0; i < nbRound/increment; i++ )
         {
             //System.out.println( "\nInserting " + i + " in the tree ---->" );
             try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
             {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+                
                 for ( long j = 0; j < increment; j++ )
                 {
                     long val = i*increment + j;
@@ -551,12 +593,15 @@ public class BTreeBrowseTest
         
         System.out.println( "Delta add    : " + ( t1 - t0 ) );
         System.out.println( "File name    : " + dataDir );
+        System.out.println( "Nb cache hits : " + recordManager.nbCacheHits.get() );
+        System.out.println( "Nb cache misses : " + recordManager.nbCacheMisses.get() );
         
         //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
 
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
 
             // Move forward
@@ -597,6 +642,687 @@ public class BTreeBrowseTest
             t1 = System.currentTimeMillis();
             
             System.out.println( "Delta browse : " + ( t1 - t0 ) );
+            System.out.println( "Nb cache hits : " + recordManager.nbCacheHits.get() );
+            System.out.println( "Nb cache misses : " + recordManager.nbCacheMisses.get() );
+        }
+    }
+    
+    
+    @Test
+    public void testAddRandom() throws Exception
+    {
+        // Inject some data
+        long increment = 20L;
+        long nbRound = 100_000L;
+        long t0 = System.currentTimeMillis();
+
+        long[] values = new long[(int)nbRound];
+        
+        for ( long i = 0; i < nbRound; i++ )
+        {
+            values[(int)i] = i;
+        }
+        
+        shuffle( values );
+
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    long val = values[( int )( i * increment + j )];
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.insert( writeTxn, val, Long.toString( val ) );
+                }
+            }
+        }
+
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
+        int counter = 0;
+
+        try ( Transaction readTxn = recordManager.beginReadTransaction() )
+        {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
+            TupleCursor<Long, String> cursor = btree.browse( readTxn );
+    
+            while ( cursor.hasNext() )
+            {
+                cursor.next();
+                counter++;
+            }
+        }
+        
+        assertEquals( nbRound, counter );
+        
+        // Now delete the elements
+        shuffle( values );
+        
+        increment = 1L;
+        
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            //System.out.println( "\nInserting " + i + " in the tree ---->" );
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    int elemNb = ( int )( i * increment + j );
+                    long val = values[elemNb];
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.delete( writeTxn, val );
+                }
+            }
+        }
+    }
+    
+    
+    @Test
+    public void testReopen() throws Exception
+    {
+        // Inject some data
+        long increment = 1L;
+        long nbRound = 100L;
+        long t0 = System.currentTimeMillis();
+
+        long[] values = new long[(int)nbRound];
+        
+        for ( long i = 0; i < nbRound; i++ )
+        {
+            values[(int)i] = i;
+        }
+        
+        //shuffle( values );
+        //printValues( values );
+        values = new long[]
+            {
+                38, 40, 61, 34, 9, 59, 78, 30, 42, 76, 84, 52, 37, 58, 88, 27, 24, 22, 33, 39, 
+                74, 44, 65, 45, 70, 98, 64, 99, 31, 19, 95, 57, 35, 90, 68, 1, 12, 69, 77, 73, 83, 
+                6, 96, 80, 7, 23, 43, 85, 36, 48, 32, 66, 53, 87, 16, 10, 15, 13, 5, 91, 54, 71, 
+                92, 72, 82, 63, 97, 62, 26, 56, 41, 18, 11, 3, 21, 75, 46, 67, 93, 2, 28, 29, 25, 
+                14, 0, 94, 4, 81, 20, 55, 8, 79, 51, 50, 60, 86, 89, 47, 49, 17
+            };
+
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    int pos = ( int )( i * increment + j );
+                    long val = values[pos];
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    System.out.println( "Adding value " + pos );
+                    btree.insert( writeTxn, val, Long.toString( val ) );
+                }
+            }
+        }
+
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
+        
+        recordManager.close();
+        recordManager = new RecordManager( dataDir.getAbsolutePath() );
+        
+        int counter = 0;
+
+        try ( Transaction readTxn = recordManager.beginReadTransaction() )
+        {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
+            TupleCursor<Long, String> cursor = btree.browse( readTxn );
+    
+            while ( cursor.hasNext() )
+            {
+                cursor.next();
+                counter++;
+            }
+        }
+        
+        assertEquals( nbRound, counter );
+        
+        // Now delete the elements
+        //shuffle( values );
+        //printValues( values );
+        values = new long[]
+            {
+                13, 42, 95, 59, 96, 62, 39, 90, 32, 5, 20, 7, 37, 63, 25, 17, 23, 97, 4, 16, 
+                53, 69, 89, 9, 80, 71, 19, 22, 31, 33, 12, 29, 34, 65, 6, 57, 15, 18, 24, 93, 38, 
+                92, 83, 98, 28, 0, 21, 94, 8, 64, 14, 40, 48, 26, 41, 66, 81, 52, 82, 88, 68, 74, 
+                55, 84, 54, 79, 61, 87, 67, 99, 36, 47, 1, 86, 58, 50, 51, 75, 49, 56, 27, 78, 60, 
+                45, 30, 77, 46, 73, 35, 43, 91, 85, 70, 44, 11, 10, 3, 72, 2, 76
+            };
+        
+        increment = 1L;
+        
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            //System.out.println( "\nInserting " + i + " in the tree ---->" );
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    int elemNb = ( int )( i * increment + j );
+                    long val = values[elemNb];
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    System.out.println( "Removing value " + val );
+                    btree.delete( writeTxn, val );
+                }
+            }
+        }
+    }
+
+    
+    private void printValues( long[] values )
+    {
+        boolean isFirst = true;
+        int nbVal = 0;
+        StringBuilder sb = new StringBuilder();
+        
+        for ( long val : values )
+        {
+            if ( isFirst )
+            {
+                sb.append( "    long[] values = new long[]\n    {\n        " );
+                isFirst = false;
+            }
+            else
+            {
+                sb.append( ", " );
+            }
+            
+            if ( nbVal == 20 )
+            {
+                nbVal = 0;
+                sb.append( "\n        " );
+            }
+            else
+            {
+                nbVal++;
+            }
+            
+            sb.append( val );
+        }
+        
+        sb.append( "\n    };" );
+        
+        System.out.println(  sb.toString() );
+    }
+    
+    
+    @Test
+    public void testDeleteDebug() throws Exception
+    {
+        btree.setPageNbElem( 4 );
+
+        // Inject some data
+        long increment = 20L;
+        long nbRound = 1000L;
+        long t0 = System.currentTimeMillis();
+
+        long[] values = new long[]
+            {
+                962, 598, 975, 719, 246, 498, 482, 326, 205, 777, 73, 12, 847, 428, 934, 533, 149, 20, 334, 686, 
+                139, 40, 640, 438, 838, 999, 827, 560, 658, 868, 798, 55, 112, 315, 435, 153, 451, 280, 570, 769, 665, 
+                821, 86, 780, 587, 557, 900, 59, 884, 657, 240, 324, 448, 287, 92, 693, 169, 439, 959, 677, 254, 23, 
+                212, 22, 387, 765, 596, 915, 486, 573, 219, 339, 304, 16, 187, 823, 933, 423, 109, 113, 741, 436, 420, 
+                290, 250, 926, 181, 150, 321, 558, 67, 628, 432, 90, 745, 302, 586, 742, 521, 910, 978, 314, 322, 568, 
+                295, 221, 178, 316, 360, 552, 747, 309, 578, 588, 8, 503, 244, 468, 261, 269, 846, 170, 367, 815, 459, 
+                750, 607, 662, 399, 427, 79, 496, 7, 15, 203, 717, 264, 664, 799, 887, 687, 278, 143, 793, 383, 623, 
+                553, 325, 446, 536, 335, 692, 297, 257, 273, 495, 699, 499, 60, 308, 141, 58, 951, 976, 106, 480, 901, 
+                947, 104, 224, 861, 146, 694, 466, 547, 229, 525, 133, 262, 748, 487, 801, 283, 878, 505, 718, 906, 230, 
+                709, 164, 182, 862, 49, 582, 831, 300, 2, 614, 527, 621, 402, 194, 585, 253, 667, 215, 108, 963, 886, 
+                648, 161, 350, 924, 391, 422, 63, 775, 405, 740, 381, 601, 98, 970, 948, 688, 500, 53, 344, 35, 803, 
+                771, 61, 235, 708, 892, 0, 42, 701, 208, 863, 356, 713, 802, 158, 920, 888, 24, 974, 540, 368, 794, 
+                770, 492, 561, 370, 29, 622, 17, 619, 893, 983, 817, 567, 345, 767, 818, 564, 995, 929, 199, 425, 174, 
+                816, 424, 992, 515, 569, 602, 218, 659, 781, 216, 225, 790, 416, 213, 627, 103, 551, 579, 954, 372, 171, 
+                398, 768, 75, 909, 833, 33, 822, 969, 679, 882, 695, 167, 649, 592, 964, 263, 788, 864, 41, 227, 876, 
+                896, 875, 268, 691, 609, 418, 319, 606, 421, 732, 68, 542, 479, 464, 36, 826, 122, 668, 493, 944, 537, 
+                96, 508, 147, 660, 516, 475, 941, 37, 298, 461, 114, 891, 13, 841, 584, 997, 766, 674, 313, 656, 160, 
+                787, 384, 172, 689, 65, 559, 762, 286, 785, 837, 100, 931, 867, 120, 949, 942, 129, 4, 115, 359, 755, 
+                354, 987, 39, 676, 724, 624, 11, 365, 458, 705, 245, 825, 782, 895, 911, 144, 866, 443, 835, 946, 156, 
+                773, 21, 714, 54, 419, 756, 470, 743, 338, 341, 204, 734, 238, 357, 807, 267, 855, 47, 433, 460, 544, 
+                604, 829, 548, 943, 550, 532, 990, 353, 671, 131, 471, 871, 340, 201, 501, 51, 452, 562, 510, 196, 851, 
+                883, 965, 28, 337, 727, 77, 574, 507, 481, 546, 200, 539, 565, 362, 912, 43, 778, 595, 34, 666, 409, 
+                27, 66, 491, 814, 226, 389, 608, 291, 407, 472, 454, 673, 168, 3, 638, 366, 210, 277, 397, 519, 469, 
+                95, 758, 956, 563, 889, 123, 738, 902, 198, 710, 981, 955, 760, 97, 166, 819, 260, 850, 957, 351, 549, 
+                434, 632, 57, 809, 32, 299, 259, 1, 581, 848, 860, 396, 828, 744, 274, 746, 414, 214, 327, 26, 99, 
+                71, 415, 14, 494, 683, 786, 38, 31, 986, 820, 64, 348, 395, 626, 634, 9, 852, 531, 307, 543, 958, 
+                455, 132, 806, 594, 330, 994, 935, 752, 968, 761, 504, 430, 288, 796, 897, 647, 282, 918, 706, 233, 730, 
+                332, 117, 25, 485, 757, 162, 642, 824, 93, 83, 333, 222, 441, 52, 363, 857, 928, 529, 232, 84, 776, 
+                843, 483, 700, 711, 456, 523, 591, 655, 853, 251, 369, 960, 996, 654, 101, 393, 797, 50, 859, 292, 795, 
+                406, 590, 932, 85, 530, 352, 145, 725, 922, 927, 388, 275, 937, 961, 175, 513, 284, 885, 749, 124, 753, 
+                437, 804, 832, 840, 111, 258, 242, 630, 121, 78, 739, 764, 572, 107, 830, 779, 94, 509, 808, 890, 159, 
+                684, 707, 457, 236, 980, 880, 940, 88, 600, 759, 192, 331, 952, 731, 239, 184, 899, 663, 317, 207, 318, 
+                979, 392, 234, 462, 189, 580, 105, 763, 478, 18, 939, 467, 364, 904, 643, 938, 620, 858, 998, 811, 417, 
+                813, 720, 135, 445, 10, 46, 783, 228, 898, 715, 408, 873, 612, 48, 571, 231, 792, 905, 675, 680, 704, 
+                252, 526, 358, 716, 615, 426, 394, 599, 916, 248, 220, 751, 126, 678, 522, 812, 431, 726, 839, 349, 346, 
+                157, 134, 87, 844, 62, 74, 894, 512, 490, 404, 528, 281, 69, 712, 836, 834, 279, 82, 474, 800, 271, 
+                945, 610, 669, 791, 917, 444, 217, 524, 382, 541, 342, 617, 410, 152, 737, 136, 163, 930, 361, 907, 636, 
+                877, 518, 127, 403, 223, 130, 772, 682, 237, 914, 400, 881, 872, 633, 685, 312, 211, 729, 449, 310, 19, 
+                936, 188, 272, 266, 118, 625, 611, 465, 810, 142, 125, 151, 735, 256, 670, 593, 650, 328, 440, 984, 870, 
+                378, 520, 566, 723, 556, 616, 255, 646, 545, 514, 371, 320, 605, 347, 249, 476, 165, 950, 702, 138, 506, 
+                966, 265, 576, 185, 56, 774, 698, 805, 177, 629, 190, 305, 390, 186, 323, 644, 183, 76, 635, 209, 80, 
+                583, 869, 923, 991, 789, 375, 577, 155, 639, 116, 988, 502, 128, 672, 645, 270, 285, 180, 343, 971, 385, 
+                511, 247, 137, 110, 119, 989, 442, 736, 879, 429, 603, 294, 697, 589, 450, 6, 690, 179, 45, 72, 473, 
+                453, 311, 243, 463, 754, 661, 874, 30, 534, 303, 919, 631, 681, 376, 722, 488, 972, 993, 489, 925, 447, 
+                651, 355, 842, 154, 81, 575, 733, 921, 903, 703, 148, 484, 653, 379, 70, 554, 967, 652, 973, 301, 721, 
+                597, 276, 306, 380, 977, 477, 641, 197, 206, 377, 535, 497, 696, 293, 373, 908, 845, 191, 618, 555, 538, 
+                728, 784, 411, 982, 140, 289, 5, 176, 413, 517, 296, 102, 173, 44, 613, 386, 856, 91, 89, 241, 913, 
+                849, 953, 865, 637, 193, 985, 401, 412, 202, 195, 336, 374, 329, 854
+            };
+        
+        for ( long i = 0; i < nbRound; i++ )
+        {
+            values[(int)i] = i;
+        }
+        
+        //shuffle( values );
+
+        //printValues( values );
+
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            //System.out.println( "\nInserting " + i + " in the tree ---->" );
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    long val = values[( int )( i * increment + j )];
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.insert( writeTxn, val, Long.toString( val ) );
+                }
+            }
+        }
+
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
+        int counter = 0;
+
+        try ( Transaction readTxn = recordManager.beginReadTransaction() )
+        {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
+            TupleCursor<Long, String> cursor = btree.browse( readTxn );
+    
+            while ( cursor.hasNext() )
+            {
+                cursor.next();
+                counter++;
+            }
+        }
+        
+        assertEquals( nbRound, counter );
+
+        try ( Transaction readTxn = recordManager.beginReadTransaction() )
+        {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
+        }
+
+        // Now delete the elements
+        //shuffle( values );
+        
+        //printValues( values );
+        values = new long[]
+            {
+                477, 459, 542, 462, 119, 743, 714, 881, 24, 561, 550, 583, 38, 562, 417, 954, 893, 421, 173, 25, 
+                766, 70, 928, 685, 797, 839, 313, 599, 885, 386, 573, 246, 763, 936, 430, 380, 327, 169, 318, 631, 677, 
+                332, 123, 596, 312, 449, 105, 129, 533, 435, 985, 465, 978, 3, 315, 911, 463, 632, 520, 323, 142, 19, 
+                937, 609, 755, 216, 614, 329, 617, 628, 87, 440, 745, 222, 616, 842, 657, 856, 776, 405, 373, 841, 292, 
+                389, 107, 309, 947, 460, 930, 43, 636, 961, 886, 703, 57, 718, 431, 39, 643, 224, 383, 269, 896, 346, 
+                579, 512, 147, 910, 448, 234, 706, 995, 296, 917, 442, 131, 721, 487, 209, 126, 339, 555, 33, 475, 876, 
+                135, 957, 408, 199, 571, 557, 554, 396, 31, 35, 8, 948, 395, 914, 905, 214, 601, 809, 64, 761, 551, 
+                700, 575, 106, 65, 193, 275, 606, 892, 41, 875, 420, 852, 168, 879, 238, 618, 996, 356, 515, 91, 553, 
+                402, 26, 895, 83, 756, 227, 788, 784, 964, 974, 391, 494, 748, 334, 211, 942, 864, 452, 682, 270, 50, 
+                653, 593, 367, 68, 861, 289, 900, 218, 711, 413, 615, 656, 854, 869, 534, 923, 675, 285, 673, 267, 932, 
+                497, 316, 139, 620, 567, 751, 759, 48, 965, 314, 845, 630, 658, 172, 384, 707, 683, 186, 953, 406, 32, 
+                783, 728, 587, 882, 15, 559, 539, 742, 870, 828, 655, 713, 22, 716, 984, 693, 749, 723, 972, 114, 511, 
+                345, 27, 264, 350, 704, 662, 272, 970, 621, 454, 484, 437, 916, 310, 560, 358, 200, 684, 196, 324, 890, 
+                92, 20, 605, 546, 127, 291, 526, 790, 337, 732, 151, 758, 966, 924, 578, 423, 818, 701, 66, 590, 441, 
+                752, 582, 453, 991, 793, 230, 804, 377, 245, 705, 648, 153, 295, 623, 128, 258, 833, 753, 989, 100, 425, 
+                496, 600, 7, 152, 342, 439, 176, 143, 73, 810, 592, 674, 495, 538, 192, 122, 979, 306, 671, 540, 271, 
+                519, 754, 164, 805, 777, 665, 501, 821, 522, 474, 125, 692, 308, 158, 456, 365, 819, 846, 277, 263, 221, 
+                543, 353, 175, 51, 155, 687, 604, 960, 796, 254, 720, 443, 6, 897, 336, 278, 719, 891, 572, 872, 447, 
+                466, 779, 997, 398, 351, 480, 159, 253, 612, 949, 814, 328, 789, 60, 565, 299, 162, 467, 851, 531, 212, 
+                906, 727, 803, 228, 799, 827, 40, 689, 58, 986, 568, 231, 201, 768, 82, 873, 77, 348, 775, 45, 624, 
+                28, 134, 969, 49, 154, 18, 364, 999, 676, 633, 668, 737, 778, 971, 547, 170, 840, 436, 21, 444, 798, 
+                232, 85, 874, 666, 108, 925, 862, 481, 629, 934, 446, 410, 871, 317, 392, 516, 699, 530, 887, 335, 859, 
+                30, 229, 78, 645, 902, 800, 301, 67, 355, 619, 563, 834, 988, 379, 903, 322, 2, 300, 394, 667, 381, 
+                10, 717, 149, 427, 409, 217, 787, 724, 963, 830, 148, 69, 235, 469, 124, 597, 97, 549, 794, 378, 341, 
+                785, 801, 847, 849, 478, 260, 145, 920, 652, 837, 973, 843, 177, 762, 188, 962, 347, 491, 844, 922, 608, 
+                907, 992, 670, 697, 184, 23, 344, 510, 880, 865, 262, 935, 207, 458, 330, 982, 654, 878, 595, 868, 112, 
+                939, 607, 321, 532, 528, 72, 663, 294, 369, 411, 182, 251, 130, 698, 817, 760, 951, 722, 366, 712, 850, 
+                857, 544, 136, 509, 412, 86, 117, 79, 113, 215, 382, 101, 426, 102, 103, 933, 244, 359, 634, 884, 503, 
+                290, 672, 644, 265, 651, 94, 816, 577, 500, 223, 527, 750, 735, 226, 338, 362, 586, 450, 541, 434, 249, 
+                588, 121, 836, 598, 918, 240, 994, 422, 403, 288, 388, 397, 472, 659, 564, 625, 42, 204, 493, 191, 537, 
+                187, 715, 237, 208, 738, 505, 926, 853, 220, 639, 393, 93, 12, 647, 326, 281, 451, 118, 782, 640, 990, 
+                374, 940, 213, 944, 832, 138, 471, 773, 908, 977, 202, 55, 268, 53, 116, 464, 998, 650, 319, 680, 210, 
+                729, 952, 286, 11, 764, 611, 433, 955, 400, 160, 780, 570, 822, 407, 349, 866, 284, 490, 709, 171, 185, 
+                558, 502, 479, 461, 225, 694, 980, 390, 813, 418, 938, 104, 89, 241, 311, 913, 280, 357, 904, 976, 638, 
+                178, 476, 424, 679, 771, 370, 298, 166, 63, 483, 807, 203, 489, 189, 95, 283, 62, 331, 525, 695, 860, 
+                368, 678, 16, 363, 75, 855, 946, 37, 959, 646, 792, 219, 414, 252, 956, 54, 195, 642, 603, 302, 791, 
+                486, 372, 261, 34, 361, 150, 1, 726, 146, 521, 580, 276, 432, 325, 734, 157, 696, 233, 919, 731, 255, 
+                110, 909, 806, 993, 257, 688, 293, 835, 132, 499, 156, 194, 740, 536, 808, 320, 594, 181, 641, 340, 746, 
+                690, 376, 498, 115, 206, 61, 757, 47, 867, 576, 820, 637, 399, 610, 385, 730, 297, 180, 141, 248, 266, 
+                517, 56, 17, 236, 802, 767, 812, 591, 360, 921, 649, 602, 183, 725, 710, 488, 535, 772, 627, 898, 98, 
+                901, 507, 163, 589, 552, 273, 584, 975, 770, 664, 958, 929, 71, 899, 84, 669, 894, 46, 774, 848, 419, 
+                987, 795, 304, 333, 9, 282, 5, 354, 514, 404, 927, 983, 585, 574, 781, 303, 545, 581, 29, 556, 259, 
+                96, 877, 529, 811, 825, 415, 548, 120, 375, 287, 445, 945, 243, 14, 99, 686, 438, 635, 863, 508, 482, 
+                826, 90, 111, 736, 428, 769, 473, 88, 660, 824, 823, 950, 416, 239, 702, 931, 13, 889, 915, 0, 144, 
+                343, 741, 566, 941, 371, 661, 829, 733, 161, 274, 401, 815, 513, 981, 76, 305, 250, 205, 883, 455, 626, 
+                968, 786, 967, 44, 943, 681, 198, 739, 506, 858, 523, 80, 133, 765, 708, 744, 179, 468, 429, 485, 256, 
+                457, 4, 242, 74, 518, 52, 524, 691, 387, 492, 307, 912, 831, 613, 888, 167, 247, 838, 81, 279, 109, 
+                190, 352, 470, 59, 140, 174, 504, 165, 747, 137, 622, 36, 569, 197
+            };
+
+        increment = 1L;
+        
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            //System.out.println( "\nInserting " + i + " in the tree ---->" );
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    int elemNb = ( int )( i * increment + j );
+                    long val = values[elemNb];
+                    System.out.println( "deleting " + elemNb );
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.delete( writeTxn, val );
+                }
+            }
+        }
+    }
+    
+    
+    @Test
+    public void testDelete() throws Exception
+    {
+        //btree.setPageNbElem( 8 );
+
+        // Inject some data
+        long increment = 1_000L;
+        long nbRound = 100_000L;
+        long t0 = System.currentTimeMillis();
+
+        long[] values = new long[(int)nbRound];
+
+        for ( long i = 0; i < nbRound; i++ )
+        {
+            values[(int)i] = i;
+        }
+        
+        shuffle( values );
+        //printValues( values );
+
+        /*values = new long[]
+            {
+                71, 61, 17, 29, 86, 3, 26, 40, 73, 89, 15, 83, 65, 34, 53, 24, 14, 1, 36, 75, 
+                80, 74, 23, 6, 19, 94, 2, 90, 85, 98, 41, 84, 69, 79, 56, 48, 52, 72, 39, 13, 57, 
+                12, 45, 97, 59, 5, 35, 16, 58, 21, 81, 54, 42, 28, 66, 22, 91, 64, 51, 60, 70, 62, 
+                92, 46, 4, 37, 32, 96, 31, 50, 33, 77, 99, 27, 49, 67, 47, 43, 68, 78, 20, 9, 38, 
+                8, 18, 25, 10, 30, 0, 82, 76, 87, 55, 44, 95, 88, 93, 11, 63, 7
+            };
+        */
+
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            //System.out.println( "\nInserting " + i + " in the tree ---->" );
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    long val = values[( int )( i * increment + j )];
+                    //System.out.println( "\n\nInjecting " + val );
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.insert( writeTxn, val, Long.toString( val ) );
+                }
+            }
+        }
+
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
+        int counter = 0;
+
+        try ( Transaction readTxn = recordManager.beginReadTransaction() )
+        {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
+            TupleCursor<Long, String> cursor = btree.browse( readTxn );
+    
+            while ( cursor.hasNext() )
+            {
+                cursor.next();
+                counter++;
+            }
+        }
+        
+        assertEquals( nbRound, counter );
+        
+        // Now delete the elements
+        shuffle( values );
+        
+        //printValues( values );
+        /*
+        values = new long[]
+            {
+                88, 87, 32, 74, 16, 18, 70, 99, 62, 19, 5, 40, 7, 73, 21, 22, 79, 13, 89, 9, 
+                42, 17, 20, 68, 8, 65, 78, 31, 30, 69, 92, 57, 50, 29, 98, 34, 52, 35, 12, 27, 1, 
+                53, 82, 39, 44, 76, 55, 61, 24, 10, 36, 14, 33, 48, 80, 15, 28, 64, 49, 97, 77, 43, 
+                47, 56, 37, 71, 81, 63, 6, 38, 84, 23, 93, 67, 95, 96, 54, 60, 91, 51, 94, 58, 85, 
+                11, 83, 72, 45, 0, 46, 26, 2, 25, 86, 3, 59, 75, 90, 66, 41, 4
+            };
+        //increment = 1L;
+         */
+        
+        long tt0 = System.currentTimeMillis();
+
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            //System.out.println( "\nInserting " + i + " in the tree ---->" );
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    int elemNb = ( int )( i * increment + j );
+                    long val = values[elemNb];
+                    //System.out.println( "Deleting " + elemNb + "th element : " + val );
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.delete( writeTxn, val );
+                }
+            }
+        }
+
+        long tt1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta for " + nbRound + " : " + ( tt1 - tt0 ) );
+    }
+
+    
+    @Test
+    public void testDeleteRandom() throws Exception
+    {
+        btree.setPageNbElem( 4 );
+
+        // Inject some data
+        long increment = 1L;
+        long t0 = System.currentTimeMillis();
+
+        //long[] values = new long[(int)nbRound];
+        long[] values = new long[]
+            {
+                6, 9, 4, 13, 10, 12, 11, 3, 2, 8,
+                15, 16, 7, 14, 1, 5, 0
+        };
+        long nbRound = values.length;
+
+        /*
+        for ( long i = 0; i < nbRound; i++ )
+        {
+            values[(int)i] = i;
+        }
+        
+        shuffle( values );
+        */
+
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            //System.out.println( "\nInserting " + i + " in the tree ---->" );
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    long val = values[( int )( i * increment + j )];
+                    //System.out.println( "Injecting " + val );
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.insert( writeTxn, val, Long.toString( val ) );
+                }
+                
+                System.out.println( btree );
+            }
+        }
+
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
+        int counter = 0;
+
+        /*values = new long[]
+            {
+                13, 14
+        };*/
+
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+                
+                for ( long j = 0; j < increment; j++ )
+                {
+                    long val = values[( int )( i * increment + j )];
+
+                    System.out.println( "Deleting " + val );
+                    btree.delete( writeTxn, val );
+                    System.out.println( btree );
+                }
+            }
+        }
+    }
+
+
+    /**
+     * Test the browse methods on a btree containing many nodes
+     */
+    @Test
+    public void testDeleteBTreeNodes() throws Exception
+    {
+        // Inject some data
+        long increment = 2L;
+        long nbRound = 32L;
+        long t0 = System.currentTimeMillis();
+        
+        for ( long i = 0; i < nbRound/increment; i++ )
+        {
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( long j = 0; j < increment; j++ )
+                {
+                    long val = i*increment + j;
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.insert( writeTxn, val, Long.toString( val ) );
+                }
+            }
+        }
+
+        long t1 = System.currentTimeMillis();
+        
+        System.out.println( "Delta add    : " + ( t1 - t0 ) );
+        System.out.println( "File name    : " + dataDir );
+        
+        long[] values = new long[(int)nbRound];
+        
+        for ( long i = 0; i < nbRound; i++ )
+        {
+            values[(int)i] = i;
+        }
+        
+        shuffle( values );
+        
+        //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+        long t10 = System.currentTimeMillis();
+        
+        for ( int i = 0; i < nbRound/increment; i++ )
+        {
+            try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
+            {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
+                for ( int j = 0; j < increment; j++ )
+                {
+                    int index = (int)(i*increment + j);
+                    //MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+                    btree.delete( writeTxn, values[index] );
+                }
+            }
+            
+            // Check that we can still browse the tree
+            try ( Transaction readTxn = recordManager.beginReadTransaction() )
+            {
+                BTree<Long, String> readBtree = readTxn.getBTree( "test" );
+                TupleCursor<Long, String> cursor = readBtree.browse( readTxn );
+                
+                cursor.beforeFirst();
+                int nbElems = 0;
+                
+                while ( cursor.hasNext() )
+                {
+                    cursor.next();
+                    nbElems++;
+                }
+                
+                assertEquals( nbElems, nbRound - increment * ( i + 1 ) );
+            }
+        }
+
+        long t11 = System.currentTimeMillis();
+        
+        System.out.println( "Delta delete    : " + ( t11 - t10 ) );
+
+        // Create the cursor
+        try ( Transaction readTxn = recordManager.beginReadTransaction() )
+        {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
+            TupleCursor<Long, String> cursor = btree.browse( readTxn );
+
+            // Move forward
+            cursor.afterLast();
+            cursor.beforeFirst();
+    
+            assertFalse( cursor.hasPrev() );
+            assertFalse( cursor.hasNext() );
         }
     }
 
@@ -610,17 +1336,19 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             for ( long i = 1; i < 1_000L; i++ )
             {
                 btree.insert( writeTxn, i, Long.toString( i ) );
             }
         }
 
-        MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
+        //MavibotInspector.check( recordManager, recordManager.getCurrentRecordManagerHeader() );
 
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
 
             // Move backward
@@ -652,6 +1380,7 @@ public class BTreeBrowseTest
         // Inject some duplicate data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             btree.insert( writeTxn, 1L, "1" );
             btree.insert( writeTxn, 1L, "4" );
             btree.insert( writeTxn, 1L, "2" );
@@ -664,6 +1393,7 @@ public class BTreeBrowseTest
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
     
             // Move forward
@@ -690,6 +1420,7 @@ public class BTreeBrowseTest
     {
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browseFrom( readTxn, 1L );
     
             assertFalse( cursor.hasNext() );
@@ -729,6 +1460,7 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             btree.insert( writeTxn, 1L, "1" );
             btree.insert( writeTxn, 7L, "7" );
             btree.insert( writeTxn, 3L, "3" );
@@ -739,6 +1471,7 @@ public class BTreeBrowseTest
         // Create the cursor, starting at 5
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browseFrom( readTxn, 5L );
     
             assertTrue( cursor.hasPrev() );
@@ -817,6 +1550,8 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
+
             for ( long i = 0; i <= 1000L; i += 2 )
             {
                 btree.insert( writeTxn, i, Long.toString( i ) );
@@ -826,6 +1561,7 @@ public class BTreeBrowseTest
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browseFrom( readTxn, 1500L );
     
             assertFalse( cursor.hasNext() );
@@ -846,15 +1582,26 @@ public class BTreeBrowseTest
         // Inject some data
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
+            
             for ( long i = 1; i < 1000L; i++ )
             {
-                btree.insert( writeTxn, i, Long.toString( i ) );
+                System.out.println( "Insert " + i );
+                try
+                {
+                    btree.insert( writeTxn, i, Long.toString( i ) );
+                }
+                catch ( Exception e )
+                {
+                    e.printStackTrace();
+                }
             }
         }
 
         // Create the cursor
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
     
             // Move backward
@@ -895,11 +1642,13 @@ public class BTreeBrowseTest
     {
         try ( WriteTransaction writeTxn = recordManager.beginWriteTransaction() )
         {
+            BTree<Long, String> btree = writeTxn.getBTree( "test" );
             btree.insert( writeTxn, 1L, "1" );
         }
 
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             assertTrue( btree.hasKey( readTxn, 1L ) );
     
             assertEquals( "1", btree.get( readTxn, 1L ) );
@@ -917,7 +1666,7 @@ public class BTreeBrowseTest
     }
 
 
-    @Ignore("test used for debugging")
+    //@Ignore("test used for debugging")
     @Test
     public void testAdd20Random() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
     {
@@ -934,18 +1683,19 @@ public class BTreeBrowseTest
         {
             for ( long value : values )
             {
+                BTree<Long, String> btree = writeTxn.getBTree( "test" );
                 btree.insert( writeTxn, value, Long.toString( value ) );
-                System.out.println( btree );
             }
         }
 
         try ( Transaction readTxn = recordManager.beginReadTransaction() )
         {
+            BTree<Long, String> btree = readTxn.getBTree( "test" );
             TupleCursor<Long, String> cursor = btree.browse( readTxn );
     
             while ( cursor.hasNext() )
             {
-                System.out.println( cursor.next() );
+                cursor.next();
             }
         }
     }

Modified: directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBuilderTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBuilderTest.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBuilderTest.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BTreeBuilderTest.java Mon Oct  9 20:32:59 2017
@@ -114,7 +114,7 @@ public class BTreeBuilderTest
             {
                 btree = rm.getBtree( txn, "master" );
     
-                assertEquals( 7, btree.getRootPage().getNbPageElems() );
+                assertEquals( 7, btree.getRootPage().getPageNbElems() );
     
                 assertEquals( 7, btree.getRootPage().findRightMost().getKey().intValue() );
     

Modified: directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java Mon Oct  9 20:32:59 2017
@@ -93,7 +93,7 @@ public class BulkLoaderTest
             try
             {
                 RecordManager rm = new RecordManager( file.getAbsolutePath() );
-                BTreeImpl<Long, String> btree = ( BTreeImpl<Long, String> ) rm.addBTree( "test",
+                BTree<Long, String> btree = ( BTree<Long, String> ) rm.addBTree( "test",
                     LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
                 btree.setPageSize( 64 );
 
@@ -213,7 +213,7 @@ public class BulkLoaderTest
         try
         {
             RecordManager rm = new RecordManager( file.getAbsolutePath() );
-            BTreeImpl<Long, String> btree = ( BTreeImpl<Long, String> ) rm.addBTree( "test",
+            BTree<Long, String> btree = ( BTree<Long, String> ) rm.addBTree( "test",
                 LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
 
             int[] expectedNbPages = new int[]
@@ -270,7 +270,7 @@ public class BulkLoaderTest
         try
         {
             RecordManager rm = new RecordManager( file.getAbsolutePath() );
-            BTreeImpl<Long, String> btree = ( BTreeImpl<Long, String> ) rm.addBTree( "test",
+            BTree<Long, String> btree = ( BTree<Long, String> ) rm.addBTree( "test",
                 LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
 
             int[] expectedNbPages = new int[]
@@ -325,7 +325,7 @@ public class BulkLoaderTest
         try
         {
             RecordManager rm = new RecordManager( file.getAbsolutePath() );
-            BTreeImpl<Long, String> btree = ( BTreeImpl<Long, String> ) rm.addBTree( "test",
+            BTree<Long, String> btree = ( BTree<Long, String> ) rm.addBTree( "test",
                 LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
 
             int[] expectedNbPages = new int[]
@@ -380,7 +380,7 @@ public class BulkLoaderTest
             try
             {
                 RecordManager rm = new RecordManager( file.getAbsolutePath() );
-                BTreeImpl<Long, String> btree = ( BTreeImpl<Long, String> ) rm.addBTree( "test",
+                BTree<Long, String> btree = ( BTree<Long, String> ) rm.addBTree( "test",
                     LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
 
                 int nbElems = i;
@@ -512,7 +512,7 @@ public class BulkLoaderTest
         try
         {
             RecordManager rm = new RecordManager( file.getAbsolutePath() );
-            BTreeImpl<Long, String> btree = ( BTreeImpl<Long, String> ) rm.addBTree( "test",
+            BTree<Long, String> btree = ( BTree<Long, String> ) rm.addBTree( "test",
                 LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
 
             int nbElems = 4;
@@ -914,7 +914,7 @@ public class BulkLoaderTest
         try
         {
             RecordManager rm = new RecordManager( file.getAbsolutePath() );
-            BTreeImpl<Long, String> btree = ( BTreeImpl<Long, String> ) rm.addBTree( "test",
+            BTree<Long, String> btree = ( BTree<Long, String> ) rm.addBTree( "test",
                 LongSerializer.INSTANCE, StringSerializer.INSTANCE, false );
 
             // btree.valueThresholdUp = 8;

Modified: directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java?rev=1811602&r1=1811601&r2=1811602&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java Mon Oct  9 20:32:59 2017
@@ -54,7 +54,7 @@ public class PageReclaimerTest
 
     private RecordManager rm;
 
-    private BTreeImpl<Integer, String> uidTree;
+    private BTree<Integer, String> uidTree;
     
     @Rule
     public TemporaryFolder tmpDir;
@@ -74,7 +74,7 @@ public class PageReclaimerTest
         rm = new RecordManager( dbFile.getAbsolutePath() );
         rm.setPageReclaimerThreshold( 10 );
         
-        uidTree = ( BTreeImpl<Integer, String> ) rm.addBTree( TREE_NAME, IntSerializer.INSTANCE, StringSerializer.INSTANCE, false );
+        uidTree = ( BTree<Integer, String> ) rm.addBTree( TREE_NAME, IntSerializer.INSTANCE, StringSerializer.INSTANCE, false );
     }
 
 
@@ -92,7 +92,7 @@ public class PageReclaimerTest
         uidTree.close();
         rm.close();
         rm = new RecordManager( dbFile.getAbsolutePath() );
-        uidTree = ( BTreeImpl ) rm.getBtree( TREE_NAME );
+        uidTree = ( BTree ) rm.getBtree( TREE_NAME );
     }
 
     
@@ -265,7 +265,7 @@ public class PageReclaimerTest
         config.setValueSerializer( StringSerializer.INSTANCE );
         config.setPageSize( 4 );
 
-        BTree btree = new BTreeImpl( config );
+        BTree btree = new BTree( config );
         
         Transaction writeTransaction = new WriteTransaction();