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 2014/02/10 16:35:20 UTC

svn commit: r1566659 [2/6] - in /directory/mavibot/branches/with-txns/mavibot: img/ src/main/java/org/apache/directory/mavibot/btree/ src/main/java/org/apache/directory/mavibot/btree/comparator/ src/main/java/org/apache/directory/mavibot/btree/exceptio...

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeFactory.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeFactory.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeFactory.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeFactory.java Mon Feb 10 15:35:18 2014
@@ -20,22 +20,21 @@
 package org.apache.directory.mavibot.btree;
 
 
-import java.io.IOException;
 import java.util.LinkedList;
 
 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
 
 
 /**
- * This class construct a BTree from a serialized version of a BTree. We need it
- * to avoid exposing all the methods of the BTree class.<br>
- * 
+ * This class construct a B-tree from a serialized version of a B-tree. We need it
+ * to avoid exposing all the methods of the B-tree class.<br>
+ *
  * All its methods are static.
- *  
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  *
- * @param <K> The BTree key type
- * @param <V> The BTree valye type
+ * @param <K> The B-tree key type
+ * @param <V> The B-tree value type
  */
 public class BTreeFactory<K, V>
 {
@@ -44,7 +43,9 @@ public class BTreeFactory<K, V>
     //--------------------------------------------------------------------------------------------
 
     /**
-     * Creates a new persisted BTree, with no initialization. 
+     * Creates a new persisted B-tree, with no initialization.
+     *
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree()
     {
@@ -55,10 +56,11 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new persisted BTree using the BTreeConfiguration to initialize the 
-     * BTree
-     * 
+     * Creates a new persisted B-tree using the BTreeConfiguration to initialize the
+     * B-tree
+     *
      * @param configuration The configuration to use
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree( PersistedBTreeConfiguration<K, V> configuration )
     {
@@ -69,14 +71,13 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new persisted BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new persisted B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
-     * @param allowDuplicates Tells if the BTree allows multiple value for a given key
-     * @throws IOException
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer )
@@ -98,14 +99,14 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new persisted BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new persisted B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
-     * @param allowDuplicates Tells if the BTree allows multiple value for a given key
-     * @throws IOException
+     * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer, boolean allowDuplicates )
@@ -127,15 +128,15 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new persisted BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new persisted B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
-     * @param allowDuplicates Tells if the BTree allows multiple value for a given key
-     * @param cacheSize The size to be used for this BTree cache
-     * @throws IOException
+     * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
+     * @param cacheSize The size to be used for this B-tree cache
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer, boolean allowDuplicates, int cacheSize )
@@ -157,14 +158,14 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new persisted BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new persisted B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
      * @param pageSize Size of the page
-     * @throws IOException
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer, int pageSize )
@@ -186,15 +187,15 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new persisted BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new persisted B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
      * @param pageSize Size of the page
-     * @param allowDuplicates Tells if the BTree allows multiple value for a given key
-     * @throws IOException
+     * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer, int pageSize, boolean allowDuplicates )
@@ -216,16 +217,16 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new persisted BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new persisted B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
      * @param pageSize Size of the page
-     * @param allowDuplicates Tells if the BTree allows multiple value for a given key
-     * @param cacheSize The size to be used for this BTree cache
-     * @throws IOException
+     * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
+     * @param cacheSize The size to be used for this B-tree cache
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createPersistedBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer, int pageSize, boolean allowDuplicates, int cacheSize )
@@ -247,10 +248,12 @@ public class BTreeFactory<K, V>
 
 
     //--------------------------------------------------------------------------------------------
-    // Create in-memory btrees
+    // Create in-memory B-trees
     //--------------------------------------------------------------------------------------------
     /**
-     * Creates a new in-memory BTree, with no initialization. 
+     * Creates a new in-memory B-tree, with no initialization.
+     *
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree()
     {
@@ -261,10 +264,11 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new in-memory BTree using the BTreeConfiguration to initialize the 
-     * BTree
-     * 
+     * Creates a new in-memory B-tree using the BTreeConfiguration to initialize the
+     * B-tree
+     *
      * @param configuration The configuration to use
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree( InMemoryBTreeConfiguration<K, V> configuration )
     {
@@ -275,12 +279,13 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new in-memory BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new in-memory B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer )
@@ -301,14 +306,14 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new in-memory BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new in-memory B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
-     * @param allowDuplicates Tells if the BTree allows multiple value for a given key
-     * @throws IOException
+     * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer, boolean allowDuplicates )
@@ -329,14 +334,14 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new in-memory BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new in-memory B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
      * @param pageSize Size of the page
-     * @throws IOException
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree( String name, ElementSerializer<K> keySerializer,
         ElementSerializer<V> valueSerializer, int pageSize )
@@ -357,14 +362,14 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new in-memory BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new in-memory B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param filePath The name of the data directory with absolute path
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
-     * @throws IOException
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree( String name, String filePath,
         ElementSerializer<K> keySerializer,
@@ -387,19 +392,18 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new in-memory BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new in-memory B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param filePath The name of the data directory with absolute path
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
      * @param pageSize Size of the page
-     * @throws IOException
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree( String name, String filePath,
-        ElementSerializer<K> keySerializer,
-        ElementSerializer<V> valueSerializer, int pageSize )
+        ElementSerializer<K> keySerializer, ElementSerializer<V> valueSerializer, int pageSize )
     {
         InMemoryBTreeConfiguration<K, V> configuration = new InMemoryBTreeConfiguration<K, V>();
 
@@ -418,16 +422,16 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Creates a new in-memory BTree using the parameters to initialize the 
-     * BTree
-     * 
-     * @param name The BTree's name
+     * Creates a new in-memory B-tree using the parameters to initialize the
+     * B-tree
+     *
+     * @param name The B-tree's name
      * @param filePath The name of the data directory with absolute path
      * @param keySerializer Key serializer
      * @param valueSerializer Value serializer
      * @param pageSize Size of the page
-     * @param allowDuplicates Tells if the BTree allows multiple value for a given key
-     * @throws IOException
+     * @param allowDuplicates Tells if the B-tree allows multiple value for a given key
+     * @return a new B-tree instance
      */
     public static <K, V> BTree<K, V> createInMemoryBTree( String name, String filePath,
         ElementSerializer<K> keySerializer,
@@ -453,12 +457,12 @@ public class BTreeFactory<K, V>
     // Create Pages
     //--------------------------------------------------------------------------------------------
     /**
-     * Create a new Leaf for the given BTree.
-     * 
-     * @param btree The BTree which will contain this leaf
+     * Create a new Leaf for the given B-tree.
+     *
+     * @param btree The B-tree which will contain this leaf
      * @param revision The Leaf's revision
      * @param nbElems The number or elements in this leaf
-     * 
+     *
      * @return A Leaf instance
      */
     /* no qualifier*/static <K, V> Page<K, V> createLeaf( BTree<K, V> btree, long revision, int nbElems )
@@ -475,9 +479,9 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Create a new Node for the given BTree.
-     * 
-     * @param btree The BTree which will contain this node
+     * Create a new Node for the given B-tree.
+     *
+     * @param btree The B-tree which will contain this node
      * @param revision The Node's revision
      * @param nbElems The number or elements in this node
      * @return A Node instance
@@ -500,8 +504,8 @@ public class BTreeFactory<K, V>
     //--------------------------------------------------------------------------------------------
     /**
      * Set the key at a give position
-     * 
-     * @param btree The BTree to update
+     *
+     * @param btree The B-tree to update
      * @param page The page to update
      * @param pos The position in the keys array
      * @param key The key to inject
@@ -525,6 +529,9 @@ public class BTreeFactory<K, V>
 
     /**
      * Set the value at a give position
+     *
+     * @param btree The B-tree to update
+     * @param page The page to update
      * @param pos The position in the values array
      * @param value the value to inject
      */
@@ -543,11 +550,11 @@ public class BTreeFactory<K, V>
 
     /**
      * Set the page at a give position
-     * 
-     * @param btree The BTree to update
+     *
+     * @param btree The B-tree to update
      * @param page The page to update
      * @param pos The position in the values array
-     * @param value the value to inject
+     * @param child the child page to inject
      */
     /* no qualifier*/static <K, V> void setPage( BTree<K, V> btree, Page<K, V> page, int pos, Page<K, V> child )
     {
@@ -563,42 +570,48 @@ public class BTreeFactory<K, V>
 
 
     //--------------------------------------------------------------------------------------------
-    // Update BTree
+    // Update B-tree
     //--------------------------------------------------------------------------------------------
     /**
-     * Sets the KeySerializer into the BTree
-     *  
-     * @param btree The BTree to update
+     * Sets the KeySerializer into the B-tree
+     *
+     * @param btree The B-tree to update
      * @param keySerializerFqcn the Key serializer FQCN to set
-     * @throws ClassNotFoundException
-     * @throws InstantiationException 
-     * @throws IllegalAccessException
+     * @throws ClassNotFoundException If the key serializer class cannot be found
+     * @throws InstantiationException If the key serializer class cannot be instanciated
+     * @throws IllegalAccessException If the key serializer class cannot be accessed
+     * @throws NoSuchFieldException
+     * @throws SecurityException
+     * @throws IllegalArgumentException
      */
     /* no qualifier*/static <K, V> void setKeySerializer( BTree<K, V> btree, String keySerializerFqcn )
-        throws ClassNotFoundException, IllegalAccessException, InstantiationException
+        throws ClassNotFoundException, IllegalAccessException, InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException
     {
         Class<?> keySerializer = Class.forName( keySerializerFqcn );
         @SuppressWarnings("unchecked")
-        ElementSerializer<K> instance = ( ElementSerializer<K> ) keySerializer.newInstance();
+        ElementSerializer<K> instance = ( ElementSerializer<K> ) keySerializer.getDeclaredField( "INSTANCE" ).get( null );
         btree.setKeySerializer( instance );
     }
 
 
     /**
-     * Sets the ValueSerializer into the BTree
-     *  
-     * @param btree The BTree to update
+     * Sets the ValueSerializer into the B-tree
+     *
+     * @param btree The B-tree to update
      * @param valueSerializerFqcn the Value serializer FQCN to set
-     * @throws ClassNotFoundException
-     * @throws InstantiationException 
-     * @throws IllegalAccessException
+     * @throws ClassNotFoundException If the value serializer class cannot be found
+     * @throws InstantiationException If the value serializer class cannot be instanciated
+     * @throws IllegalAccessException If the value serializer class cannot be accessed
+     * @throws NoSuchFieldException
+     * @throws SecurityException
+     * @throws IllegalArgumentException
      */
     /* no qualifier*/static <K, V> void setValueSerializer( BTree<K, V> btree, String valueSerializerFqcn )
-        throws ClassNotFoundException, IllegalAccessException, InstantiationException
+        throws ClassNotFoundException, IllegalAccessException, InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException
     {
         Class<?> valueSerializer = Class.forName( valueSerializerFqcn );
         @SuppressWarnings("unchecked")
-        ElementSerializer<V> instance = ( ElementSerializer<V> ) valueSerializer.newInstance();
+        ElementSerializer<V> instance = ( ElementSerializer<V> ) valueSerializer.getDeclaredField( "INSTANCE" ).get( null );
         btree.setValueSerializer( instance );
     }
 
@@ -606,8 +619,8 @@ public class BTreeFactory<K, V>
     /**
      * Set the new root page for this tree. Used for debug purpose only. The revision
      * will always be 0;
-     * 
-     * @param btree The BTree to update
+     *
+     * @param btree The B-tree to update
      * @param root the new root page.
      */
     /* no qualifier*/static <K, V> void setRootPage( BTree<K, V> btree, Page<K, V> root )
@@ -617,9 +630,9 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Return the BTree root page
-     * 
-     * @param btree The Btree we want to root page from
+     * Return the B-tree root page
+     *
+     * @param btree The B-tree we want to root page from
      * @return The root page
      */
     /* no qualifier */static <K, V> Page<K, V> getRootPage( BTree<K, V> btree )
@@ -629,9 +642,9 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * update the BTree number of elements
-     * 
-     * @param btree The BTree to update
+     * Update the B-tree number of elements
+     *
+     * @param btree The B-tree to update
      * @param nbElems the nbElems to set
      */
     /* no qualifier */static <K, V> void setNbElems( BTree<K, V> btree, long nbElems )
@@ -641,9 +654,9 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Update the btree revision
-     * 
-     * @param btree The BTree to update
+     * Update the B-tree revision
+     *
+     * @param btree The B-tree to update
      * @param revision the revision to set
      */
     /* no qualifier*/static <K, V> void setRevision( BTree<K, V> btree, long revision )
@@ -653,9 +666,9 @@ public class BTreeFactory<K, V>
 
 
     /**
-     * Set the BTree name
-     * 
-     * @param btree The BTree to update
+     * Set the B-tree name
+     *
+     * @param btree The B-tree to update
      * @param name the name to set
      */
     /* no qualifier */static <K, V> void setName( BTree<K, V> btree, String name )
@@ -666,8 +679,8 @@ public class BTreeFactory<K, V>
 
     /**
      * Set the maximum number of elements we can store in a page.
-     * 
-     * @param btree The BTree to update
+     *
+     * @param btree The B-tree to update
      * @param pageSize The requested page size
      */
     /* no qualifier */static <K, V> void setPageSize( BTree<K, V> btree, int pageSize )
@@ -681,8 +694,8 @@ public class BTreeFactory<K, V>
     //--------------------------------------------------------------------------------------------
     /**
      * Includes the intermediate nodes in the path up to and including the right most leaf of the tree
-     * 
-     * @param btree the btree
+     *
+     * @param btree the B-tree
      * @return a LinkedList of all the nodes and the final leaf
      */
     /* no qualifier*/static <K, V> LinkedList<ParentPos<K, V>> getPathToRightMostLeaf( BTree<K, V> btree )
@@ -724,12 +737,12 @@ public class BTreeFactory<K, V>
 
 
     //--------------------------------------------------------------------------------------------
-    // Persisted BTree methods
+    // Persisted B-tree methods
     //--------------------------------------------------------------------------------------------
     /**
-     * Set the rootPage offset of the BTree
-     * 
-     * @param btree The btree to update
+     * Set the rootPage offset of the B-tree
+     *
+     * @param btree The B-tree to update
      * @param rootPageOffset The rootPageOffset to set
      */
     /* no qualifier*/static <K, V> void setRootPageOffset( BTree<K, V> btree, long rootPageOffset )
@@ -740,34 +753,15 @@ public class BTreeFactory<K, V>
         }
         else
         {
-            throw new IllegalArgumentException( "The BTree must be a PersistedBTree" );
-        }
-    }
-
-
-    /**
-     * Set the nextBTree offset
-     * 
-     * @param btree The btree to update
-     * @param nextBTreeOffset The nextBTreeOffset to set
-     */
-    /* no qualifier*/static <K, V> void setNextBTreeOffset( BTree<K, V> btree, long nextBTreeOffset )
-    {
-        if ( btree instanceof PersistedBTree )
-        {
-            ( ( PersistedBTree<K, V> ) btree ).setNextBTreeOffset( nextBTreeOffset );
-        }
-        else
-        {
-            throw new IllegalArgumentException( "The BTree must be a PersistedBTree" );
+            throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
         }
     }
 
 
     /**
      * Set the RecordManager
-     * 
-     * @param btree The btree to update
+     *
+     * @param btree The B-tree to update
      * @param recordManager The injected RecordManager
      */
     /* no qualifier*/static <K, V> void setRecordManager( BTree<K, V> btree, RecordManager recordManager )
@@ -778,15 +772,15 @@ public class BTreeFactory<K, V>
         }
         else
         {
-            throw new IllegalArgumentException( "The BTree must be a PersistedBTree" );
+            throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
         }
     }
 
 
     /**
      * Set the key at a give position
-     * 
-     * @param btree The btree to update
+     *
+     * @param btree The B-tree to update
      * @param page The page to update
      * @param pos The position of this key in the page
      * @param buffer The byte[] containing the serialized key
@@ -800,15 +794,15 @@ public class BTreeFactory<K, V>
         }
         else
         {
-            throw new IllegalArgumentException( "The BTree must be a PersistedBTree" );
+            throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
         }
     }
 
 
     /**
      * Includes the intermediate nodes in the path up to and including the left most leaf of the tree
-     * 
-     * @param btree The btree to process
+     *
+     * @param btree The B-tree to process
      * @return a LinkedList of all the nodes and the final leaf
      */
     /* no qualifier*/static <K, V> LinkedList<ParentPos<K, V>> getPathToLeftMostLeaf( BTree<K, V> btree )
