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.
- * + * 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.
+ * * All its methods are static. - * + * * @author Apache Directory Project * - * @param The BTree key type - * @param The BTree valye type + * @param The B-tree key type + * @param The B-tree value type */ public class BTreeFactory { @@ -44,7 +43,9 @@ public class BTreeFactory //-------------------------------------------------------------------------------------------- /** - * 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 BTree createPersistedBTree() { @@ -55,10 +56,11 @@ public class BTreeFactory /** - * 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 BTree createPersistedBTree( PersistedBTreeConfiguration configuration ) { @@ -69,14 +71,13 @@ public class BTreeFactory /** - * 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 BTree createPersistedBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer ) @@ -98,14 +99,14 @@ public class BTreeFactory /** - * 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 BTree createPersistedBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer, boolean allowDuplicates ) @@ -127,15 +128,15 @@ public class BTreeFactory /** - * 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 BTree createPersistedBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer, boolean allowDuplicates, int cacheSize ) @@ -157,14 +158,14 @@ public class BTreeFactory /** - * 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 BTree createPersistedBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer, int pageSize ) @@ -186,15 +187,15 @@ public class BTreeFactory /** - * 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 BTree createPersistedBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer, int pageSize, boolean allowDuplicates ) @@ -216,16 +217,16 @@ public class BTreeFactory /** - * 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 BTree createPersistedBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer, int pageSize, boolean allowDuplicates, int cacheSize ) @@ -247,10 +248,12 @@ public class BTreeFactory //-------------------------------------------------------------------------------------------- - // 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 BTree createInMemoryBTree() { @@ -261,10 +264,11 @@ public class BTreeFactory /** - * 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 BTree createInMemoryBTree( InMemoryBTreeConfiguration configuration ) { @@ -275,12 +279,13 @@ public class BTreeFactory /** - * 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 BTree createInMemoryBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer ) @@ -301,14 +306,14 @@ public class BTreeFactory /** - * 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 BTree createInMemoryBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer, boolean allowDuplicates ) @@ -329,14 +334,14 @@ public class BTreeFactory /** - * 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 BTree createInMemoryBTree( String name, ElementSerializer keySerializer, ElementSerializer valueSerializer, int pageSize ) @@ -357,14 +362,14 @@ public class BTreeFactory /** - * 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 BTree createInMemoryBTree( String name, String filePath, ElementSerializer keySerializer, @@ -387,19 +392,18 @@ public class BTreeFactory /** - * 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 BTree createInMemoryBTree( String name, String filePath, - ElementSerializer keySerializer, - ElementSerializer valueSerializer, int pageSize ) + ElementSerializer keySerializer, ElementSerializer valueSerializer, int pageSize ) { InMemoryBTreeConfiguration configuration = new InMemoryBTreeConfiguration(); @@ -418,16 +422,16 @@ public class BTreeFactory /** - * 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 BTree createInMemoryBTree( String name, String filePath, ElementSerializer keySerializer, @@ -453,12 +457,12 @@ public class BTreeFactory // 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 Page createLeaf( BTree btree, long revision, int nbElems ) @@ -475,9 +479,9 @@ public class BTreeFactory /** - * 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 //-------------------------------------------------------------------------------------------- /** * 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 /** * 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 /** * 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 void setPage( BTree btree, Page page, int pos, Page child ) { @@ -563,42 +570,48 @@ public class BTreeFactory //-------------------------------------------------------------------------------------------- - // 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 void setKeySerializer( BTree btree, String keySerializerFqcn ) - throws ClassNotFoundException, IllegalAccessException, InstantiationException + throws ClassNotFoundException, IllegalAccessException, InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException { Class keySerializer = Class.forName( keySerializerFqcn ); @SuppressWarnings("unchecked") - ElementSerializer instance = ( ElementSerializer ) keySerializer.newInstance(); + ElementSerializer instance = ( ElementSerializer ) 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 void setValueSerializer( BTree btree, String valueSerializerFqcn ) - throws ClassNotFoundException, IllegalAccessException, InstantiationException + throws ClassNotFoundException, IllegalAccessException, InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException { Class valueSerializer = Class.forName( valueSerializerFqcn ); @SuppressWarnings("unchecked") - ElementSerializer instance = ( ElementSerializer ) valueSerializer.newInstance(); + ElementSerializer instance = ( ElementSerializer ) valueSerializer.getDeclaredField( "INSTANCE" ).get( null ); btree.setValueSerializer( instance ); } @@ -606,8 +619,8 @@ public class BTreeFactory /** * 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 void setRootPage( BTree btree, Page root ) @@ -617,9 +630,9 @@ public class BTreeFactory /** - * 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 Page getRootPage( BTree btree ) @@ -629,9 +642,9 @@ public class BTreeFactory /** - * 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 void setNbElems( BTree btree, long nbElems ) @@ -641,9 +654,9 @@ public class BTreeFactory /** - * 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 void setRevision( BTree btree, long revision ) @@ -653,9 +666,9 @@ public class BTreeFactory /** - * 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 void setName( BTree btree, String name ) @@ -666,8 +679,8 @@ public class BTreeFactory /** * 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 void setPageSize( BTree btree, int pageSize ) @@ -681,8 +694,8 @@ public class BTreeFactory //-------------------------------------------------------------------------------------------- /** * 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 LinkedList> getPathToRightMostLeaf( BTree btree ) @@ -724,12 +737,12 @@ public class BTreeFactory //-------------------------------------------------------------------------------------------- - // 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 void setRootPageOffset( BTree btree, long rootPageOffset ) @@ -740,34 +753,15 @@ public class BTreeFactory } 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 void setNextBTreeOffset( BTree btree, long nextBTreeOffset ) - { - if ( btree instanceof PersistedBTree ) - { - ( ( PersistedBTree ) 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 void setRecordManager( BTree btree, RecordManager recordManager ) @@ -778,15 +772,15 @@ public class BTreeFactory } 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 } 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 LinkedList> getPathToLeftMostLeaf( BTree btree ) @@ -850,7 +844,7 @@ public class BTreeFactory } 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.
- * A BTree Header on disk contains the following elements : + * Store in memory the information associated with a B-tree.
+ * A B-tree Header on disk contains the following elements : *
  * +--------------------+-------------+
  * | revision           | 8 bytes     |
@@ -49,40 +50,26 @@ import java.util.concurrent.atomic.Atomi
  *
  * @author Apache Directory Project
  */
-/* No qualifier*/class BTreeHeader
+/* No qualifier*/class BTreeHeader
 {
     /** 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 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 getRootPage()
     {
-        this.pageSize = pageSize;
+        return rootPage;
     }
 
 
     /**
-     * @return the keySerializerFQCN
+     * @param rootPage the rootPage to set
      */
-    public String getKeySerializerFQCN()
+    /* no qualifier */ void setRootPage( Page 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 :
  * 
    - *
  • IN_MEMORY : the BTree will remain in memory, and won't be persisted on disk
  • - *
  • PERSISTENT : the BTree is in memory, but will be persisted on disk
  • - *
  • MANAGED : the BTree is managed by a RecordManager, and some pages may + *
  • IN_MEMORY : the B-tree will remain in memory, and won't be persisted on disk
  • + *
  • BACKED_ON_DISK : the B-tree is in memory, but will be persisted on disk
  • + *
  • PERSISTED : the B-tree is managed by a RecordManager, and some pages may * be swapped out from memory on demand
  • + *
  • PERSISTED_SUB : The B-tree is a Persisted B-tree, but a Sub B-tree one
  • + *
  • PERSISTED_MANAGEMENT : This is a Persisted B-tree used to manage the other B-trees
  • *
- * + * * @author Apache Directory Project */ 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 Apache Directory Project */ -/* No qualifier */class InMemoryBTree extends AbstractBTree implements Closeable +/* No qualifier */class InMemoryBTree extends AbstractBTree 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 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 newBtreeHeader = new BTreeHeader(); + // Create the first root page, with revision 0L. It will be empty // and increment the revision at the same time - rootPage = new InMemoryLeaf( this ); + newBtreeHeader.setBTreeOffset( 0L ); + newBtreeHeader.setRevision( 0L ); + newBtreeHeader.setNbElems( 0L ); + newBtreeHeader.setRootPage( new InMemoryLeaf( 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>(); - 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 btreeHeader = new BTreeHeader(); + btreeHeader.setRootPage( new InMemoryLeaf( 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 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 tuple = null; + revision = currentRevision.get() + 1; + } + + BTreeHeader oldBtreeHeader = getBtreeHeader(); + BTreeHeader newBtreeHeader = createNewBtreeHeader( oldBtreeHeader, revision ); + + // If the key exists, the existing value will be replaced. We store it + // to return it to the caller. + Tuple 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 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 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 oldRootPage = rootPage; + return null; + } - if ( result instanceof RemoveResult ) - { - // The element was found, and removed - RemoveResult removeResult = ( RemoveResult ) result; + // Keep the oldRootPage so that we can later access it + //Page oldRootPage = rootPage; - Page modifiedPage = removeResult.getModifiedPage(); + if ( result instanceof RemoveResult ) + { + // The element was found, and removed + RemoveResult removeResult = ( RemoveResult ) result; - // This is a new root - rootPage = modifiedPage; - tuple = removeResult.getRemovedElement(); - } + Page modifiedPage = removeResult.getModifiedPage(); - if ( withJournal ) - { - // Inject the modification into the modification queue - writeToJournal( new Deletion( 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( 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 oldBtreeHeader = getBtreeHeader(); + BTreeHeader 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 result = rootPage.insert( revision, key, value ); + InsertResult 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 leftPage = splitResult.getLeftPage(); Page rightPage = splitResult.getRightPage(); - Page newRootPage = null; // Create the new rootPage - newRootPage = new InMemoryNode( this, revision, pivot, leftPage, rightPage ); - - rootPage = newRootPage; + newBtreeHeader.setRootPage( new InMemoryNode( 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 keys = new ArrayList(); - //List values = new ArrayList(); // 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 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 getRootPage() + { + return getBtreeHeader().getRootPage(); + } + + + /* no qualifier */void setRootPage( Page 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 createNewBtreeHeader( BTreeHeader btreeHeader, long revision ) + { + BTreeHeader newBtreeHeader = new BTreeHeader(); + + 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 insert( long revision, K key, V value ) throws IOException + public InsertResult 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 delete( long revision, K key, V value, Page parent, int parentPos ) + /* no qualifier */ DeleteResult delete( K key, V value, long revision, Page 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 The type for the Key * @param 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 insert( long revision, K key, V value ) throws IOException + public InsertResult 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 child = children[pos].getValue(); // and insert the into this child - InsertResult result = child.insert( revision, key, value ); + InsertResult result = child.insert( key, value, revision ); // Ok, now, we have injected the 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 delete( long revision, K key, V value, Page parent, int parentPos ) + /* no qualifier */ DeleteResult delete( K key, V value, long revision, Page 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)child).delete( key, value, revision, this, -pos ); } else { child = children[pos].getValue(); - deleteResult = child.delete( revision, key, value, this, pos ); + deleteResult = ((AbstractPage)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 ) parent, parentPos ); + int siblingPos = selectSibling( parent, parentPos ); InMemoryNode sibling = ( InMemoryNode ) ( ( ( InMemoryNode ) 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 Apache Directory Project + */ +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 { + /** 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 { + /** 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).
* 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 The type for the Key * @param 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 * *

- * - * @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 insert( long revision, K key, V value ) throws IOException; + InsertResult 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 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 delete( long revision, K key, V value, Page parent, int parentPos ) throws IOException; + DeleteResult delete( K key, V value, long revision /*, Page 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.
- * 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.
- * 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 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 *

  • 'h' will return -4
  • *
  • 'i' will return 4
  • * - * - * + * + * * @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 : *
      * 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.
      * 
    - * + * * @author Apache Directory Project */ /* 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 ) {