@@ -850,7 +844,7 @@ public class BTreeFactory<K, V>
         }
         else
         {
-            throw new IllegalArgumentException( "The BTree must be a PersistedBTree" );
+            throw new IllegalArgumentException( "The B-tree must be a PersistedBTree" );
         }
     }
 }

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeHeader.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeHeader.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeHeader.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeHeader.java Mon Feb 10 15:35:18 2014
@@ -19,13 +19,14 @@
  */
 package org.apache.directory.mavibot.btree;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 
-import java.util.concurrent.atomic.AtomicLong;
 
 
 /**
- * Store in memory the information associated with a BTree. <br>
- * A BTree Header on disk contains the following elements :
+ * Store in memory the information associated with a B-tree. <br>
+ * A B-tree Header on disk contains the following elements :
  * <pre>
  * +--------------------+-------------+
  * | revision           | 8 bytes     |
@@ -49,40 +50,26 @@ import java.util.concurrent.atomic.Atomi
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-/* No qualifier*/class BTreeHeader
+/* No qualifier*/class BTreeHeader<K, V>
 {
     /** The current revision */
-    private AtomicLong revision = new AtomicLong( 0L );
+    private long revision = 0L;
 
-    /** The number of elements in this BTree */
-    private AtomicLong nbElems = new AtomicLong( 0L );
+    /** The number of elements in this B-tree */
+    private Long nbElems = 0L;
 
-    /** The offset of the BTree RootPage */
+    /** The offset of the B-tree RootPage */
     private long rootPageOffset;
 
-    /** The offset of the next BTree */
-    private long nextBTreeOffset;
-
-    /** The number of elements in a page for this BTree */
-    private int pageSize;
-
-    /** The BTree name */
-    private String name;
-
-    /** The FQCN of the Key serializer */
-    private String keySerializerFQCN;
-
-    /** The FQCN of the Value serializer */
-    private String valueSerializerFQCN;
-
     // Those are data which aren't serialized : they are in memory only */
     /** The position in the file */
     private long btreeOffset;
 
-    /** The existing versions */
-    private long[] versions;
+    /** A Map containing the rootPage for this tree */
+    private Page<K, V> rootPage;
 
-    private int allowDuplicates = 0;
+    /** The number of users for this BtreeHeader */
+    private AtomicInteger nbUsers = new AtomicInteger( 0 );
 
 
     /**
@@ -94,42 +81,6 @@ import java.util.concurrent.atomic.Atomi
 
 
     /**
-     * @return the name
-     */
-    public String getName()
-    {
-        return name;
-    }
-
-
-    /**
-     * @param name the name to set
-     */
-    /* no qualifier */void setName( String name )
-    {
-        this.name = name;
-    }
-
-
-    /**
-     * @return the versions
-     */
-    public long[] getVersions()
-    {
-        return versions;
-    }
-
-
-    /**
-     * @param versions the versions to set
-     */
-    /* no qualifier */void setVersions( long[] versions )
-    {
-        this.versions = versions;
-    }
-
-
-    /**
      * @return the btreeOffset
      */
     public long getBTreeOffset()
@@ -170,7 +121,7 @@ import java.util.concurrent.atomic.Atomi
      */
     public long getRevision()
     {
-        return revision.get();
+        return revision;
     }
 
 
@@ -179,18 +130,7 @@ import java.util.concurrent.atomic.Atomi
      */
     /* no qualifier */void setRevision( long revision )
     {
-        this.revision.set( revision );
-    }
-
-
-    /**
-     * Increment the revision
-     *
-     * @return the new revision
-     */
-    /* no qualifier */long incrementRevision()
-    {
-        return revision.incrementAndGet();
+        this.revision = revision;
     }
 
 
@@ -199,25 +139,7 @@ import java.util.concurrent.atomic.Atomi
      */
     public long getNbElems()
     {
-        return nbElems.get();
-    }
-
-
-    /**
-     * Increment the number of elements
-     */
-    /* no qualifier */void incrementNbElems()
-    {
-        nbElems.incrementAndGet();
-    }
-
-
-    /**
-     * Decrement the number of elements
-     */
-    public void decrementNbElems()
-    {
-        nbElems.decrementAndGet();
+        return nbElems;
     }
 
 
@@ -226,91 +148,70 @@ import java.util.concurrent.atomic.Atomi
      */
     /* no qualifier */void setNbElems( long nbElems )
     {
-        this.nbElems.set( nbElems );
+        this.nbElems = nbElems;
     }
 
 
     /**
-     * @return the nextBTreeOffset
-     */
-    public long getNextBTreeOffset()
-    {
-        return nextBTreeOffset;
-    }
-
-
-    /**
-     * @param nextBtreeOffset the nextBtreeOffset to set
+     * Increment the number of elements
      */
-    /* no qualifier */void setNextBTreeOffset( long nextBTreeOffset )
+    /* no qualifier */void incrementNbElems()
     {
-        this.nextBTreeOffset = nextBTreeOffset;
+        nbElems++;
     }
 
 
     /**
-     * @return the pageSize
+     * Decrement the number of elements
      */
-    public int getPageSize()
+    /* no qualifier */void decrementNbElems()
     {
-        return pageSize;
+        nbElems--;
     }
 
 
     /**
-     * @param pageSize the pageSize to set
+     * @return the rootPage
      */
-    /* no qualifier */void setPageSize( int pageSize )
+    /* no qualifier */ Page<K, V> getRootPage()
     {
-        this.pageSize = pageSize;
+        return rootPage;
     }
 
 
     /**
-     * @return the keySerializerFQCN
+     * @param rootPage the rootPage to set
      */
-    public String getKeySerializerFQCN()
+    /* no qualifier */ void setRootPage( Page<K, V> rootPage )
     {
-        return keySerializerFQCN;
+        this.rootPage = rootPage;
     }
 
 
     /**
-     * @param keySerializerFQCN the keySerializerFQCN to set
+     * @return the nbUsers
      */
-    /* no qualifier */void setKeySerializerFQCN( String keySerializerFQCN )
+    /* no qualifier */ int getNbUsers()
     {
-        this.keySerializerFQCN = keySerializerFQCN;
+        return nbUsers.get();
     }
 
 
     /**
-     * @return the valueSerializerFQCN
+     * Increment the number of users
      */
-    public String getValueSerializerFQCN()
+    /* no qualifier */ void incrementNbUsers()
     {
-        return valueSerializerFQCN;
+        nbUsers.incrementAndGet();
     }
 
 
     /**
-     * @param valueSerializerFQCN the valueSerializerFQCN to set
+     * Decrement the number of users
      */
-    /* no qualifier */void setValueSerializerFQCN( String valueSerializerFQCN )
+    /* no qualifier */ void decrementNbUsers()
     {
-        this.valueSerializerFQCN = valueSerializerFQCN;
-    }
-
-
-    public boolean isAllowDuplicates()
-    {
-        return ( allowDuplicates == 1 );
-    }
-
-
-    /* no qualifier */void setAllowDuplicates( boolean allowDuplicates )
-    {
-        this.allowDuplicates = ( allowDuplicates ? 1 : 0 );
+        nbUsers.decrementAndGet();
     }
 
 
@@ -321,42 +222,12 @@ import java.util.concurrent.atomic.Atomi
     {
         StringBuilder sb = new StringBuilder();
 
-        sb.append( "Btree '" ).append( name ).append( "'" );
+        sb.append( "B-treeHeader " );
         sb.append( ", revision[" ).append( revision ).append( "]" );
         sb.append( ", btreeOffset[" ).append( btreeOffset ).append( "]" );
         sb.append( ", rootPageOffset[" ).append( rootPageOffset ).append( "]" );
-        sb.append( ", nextBTree[" ).append( nextBTreeOffset ).append( "]" );
         sb.append( ", nbElems[" ).append( nbElems ).append( "]" );
-        sb.append( ", pageSize[" ).append( pageSize ).append( "]" );
-        sb.append( ", hasDuplicates[" ).append( isAllowDuplicates() ).append( "]" );
-        sb.append( "{\n" );
-        sb.append( "    Key serializer   : " ).append( keySerializerFQCN ).append( "\n" );
-        sb.append( "    Value serializer : " ).append( valueSerializerFQCN ).append( "\n" );
-        sb.append( "}\n" );
-
-        if ( ( versions != null ) && ( versions.length != 0 ) )
-        {
-            sb.append( "Versions : \n" );
-            sb.append( "{\n" );
-
-            boolean isFirst = true;
-
-            for ( long version : versions )
-            {
-                if ( isFirst )
-                {
-                    isFirst = false;
-                }
-                else
-                {
-                    sb.append( ",\n" );
-                }
-
-                sb.append( "    " ).append( version );
-            }
-
-            sb.append( "}\n" );
-        }
+        sb.append( ", nbUsers[" ).append( nbUsers.get() ).append( "]" );
 
         return sb.toString();
     }

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeTypeEnum.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeTypeEnum.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeTypeEnum.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeTypeEnum.java Mon Feb 10 15:35:18 2014
@@ -21,24 +21,32 @@ package org.apache.directory.mavibot.btr
 
 
 /**
- * An enum to describe the BTree type. We have three possible type :
+ * An enum to describe the B-tree type. We have three possible type :
  * <ul>
- * <li>IN_MEMORY : the BTree will remain in memory, and won't be persisted on disk</li>
- * <li>PERSISTENT : the BTree is in memory, but will be persisted on disk</li>
- * <li>MANAGED : the BTree is managed by a RecordManager, and some pages may
+ * <li>IN_MEMORY : the B-tree will remain in memory, and won't be persisted on disk</li>
+ * <li>BACKED_ON_DISK : the B-tree is in memory, but will be persisted on disk</li>
+ * <li>PERSISTED : the B-tree is managed by a RecordManager, and some pages may
  * be swapped out from memory on demand</li>
+ * <li>PERSISTED_SUB : The B-tree is a Persisted B-tree, but a Sub B-tree one</li>
+ * <li>PERSISTED_MANAGEMENT : This is a Persisted B-tree used to manage the other B-trees</li>
  * </ul>
- * 
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public enum BTreeTypeEnum
 {
-    /** Pure in-memory BTree, not persisted on disk */
+    /** Pure in-memory B-tree, not persisted on disk */
     IN_MEMORY,
 
-    /** Persisted BTree */
+    /** Persisted B-tree */
     PERSISTED,
 
-    /** In-memory BTree but saved on disk */
+    /** Persisted sub B-tree */
+    PERSISTED_SUB,
+
+    /** Persisted Management B-tree */
+    PERSISTED_MANAGEMENT,
+
+    /** In-memory B-tree but saved on disk */
     BACKED_ON_DISK
 }

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java Mon Feb 10 15:35:18 2014
@@ -29,6 +29,7 @@ import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
 import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.directory.mavibot.btree.exception.InitializationException;
@@ -48,7 +49,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-/* No qualifier */class InMemoryBTree<K, V> extends AbstractBTree<K, V> implements Closeable
+/* No qualifier */class InMemoryBTree<K, V> extends AbstractBTree<K, V> implements TransactionManager, Closeable
 {
     /** The LoggerFactory used by this class */
     protected static final Logger LOG = LoggerFactory.getLogger( InMemoryBTree.class );
@@ -72,10 +73,20 @@ import org.slf4j.LoggerFactory;
     /** The associated journal. If null, this is an in-memory btree  */
     private File journal;
 
+    /** The directory where the journal will be stored */
     private File envDir;
 
+    /** The Journal channel */
     private FileChannel journalChannel = null;
 
+    /** The current transaction */
+    private WriteTransaction writeTransaction;
+
+    /** A lock to protect the creation of the transaction */
+    private ReentrantLock createTransaction = new ReentrantLock();
+
+    /** A flag set when we initiate an automatic transaction */
+    private AtomicBoolean automaticTransaction = new AtomicBoolean( true );
 
     /**
      * Creates a new BTree, with no initialization.
@@ -83,7 +94,6 @@ import org.slf4j.LoggerFactory;
     /* no qualifier */InMemoryBTree()
     {
         super();
-        btreeHeader = new BTreeHeader();
         setType( BTreeTypeEnum.IN_MEMORY );
     }
 
@@ -97,9 +107,9 @@ import org.slf4j.LoggerFactory;
     /* no qualifier */InMemoryBTree( InMemoryBTreeConfiguration<K, V> configuration )
     {
         super();
-        String name = configuration.getName();
+        String btreeName = configuration.getName();
 
-        if ( name == null )
+        if ( btreeName == null )
         {
             throw new IllegalArgumentException( "BTree name cannot be null" );
         }
@@ -111,29 +121,34 @@ import org.slf4j.LoggerFactory;
             envDir = new File( filePath );
         }
 
-        btreeHeader = new BTreeHeader();
-        btreeHeader.setName( name );
-        btreeHeader.setPageSize( configuration.getPageSize() );
-
-        keySerializer = configuration.getKeySerializer();
-        btreeHeader.setKeySerializerFQCN( keySerializer.getClass().getName() );
-
-        valueSerializer = configuration.getValueSerializer();
-        btreeHeader.setValueSerializerFQCN( valueSerializer.getClass().getName() );
+        // Store the configuration in the B-tree
+        setName( btreeName );
+        setPageSize( configuration.getPageSize() );
+        setKeySerializer( configuration.getKeySerializer() );
+        setValueSerializer( configuration.getValueSerializer() );
+        setAllowDuplicates( configuration.isAllowDuplicates() );
+        setType( configuration.getType() );
 
         readTimeOut = configuration.getReadTimeOut();
         writeBufferSize = configuration.getWriteBufferSize();
-        btreeHeader.setAllowDuplicates( configuration.isAllowDuplicates() );
-        setType( configuration.getType() );
 
         if ( keySerializer.getComparator() == null )
         {
             throw new IllegalArgumentException( "Comparator should not be null" );
         }
 
+        // Create the B-tree header
+        BTreeHeader<K, V> newBtreeHeader = new BTreeHeader<K, V>();
+
         // Create the first root page, with revision 0L. It will be empty
         // and increment the revision at the same time
-        rootPage = new InMemoryLeaf<K, V>( this );
+        newBtreeHeader.setBTreeOffset( 0L );
+        newBtreeHeader.setRevision( 0L );
+        newBtreeHeader.setNbElems( 0L );
+        newBtreeHeader.setRootPage( new InMemoryLeaf<K, V>( this ) );
+        newBtreeHeader.setRootPageOffset( 0L );
+
+        btreeRevisions.put( 0L,  newBtreeHeader );
 
         // Now, initialize the BTree
         try
@@ -152,7 +167,7 @@ import org.slf4j.LoggerFactory;
      *
      * @throws IOException If we get some exception while initializing the BTree
      */
-    public void init() throws IOException
+    private void init() throws IOException
     {
         // if not in-memory then default to persist mode instead of managed
         if ( envDir != null )
@@ -160,13 +175,14 @@ import org.slf4j.LoggerFactory;
             if ( !envDir.exists() )
             {
                 boolean created = envDir.mkdirs();
+
                 if ( !created )
                 {
                     throw new IllegalStateException( "Could not create the directory " + envDir + " for storing data" );
                 }
             }
 
-            this.file = new File( envDir, btreeHeader.getName() + DATA_SUFFIX );
+            this.file = new File( envDir, getName() + DATA_SUFFIX );
 
             this.journal = new File( envDir, file.getName() + JOURNAL_SUFFIX );
             setType( BTreeTypeEnum.BACKED_ON_DISK );
@@ -175,8 +191,6 @@ import org.slf4j.LoggerFactory;
         // Create the queue containing the pending read transactions
         readTransactions = new ConcurrentLinkedQueue<ReadTransaction<K, V>>();
 
-        writeLock = new ReentrantLock();
-
         // Check the files and create them if missing
         // Create the queue containing the modifications, if it's not a in-memory btree
         if ( getType() == BTreeTypeEnum.BACKED_ON_DISK )
@@ -202,6 +216,11 @@ import org.slf4j.LoggerFactory;
         else
         {
             setType( BTreeTypeEnum.IN_MEMORY );
+
+            // This is a new Btree, we have to store the BtreeHeader
+            BTreeHeader<K, V> btreeHeader = new BTreeHeader<K, V>();
+            btreeHeader.setRootPage( new InMemoryLeaf<K, V>( this ) );
+            storeRevision( btreeHeader );
         }
 
         // Initialize the txnManager thread
@@ -225,8 +244,6 @@ import org.slf4j.LoggerFactory;
             flush();
             journalChannel.close();
         }
-
-        rootPage = null;
     }
 
 
@@ -244,59 +261,78 @@ import org.slf4j.LoggerFactory;
      */
     protected Tuple<K, V> delete( K key, V value, long revision ) throws IOException
     {
-        writeLock.lock();
+        boolean inTransaction = beginTransaction( revision );
 
-        try
+        if ( revision == -1L )
         {
-            // If the key exists, the existing value will be replaced. We store it
-            // to return it to the caller.
-            Tuple<K, V> tuple = null;
+            revision = currentRevision.get() + 1;
+        }
+
+        BTreeHeader<K, V> oldBtreeHeader = getBtreeHeader();
+        BTreeHeader<K, V> newBtreeHeader = createNewBtreeHeader( oldBtreeHeader, revision );
+
+        // If the key exists, the existing value will be replaced. We store it
+        // to return it to the caller.
+        Tuple<K, V> tuple = null;
 
-            // Try to delete the entry starting from the root page. Here, the root
-            // page may be either a Node or a Leaf
-            DeleteResult<K, V> result = rootPage.delete( revision, key, value, null, -1 );
+        // Try to delete the entry starting from the root page. Here, the root
+        // page may be either a Node or a Leaf
+        DeleteResult<K, V> result = getRootPage().delete( key, value, revision );
 
-            if ( result instanceof NotPresentResult )
+        if ( result instanceof NotPresentResult )
+        {
+            // Key not found.
+            if ( !inTransaction )
             {
-                // Key not found.
-                return null;
+                commit();
             }
 
-            // Keep the oldRootPage so that we can later access it
-            Page<K, V> oldRootPage = rootPage;
+            return null;
+        }
 
-            if ( result instanceof RemoveResult )
-            {
-                // The element was found, and removed
-                RemoveResult<K, V> removeResult = ( RemoveResult<K, V> ) result;
+        // Keep the oldRootPage so that we can later access it
+        //Page<K, V> oldRootPage = rootPage;
 
-                Page<K, V> modifiedPage = removeResult.getModifiedPage();
+        if ( result instanceof RemoveResult )
+        {
+            // The element was found, and removed
+            RemoveResult<K, V> removeResult = ( RemoveResult<K, V> ) result;
 
-                // This is a new root
-                rootPage = modifiedPage;
-                tuple = removeResult.getRemovedElement();
-            }
+            Page<K, V> modifiedPage = removeResult.getModifiedPage();
 
-            if ( withJournal )
-            {
-                // Inject the modification into the modification queue
-                writeToJournal( new Deletion<K, V>( key ) );
-            }
+            // This is a new root
+            newBtreeHeader.setRootPage( modifiedPage );
+            tuple = removeResult.getRemovedElement();
+        }
 
-            // Decrease the number of elements in the current tree if the deletion is successful
-            if ( tuple != null )
-            {
-                btreeHeader.decrementNbElems();
-            }
+        if ( withJournal )
+        {
+            // Inject the modification into the modification queue
+            writeToJournal( new Deletion<K, V>( key ) );
+        }
 
-            // Return the value we have found if it was modified
-            return tuple;
+        // Decrease the number of elements in the current tree if the deletion is successful
+        if ( tuple != null )
+        {
+            newBtreeHeader.decrementNbElems();
         }
-        finally
+
+        // Return the value we have found if it was modified
+        if ( !inTransaction )
+        {
+            storeRevision( newBtreeHeader );
+            commit();
+        }
+
+        if ( oldBtreeHeader.getNbUsers() == 0 )
         {
-            // See above
-            writeLock.unlock();
+            synchronized ( btreeRevisions )
+            {
+                btreeRevisions.remove( oldBtreeHeader.getRevision() );
+            }
         }
+
+        return tuple;
     }
 
 
@@ -320,6 +356,18 @@ import org.slf4j.LoggerFactory;
             throw new IllegalArgumentException( "Key must not be null" );
         }
 
+        // We have to start a new transaction, which will be committed or rollbacked
+        // locally. This will duplicate the current BtreeHeader during this phase.
+        boolean inTransaction = beginTransaction( revision );
+
+        if ( revision == -1L )
+        {
+            revision = currentRevision.get() + 1;
+        }
+
+        BTreeHeader<K, V> oldBtreeHeader = getBtreeHeader();
+        BTreeHeader<K, V> newBtreeHeader = createNewBtreeHeader( oldBtreeHeader, revision );
+
         // If the key exists, the existing value will be replaced. We store it
         // to return it to the caller.
         V modifiedValue = null;
@@ -327,7 +375,7 @@ import org.slf4j.LoggerFactory;
         // Try to insert the new value in the tree at the right place,
         // starting from the root page. Here, the root page may be either
         // a Node or a Leaf
-        InsertResult<K, V> result = rootPage.insert( revision, key, value );
+        InsertResult<K, V> result = newBtreeHeader.getRootPage().insert( key, value, revision );
 
         if ( result instanceof ModifyResult )
         {
@@ -337,7 +385,7 @@ import org.slf4j.LoggerFactory;
 
             // The root has just been modified, we haven't split it
             // Get it and make it the current root page
-            rootPage = modifiedPage;
+            newBtreeHeader.setRootPage( modifiedPage );
 
             modifiedValue = modifyResult.getModifiedValue();
         }
@@ -350,12 +398,9 @@ import org.slf4j.LoggerFactory;
             K pivot = splitResult.getPivot();
             Page<K, V> leftPage = splitResult.getLeftPage();
             Page<K, V> rightPage = splitResult.getRightPage();
-            Page<K, V> newRootPage = null;
 
             // Create the new rootPage
-            newRootPage = new InMemoryNode<K, V>( this, revision, pivot, leftPage, rightPage );
-
-            rootPage = newRootPage;
+            newBtreeHeader.setRootPage( new InMemoryNode<K, V>( this, revision, pivot, leftPage, rightPage ) );
         }
 
         // Inject the modification into the modification queue
@@ -368,7 +413,27 @@ import org.slf4j.LoggerFactory;
         // and does not replace an element
         if ( modifiedValue == null )
         {
-            btreeHeader.incrementNbElems();
+            newBtreeHeader.incrementNbElems();
+        }
+
+        if ( !inTransaction )
+        {
+            storeRevision( newBtreeHeader );
+
+            commit();
+        }
+
+        if ( oldBtreeHeader.getNbUsers() == 0 )
+        {
+            synchronized ( btreeRevisions )
+            {
+                long oldRevision = oldBtreeHeader.getRevision();
+
+                if ( oldRevision < newBtreeHeader.getRevision() )
+                {
+                    btreeRevisions.remove( oldBtreeHeader.getRevision() );
+                }
+            }
         }
 
         // Return the value we have found if it was modified
@@ -456,7 +521,7 @@ import org.slf4j.LoggerFactory;
         }
 
         // Write the number of elements first
-        bb.putLong( btreeHeader.getNbElems() );
+        bb.putLong( getBtreeHeader().getNbElems() );
 
         while ( cursor.hasNext() )
         {
@@ -501,8 +566,6 @@ import org.slf4j.LoggerFactory;
      */
     private void applyJournal() throws IOException
     {
-        long revision = generateRevision();
-
         if ( !journal.exists() )
         {
             throw new IOException( "The journal does not exist" );
@@ -535,7 +598,7 @@ import org.slf4j.LoggerFactory;
                     //values.add( value );
 
                     // Inject the data in the tree. (to be replaced by a bulk load)
-                    insert( key, value, revision );
+                    insert( key, value, getBtreeHeader().getRevision() );
                 }
                 else
                 {
@@ -543,7 +606,7 @@ import org.slf4j.LoggerFactory;
                     K key = keySerializer.deserialize( bufferHandler );
 
                     // Remove the key from the tree
-                    delete( key, revision );
+                    delete( key, getBtreeHeader().getRevision() );
                 }
             }
         }
@@ -565,8 +628,6 @@ import org.slf4j.LoggerFactory;
      */
     public void load( File file ) throws IOException
     {
-        long revision = generateRevision();
-
         if ( !file.exists() )
         {
             throw new IOException( "The file does not exist" );
@@ -579,11 +640,6 @@ import org.slf4j.LoggerFactory;
         BufferHandler bufferHandler = new BufferHandler( channel, buffer );
 
         long nbElems = LongSerializer.deserialize( bufferHandler.read( 8 ) );
-        btreeHeader.setNbElems( nbElems );
-
-        // Prepare a list of keys and values read from the disk
-        //List<K> keys = new ArrayList<K>();
-        //List<V> values = new ArrayList<V>();
 
         // desactivate the journal while we load the file
         boolean isJournalActivated = withJournal;
@@ -596,15 +652,11 @@ import org.slf4j.LoggerFactory;
             // Read the key
             K key = keySerializer.deserialize( bufferHandler );
 
-            //keys.add( key );
-
             // Read the value
             V value = valueSerializer.deserialize( bufferHandler );
 
-            //values.add( value );
-
             // Inject the data in the tree. (to be replaced by a bulk load)
-            insert( key, value, revision );
+            insert( key, value, getBtreeHeader().getRevision() );
         }
 
         // Restore the withJournal value
@@ -616,7 +668,7 @@ import org.slf4j.LoggerFactory;
 
 
     /**
-     * Get the rootPzge associated to a give revision.
+     * Get the rootPage associated to a give revision.
      *
      * @param revision The revision we are looking for
      * @return The rootPage associated to this revision
@@ -626,7 +678,24 @@ import org.slf4j.LoggerFactory;
     public Page<K, V> getRootPage( long revision ) throws IOException, KeyNotFoundException
     {
         // Atm, the in-memory BTree does not support searches in many revisions
-        return rootPage;
+        return getBtreeHeader().getRootPage();
+    }
+
+
+    /**
+     * Get the current rootPage
+     *
+     * @return The rootPage
+     */
+    public Page<K, V> getRootPage()
+    {
+        return getBtreeHeader().getRootPage();
+    }
+
+
+    /* no qualifier */void setRootPage( Page<K, V> root )
+    {
+        getBtreeHeader().setRootPage( root );
     }
 
 
@@ -722,7 +791,53 @@ import org.slf4j.LoggerFactory;
      */
     public void beginTransaction()
     {
-        // Does nothing...
+        automaticTransaction.set( false );
+        beginTransaction( getRevision() + 1 );
+    }
+
+
+    /**
+     * Starts a transaction
+     */
+    private boolean beginTransaction( long revision )
+    {
+        createTransaction.lock();
+
+        if ( writeTransaction == null )
+        {
+            writeTransaction = new WriteTransaction();
+        }
+
+        if ( isTransactionStarted() && !automaticTransaction.get() )
+        {
+            createTransaction.unlock();
+
+            return true;
+        }
+
+        createTransaction.unlock();
+
+        writeTransaction.start();
+
+        return false;
+    }
+
+
+    /**
+     * Create a new B-tree header to be used for update operations
+     * @param revision The reclaimed revision
+     */
+    private BTreeHeader<K, V> createNewBtreeHeader( BTreeHeader<K, V> btreeHeader, long revision )
+    {
+        BTreeHeader<K, V> newBtreeHeader = new BTreeHeader<K, V>();
+
+        newBtreeHeader.setBTreeOffset( btreeHeader.getBTreeOffset() );
+        newBtreeHeader.setRevision( revision );
+        newBtreeHeader.setNbElems( btreeHeader.getNbElems() );
+        newBtreeHeader.setRootPage( btreeHeader.getRootPage() );
+        newBtreeHeader.setRootPageOffset( btreeHeader.getRootPageOffset() );
+
+        return newBtreeHeader;
     }
 
 
@@ -731,7 +846,41 @@ import org.slf4j.LoggerFactory;
      */
     public void commit()
     {
-        // Does nothing...
+        createTransaction.lock();
+
+        if ( writeTransaction == null )
+        {
+            throw new RuntimeException( "Cannot commit a transaction which hasn't been started");
+        }
+
+        createTransaction.unlock();
+
+        writeTransaction.commit();
+        automaticTransaction.set( true );
+    }
+
+
+    /**
+     * Tells if a transaction has been started or not
+     */
+    private boolean isTransactionStarted()
+    {
+        createTransaction.lock();
+
+        if ( writeTransaction == null )
+        {
+
+        }
+        boolean started = ( writeTransaction != null ) && ( writeTransaction.isStarted() );
+
+        if ( !started )
+        {
+
+        }
+
+        createTransaction.unlock();
+
+        return started;
     }
 
 
@@ -740,7 +889,16 @@ import org.slf4j.LoggerFactory;
      */
     public void rollback()
     {
-        // Does nothing...
+        createTransaction.lock();
+
+        if ( writeTransaction == null )
+        {
+            throw new RuntimeException( "Cannot rollback a transaction which hasn't been started");
+        }
+
+        createTransaction.unlock();
+
+        writeTransaction.rollback();
     }
 
 
@@ -760,16 +918,15 @@ import org.slf4j.LoggerFactory;
             case BACKED_ON_DISK:
                 sb.append( "Persistent " );
                 break;
-
         }
 
         sb.append( "BTree" );
-        sb.append( "[" ).append( btreeHeader.getName() ).append( "]" );
-        sb.append( "( pageSize:" ).append( btreeHeader.getPageSize() );
+        sb.append( "[" ).append( getName() ).append( "]" );
+        sb.append( "( pageSize:" ).append( getPageSize() );
 
-        if ( rootPage != null )
+        if ( getBtreeHeader().getRootPage() != null )
         {
-            sb.append( ", nbEntries:" ).append( btreeHeader.getNbElems() );
+            sb.append( ", nbEntries:" ).append( getBtreeHeader().getNbElems() );
         }
         else
         {
@@ -787,7 +944,7 @@ import org.slf4j.LoggerFactory;
             sb.append( keySerializer.getComparator().getClass().getSimpleName() );
         }
 
-        sb.append( ", DuplicatesAllowed: " ).append( btreeHeader.isAllowDuplicates() );
+        sb.append( ", DuplicatesAllowed: " ).append( isAllowDuplicates() );
 
         if ( getType() == BTreeTypeEnum.BACKED_ON_DISK )
         {
@@ -822,7 +979,7 @@ import org.slf4j.LoggerFactory;
         }
 
         sb.append( ") : \n" );
-        sb.append( rootPage.dumpPage( "" ) );
+        sb.append( getRootPage().dumpPage( "" ) );
 
         return sb.toString();
     }

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java Mon Feb 10 15:35:18 2014
@@ -72,7 +72,7 @@ import org.apache.directory.mavibot.btre
     /**
      * {@inheritDoc}
      */
-    public InsertResult<K, V> insert( long revision, K key, V value ) throws IOException
+    public InsertResult<K, V> insert( K key, V value, long revision ) throws IOException
     {
         // Find the key into this leaf
         int pos = findPos( key );
@@ -117,7 +117,7 @@ import org.apache.directory.mavibot.btre
      * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
-    public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
+    /* no qualifier */ DeleteResult<K, V> delete( K key, V value, long revision, Page<K, V> parent, int parentPos )
         throws IOException
     {
         // Check that the leaf is not empty

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryNode.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryNode.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryNode.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryNode.java Mon Feb 10 15:35:18 2014
@@ -28,7 +28,7 @@ import java.util.List;
 /**
  * A MVCC Node. It stores the keys and references to its children page. It does not
  * contain any value.
- * 
+ *
  * @param <K> The type for the Key
  * @param <V> The type for the stored value
  *
@@ -40,7 +40,7 @@ import java.util.List;
      * 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 btree the parent BTree
      * @param revision the Node revision
      * @param nbElems The number of elements in this Node
@@ -59,7 +59,7 @@ import java.util.List;
      * 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 btree the parent BTree
      * @param revision the Node revision
      * @param key The new key
@@ -89,7 +89,7 @@ import java.util.List;
     /**
      * {@inheritDoc}
      */
-    public InsertResult<K, V> insert( long revision, K key, V value ) throws IOException
+    public InsertResult<K, V> insert( K key, V value, long revision ) throws IOException
     {
         // Find the key into this leaf
         int pos = findPos( key );
@@ -105,7 +105,7 @@ import java.util.List;
         Page<K, V> child = children[pos].getValue();
 
         // and insert the <K, V> into this child
-        InsertResult<K, V> result = child.insert( revision, key, value );
+        InsertResult<K, V> result = child.insert( key, value, revision );
 
         // Ok, now, we have injected the <K, V> tuple down the tree. Let's check
         // the result to see if we have to split the current page
@@ -145,7 +145,7 @@ import java.util.List;
     /**
      * Modifies the current node after a remove has been done in one of its children.
      * The node won't be merged with another node.
-     * 
+     *
      * @param removeResult The result of a remove operation
      * @param index the position of the key, not transformed
      * @param pos The position of the key, as a positive value
@@ -188,7 +188,7 @@ import java.util.List;
     /**
      * Handles the removal of an element from the root page, when two of its children
      * have been merged.
-     * 
+     *
      * @param mergedResult The merge result
      * @param pos The position in the current root
      * @param found Tells if the removed key is present in the root page
@@ -223,7 +223,7 @@ import java.util.List;
      * Borrows an element from the right sibling, creating a new sibling with one
      * less element and creating a new page where the element to remove has been
      * deleted and the borrowed element added on the right.
-     * 
+     *
      * @param revision The new revision for all the pages
      * @param sibling The right sibling
      * @param pos The position of the element to remove
@@ -308,7 +308,7 @@ import java.util.List;
      * Borrows an element from the left sibling, creating a new sibling with one
      * less element and creating a new page where the element to remove has been
      * deleted and the borrowed element added on the left.
-     * 
+     *
      * @param revision The new revision for all the pages
      * @param sibling The left sibling
      * @param pos The position of the element to remove
@@ -392,7 +392,7 @@ import java.util.List;
     /**
      * We have to merge the node with its sibling, both have N/2 elements before the element
      * removal.
-     * 
+     *
      * @param revision The revision
      * @param mergedResult The result of the merge
      * @param sibling The Page we will merge the current page with
@@ -523,7 +523,7 @@ import java.util.List;
     /**
      * {@inheritDoc}
      */
-    public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
+    /* no qualifier */ DeleteResult<K, V> delete( K key, V value, long revision, Page<K, V> parent, int parentPos )
         throws IOException
     {
         // We first try to delete the element from the child it belongs to
@@ -538,12 +538,12 @@ import java.util.List;
         {
             index = -( pos + 1 );
             child = children[-pos].getValue();
-            deleteResult = child.delete( revision, key, value, this, -pos );
+            deleteResult = ((AbstractPage<K, V>)child).delete( key, value, revision, this, -pos );
         }
         else
         {
             child = children[pos].getValue();
-            deleteResult = child.delete( revision, key, value, this, pos );
+            deleteResult = ((AbstractPage<K, V>)child).delete( key, value, revision, this, pos );
         }
 
         // If the key is not present in the tree, we simply return
@@ -604,7 +604,7 @@ import java.util.List;
                 // We will remove one element from a page that will have less than N/2 elements,
                 // which will lead to some reorganization : either we can borrow an element from
                 // a sibling, or we will have to merge two pages
-                int siblingPos = selectSibling( ( InMemoryNode<K, V> ) parent, parentPos );
+                int siblingPos = selectSibling( parent, parentPos );
 
                 InMemoryNode<K, V> sibling = ( InMemoryNode<K, V> ) ( ( ( InMemoryNode<K, V> ) parent ).children[siblingPos]
                     .getValue() );
@@ -717,7 +717,7 @@ import java.util.List;
 
     /**
      * Remove the key at a given position.
-     * 
+     *
      * @param mergedResult The page we will remove a key from
      * @param revision The revision of the modified page
      * @param pos The position into the page of the element to remove
@@ -780,7 +780,7 @@ import java.util.List;
 
     /**
      * Set the value at a give position
-     * 
+     *
      * @param pos The position in the values array
      * @param value the value to inject
      */
@@ -794,7 +794,7 @@ import java.util.List;
      * This method is used when we have to replace a child in a page when we have
      * found the key in the tree (the value will be changed, so we have made
      * copies of the existing pages).
-     * 
+     *
      * @param revision The current revision
      * @param result The modified page
      * @param pos The position of the found key
@@ -825,7 +825,7 @@ import java.util.List;
     /**
      * Adds a new key into a copy of the current page at a given position. We return the
      * modified page. The new page will have one more key than the current page.
-     * 
+     *
      * @param copiedPages the list of copied pages
      * @param revision The revision of the modified page
      * @param key The key to insert
@@ -880,7 +880,7 @@ import java.util.List;
      * If the newly added element is in the middle, we will use it
      * as a pivot. Otherwise, we will use either the last element in the left page if the element is added
      * on the left, or the first element in the right page if it's added on the right.
-     * 
+     *
      * @param copiedPages the list of copied pages
      * @param revision The new revision for all the created pages
      * @param pivot The key that will be move up after the split
@@ -978,7 +978,7 @@ import java.util.List;
 
     /**
      * Copies the current page and all its keys, with a new revision.
-     * 
+     *
      * @param revision The new revision
      * @return The copied page
      */

Added: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryTransactionManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryTransactionManager.java?rev=1566659&view=auto
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryTransactionManager.java (added)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryTransactionManager.java Mon Feb 10 15:35:18 2014
@@ -0,0 +1,54 @@
+/*
+ *  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;
+
+/**
+ * An implementation of a TransactionManager for in-memory B-trees
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class InMemoryTransactionManager implements TransactionManager
+{
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void beginTransaction()
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void commit()
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void rollback()
+    {
+    }
+}

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionComparator.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionComparator.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionComparator.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionComparator.java Mon Feb 10 15:35:18 2014
@@ -30,6 +30,17 @@ import java.util.Comparator;
  */
 /* no qualifier*/class NameRevisionComparator implements Comparator<NameRevision>
 {
+    /** A static instance of a NameRevisionComparator */
+    public static final NameRevisionComparator INSTANCE = new NameRevisionComparator();
+
+    /**
+     * A private constructor of the NameRevisionComparator class
+     */
+    private NameRevisionComparator()
+    {
+    }
+
+
     /**
      * {@inheritDoc}
      */

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionSerializer.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionSerializer.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/NameRevisionSerializer.java Mon Feb 10 15:35:18 2014
@@ -41,12 +41,15 @@ import org.apache.directory.mavibot.btre
  */
 /* no qualifier*/class NameRevisionSerializer extends AbstractElementSerializer<NameRevision>
 {
+    /** A static instance of a NameRevisionSerializer */
+    /*No qualifier*/ final static NameRevisionSerializer INSTANCE = new NameRevisionSerializer();
+
     /**
      * Create a new instance of a NameRevisionSerializer
      */
-    /* no qualifier*/NameRevisionSerializer()
+    private NameRevisionSerializer()
     {
-        super( new NameRevisionComparator() );
+        super( NameRevisionComparator.INSTANCE );
     }
 
 

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/Page.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/Page.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/Page.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/Page.java Mon Feb 10 15:35:18 2014
@@ -31,7 +31,7 @@ import org.apache.directory.mavibot.btre
  * (containing keys and references to child pages).<br/>
  * A Page can be stored on disk. If so, we store the serialized value of this Page into
  * one or more {@link PageIO} (they will be linked)
- * 
+ *
  * @param <K> The type for the Key
  * @param <V> The type for the stored value
  *
@@ -56,22 +56,22 @@ import org.apache.directory.mavibot.btre
      * the Page is full, we split it and propagate the new pivot up into the tree</li>
      * </ul>
      * <p>
-     * 
-     * @param revision The new revision for the modified pages
+     *
      * @param key Inserted key
      * @param value Inserted value
+     * @param revision The new revision for the modified pages
      * @return Either a modified Page or an Overflow element if the Page was full
      * @throws IOException If we have an error while trying to access the page
      */
-    InsertResult<K, V> insert( long revision, K key, V value ) throws IOException;
+    InsertResult<K, V> insert( K key, V value, long revision ) throws IOException;
 
 
     /**
-     * Deletes the value from an entry associated with the given key in this page. We first find 
+     * Deletes the value from an entry associated with the given key in this page. We first find
      * the place were to remove the <K,V> into the tree, by recursively browsing the pages.
-     * If the value is present, it will be deleted first, later if there are no other values associated with 
+     * If the value is present, it will be deleted first, later if there are no other values associated with
      * this key(which can happen when duplicates are enabled), we will remove the key from the tree.
-     * 
+     *
      * @param revision The new revision for the modified pages
      * @param key The key to delete
      * @param value The value to delete (can be null)
@@ -80,15 +80,15 @@ import org.apache.directory.mavibot.btre
      * @return Either a modified Page if the key has been removed from the page, or a NotPresentResult.
      * @throws IOException If we have an error while trying to access the page
      */
-    DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos ) throws IOException;
+    DeleteResult<K, V> delete( K key, V value, long revision /*, Page<K, V> parent, int parentPos*/ ) throws IOException;
 
 
     /**
-     * Gets the value associated with the given key, if any. If we don't have 
+     * Gets the value associated with the given key, if any. If we don't have
      * one, this method will throw a KeyNotFoundException.<br/>
-     * Note that we may get back null if a null value has been associated 
+     * Note that we may get back null if a null value has been associated
      * with the key.
-     * 
+     *
      * @param key The key we are looking for
      * @return The associated value, which can be null
      * @throws KeyNotFoundException If no entry with the given key can be found
@@ -98,23 +98,23 @@ import org.apache.directory.mavibot.btre
 
 
     /**
-     * Gets the values associated with the given key, if any. If we don't have 
+     * Gets the values associated with the given key, if any. If we don't have
      * the key, this method will throw a KeyNotFoundException.<br/>
-     * Note that we may get back null if a null value has been associated 
+     * Note that we may get back null if a null value has been associated
      * with the key.
-     * 
+     *
      * @param key The key we are looking for
      * @return The associated value, which can be null
      * @throws KeyNotFoundException If no entry with the given key can be found
      * @throws IOException If we have an error while trying to access the page
-     * @throws IllegalArgumentException If duplicates are not enabled 
+     * @throws IllegalArgumentException If duplicates are not enabled
      */
     ValueCursor<V> getValues( K key ) throws KeyNotFoundException, IOException, IllegalArgumentException;
 
 
     /**
      * Checks if the page contains the given key with the given value.
-     * 
+     *
      * @param key The key we are looking for
      * @param value The value associated with the given key
      * @return true if the key and value are associated with each other, false otherwise
@@ -125,7 +125,7 @@ import org.apache.directory.mavibot.btre
     /**
      * Browses the tree, looking for the given key, and creates a Cursor on top
      * of the found result.
-     * 
+     *
      * @param key The key we are looking for.
      * @param transaction The started transaction for this operation
      * @param stack The stack of parents we go through to get to this page
@@ -138,7 +138,7 @@ import org.apache.directory.mavibot.btre
 
     /**
      * Browses the whole tree, and creates a Cursor on top of it.
-     * 
+     *
      * @param transaction The started transaction for this operation
      * @param stack The stack of parents we go through to get to this page
      * @return A Cursor to browse the next elements
@@ -156,7 +156,7 @@ import org.apache.directory.mavibot.btre
 
     /**
      * Returns the key at a given position
-     * 
+     *
      * @param pos The position of the key we want to retrieve
      * @return The key found at the given position
      */
@@ -166,7 +166,7 @@ import org.apache.directory.mavibot.btre
     /**
      * Finds the leftmost key in this page. If the page is a node, it will go
      * down in the leftmost children to recursively find the leftmost key.
-     * 
+     *
      * @return The leftmost key in the tree
      */
     K getLeftMostKey();
@@ -175,7 +175,7 @@ import org.apache.directory.mavibot.btre
     /**
      * Finds the rightmost key in this page. If the page is a node, it will go
      * down in the rightmost children to recursively find the rightmost key.
-     * 
+     *
      * @return The rightmost key in the tree
      */
     K getRightMostKey();
@@ -184,7 +184,7 @@ import org.apache.directory.mavibot.btre
     /**
      * Finds the leftmost element in this page. If the page is a node, it will go
      * down in the leftmost children to recursively find the leftmost element.
-     * 
+     *
      * @return The leftmost element in the tree
      * @throws IOException If we have an error while trying to access the page
      */
@@ -194,7 +194,7 @@ import org.apache.directory.mavibot.btre
     /**
      * Finds the rightmost element in this page. If the page is a node, it will go
      * down in the rightmost children to recursively find the rightmost element.
-     * 
+     *
      * @return The rightmost element in the tree
      * @throws IOException If we have an error while trying to access the page
      */
@@ -240,8 +240,8 @@ import org.apache.directory.mavibot.btre
      * <li>'h' will return -4</li>
      * <li>'i' will return 4</li>
      * </ul>
-     * 
-     * 
+     *
+     *
      * @param key The key to find
      * @return The position in the page.
      */
@@ -250,7 +250,7 @@ import org.apache.directory.mavibot.btre
 
     /**
      * Checks if the given key exists.
-     *  
+     *
      * @param key The key we are looking at
      * @return true if the key is present, false otherwise
      * @throws IOException If we have an error while trying to access the page

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java?rev=1566659&r1=1566658&r2=1566659&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java Mon Feb 10 15:35:18 2014
@@ -34,25 +34,25 @@ import org.apache.directory.mavibot.btre
  * Here is the logical structure of a PageIO :
  * <pre>
  * For a first page :
- * 
+ *
  * +----------+------+----------------------+
  * | nextPage | size | XXXXXXXXXXXXXXXXXXXX |
  * +----------+------+----------------------+
- * 
+ *
  * for any page but the first :
- * 
+ *
  * +----------+-----------------------------+
  * | nextPage | XXXXXXXXXXXXXXXXXXXXXXXXXXX |
  * +----------+-----------------------------+
- * 
+ *
  * for the last page :
  * +----------+-----------------------------+
  * |    -1    | XXXXXXXXXXXXXXXXXXXXXXXXXXX |
  * +----------+-----------------------------+
- * 
+ *
  * In any case, the page length is always PageSize.
  * </pre>
- *  
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 /* No qualifier*/class PageIO
@@ -70,7 +70,7 @@ import org.apache.directory.mavibot.btre
     private long offset;
 
 
-    /** 
+    /**
      * A default constructor for a PageIO
      */
     /* no qualifier */PageIO()
@@ -81,7 +81,7 @@ import org.apache.directory.mavibot.btre
     }
 
 
-    /** 
+    /**
      * A constructor for a PageIO when we know the offset of this page on disk
      */
     /* no qualifier */PageIO( long offset )
@@ -179,6 +179,45 @@ import org.apache.directory.mavibot.btre
     }
 
 
+    /* no qualifier */PageIO copy( PageIO copy )
+    {
+        // The data
+        if ( data.isDirect() )
+        {
+            copy.data = ByteBuffer.allocateDirect( data.capacity() );
+        }
+        else
+        {
+            copy.data = ByteBuffer.allocate( data.capacity() );
+        }
+
+        // Save the original buffer position and limit
+        int start = data.position();
+        int limit = data.limit();
+
+        // The data is extended to get all the bytes in it
+        data.position( 0 );
+        data.limit( data.capacity() );
+
+        // Copy the data
+        copy.data.put( data );
+
+        // Restore the original buffer to the initial position and limit
+        data.position( start );
+        data.limit( limit );
+
+        // Set those position and limit in the copied buffer
+        copy.data.position( start );
+        copy.data.limit( limit );
+
+        // The size
+        copy.size = size;
+
+        // The offset and next page pointers are not copied.
+        return copy;
+    }
+
+
     /**
      * @see Object#toString()
      */
@@ -186,7 +225,7 @@ import org.apache.directory.mavibot.btre
     {
         StringBuilder sb = new StringBuilder();
 
-        sb.append( "PageIO[offset:" ).append( offset );
+        sb.append( "PageIO[offset:" ).append( Long.toHexString( offset ) );
 
         if ( size != -1 )
         {