directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1572181 - in /directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree: BTreeFactory.java BTreeHeader.java InMemoryBTree.java PersistedBTree.java RecordManager.java
Date Wed, 26 Feb 2014 18:19:22 GMT
Author: elecharny
Date: Wed Feb 26 18:19:22 2014
New Revision: 1572181

URL: http://svn.apache.org/r1572181
Log:
o Many changes in the RecordManager to make it possible to add new B-trees, and to insert values in them.
o The file layout has been changed. 
o The write transaction is now implemented
o revisions are created and kept on disk
o Still not possible to read back the file, and the CopiedPage btree is not updated

Modified:
    directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeFactory.java
    directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeHeader.java
    directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java
    directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java
    directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java

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=1572181&r1=1572180&r2=1572181&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 Wed Feb 26 18:19:22 2014
@@ -749,7 +749,7 @@ public class BTreeFactory<K, V>
     {
         if ( btree instanceof PersistedBTree )
         {
-            ( ( PersistedBTree<K, V> ) btree ).setRootPageOffset( rootPageOffset );
+            ( ( PersistedBTree<K, V> ) btree ).getBtreeHeader().setRootPageOffset( rootPageOffset );
         }
         else
         {

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=1572181&r1=1572180&r2=1572181&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 Wed Feb 26 18:19:22 2014
@@ -22,8 +22,6 @@ package org.apache.directory.mavibot.btr
 import java.util.concurrent.atomic.AtomicInteger;
 
 
-
-
 /**
  * Store in memory the information associated with a B-tree. <br>
  * A B-tree Header on disk contains the following elements :
@@ -35,22 +33,20 @@ import java.util.concurrent.atomic.Atomi
  * +--------------------+-------------+
  * | rootPageOffset     | 8 bytes     |
  * +--------------------+-------------+
- * | nextBtreeHeader    | 8 bytes     |
- * +--------------------+-------------+
- * | pageSize           | 4 bytes     |
- * +--------------------+-------------+
- * | name               | 4 bytes + N |
- * +--------------------+-------------+
- * | keySerializeFQCN   | 4 bytes + N |
- * +--------------------+-------------+
- * | valueSerializeFQCN | 4 bytes + N |
+ * | BtreeOffset        | 8 bytes     |
  * +--------------------+-------------+
  * </pre>
- * Each BtreeHeader will be written starting on a new page.
+ * Each B-tree Header will be written starting on a new page.
+ * In memory, a B-tree Header store a bit more of information :
+ * <li>
+ * <ul>rootPage : the associated rootPage in memory</lu>
+ * <ul>nbUsers : the number of readThreads using this revision</lu>
+ * <ul>offset : the offset of this B-tre header</lu>
+ * </li>
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-/* No qualifier*/class BTreeHeader<K, V>
+/* No qualifier*/class BTreeHeader<K, V> implements Cloneable
 {
     /** The current revision */
     private long revision = 0L;
@@ -61,16 +57,19 @@ import java.util.concurrent.atomic.Atomi
     /** The offset of the B-tree RootPage */
     private long rootPageOffset;
 
-    // Those are data which aren't serialized : they are in memory only */
-    /** The position in the file */
-    private long btreeOffset;
+    /** The position of the B-tree header in the file */
+    private long btreeHeaderOffset;
 
+    // Those are data which aren't serialized : they are in memory only */
     /** A Map containing the rootPage for this tree */
     private Page<K, V> rootPage;
 
     /** The number of users for this BtreeHeader */
     private AtomicInteger nbUsers = new AtomicInteger( 0 );
 
+    /** The B-tree this header is associated with */
+    private BTree<K, V> btree;
+
 
     /**
      * Creates a BTreeHeader instance
@@ -81,20 +80,61 @@ import java.util.concurrent.atomic.Atomi
 
 
     /**
-     * @return the btreeOffset
+     * @return the B-tree info Offset
+     */
+    public long getBTreeInfoOffset()
+    {
+        return ((PersistedBTree<K, V>)btree).getBtreeInfoOffset();
+    }
+
+
+    /**
+     * @return the B-tree header Offset
+     */
+    public long getBTreeHeaderOffset()
+    {
+        return btreeHeaderOffset;
+    }
+
+
+    public BTreeHeader<K, V> clone()
+    {
+        try
+        {
+            BTreeHeader<K, V> copy = (BTreeHeader<K, V>)super.clone();
+
+            return copy;
+        }
+        catch ( CloneNotSupportedException cnse )
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * Copy the current B-tre header and return the copy
+     * @return
      */
-    public long getBTreeOffset()
+    /* no qualifier */ BTreeHeader<K, V> copy()
     {
-        return btreeOffset;
+        BTreeHeader<K, V> copy = clone();
+
+        // Clear the fields that should not be copied
+        copy.rootPage = null;
+        copy.rootPageOffset = -1L;
+        copy.btreeHeaderOffset = -1L;
+
+        return copy;
     }
 
 
     /**
-     * @param btreeOffset the btreeOffset to set
+     * @param btreeOffset the B-tree header Offset to set
      */
-    /* no qualifier */void setBTreeOffset( long btreeOffset )
+    /* no qualifier */void setBTreeHeaderOffset( long btreeHeaderOffset )
     {
-        this.btreeOffset = btreeOffset;
+        this.btreeHeaderOffset = btreeHeaderOffset;
     }
 
 
@@ -216,6 +256,24 @@ import java.util.concurrent.atomic.Atomi
 
 
     /**
+     * @return the btree
+     */
+    /* no qualifier */ BTree<K, V> getBtree()
+    {
+        return btree;
+    }
+
+
+    /**
+     * @param btree the btree to set
+     */
+    /* no qualifier */ void setBtree( BTree<K, V> btree )
+    {
+        this.btree = btree;
+    }
+
+
+    /**
      * @see Object#toString()
      */
     public String toString()
@@ -223,9 +281,11 @@ import java.util.concurrent.atomic.Atomi
         StringBuilder sb = new StringBuilder();
 
         sb.append( "B-treeHeader " );
+        sb.append( ", offset[0x" ).append( Long.toHexString( btreeHeaderOffset ) ).append( "]" );
+        sb.append( ", name[" ).append( btree.getName() ).append( "]" );
         sb.append( ", revision[" ).append( revision ).append( "]" );
-        sb.append( ", btreeOffset[" ).append( btreeOffset ).append( "]" );
-        sb.append( ", rootPageOffset[" ).append( rootPageOffset ).append( "]" );
+        sb.append( ", btreeInfoOffset[0x" ).append( Long.toHexString( ((PersistedBTree<K, V>)btree).getBtreeInfoOffset() ) ).append( "]" );
+        sb.append( ", rootPageOffset[0x" ).append( Long.toHexString( rootPageOffset ) ).append( "]" );
         sb.append( ", nbElems[" ).append( nbElems ).append( "]" );
         sb.append( ", nbUsers[" ).append( nbUsers.get() ).append( "]" );
 

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=1572181&r1=1572180&r2=1572181&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 Wed Feb 26 18:19:22 2014
@@ -136,7 +136,7 @@ import org.slf4j.LoggerFactory;
 
         // Create the first root page, with revision 0L. It will be empty
         // and increment the revision at the same time
-        newBtreeHeader.setBTreeOffset( 0L );
+        newBtreeHeader.setBTreeHeaderOffset( 0L );
         newBtreeHeader.setRevision( 0L );
         newBtreeHeader.setNbElems( 0L );
         newBtreeHeader.setRootPage( new InMemoryLeaf<K, V>( this ) );
@@ -831,7 +831,7 @@ import org.slf4j.LoggerFactory;
     {
         BTreeHeader<K, V> newBtreeHeader = new BTreeHeader<K, V>();
 
-        newBtreeHeader.setBTreeOffset( btreeHeader.getBTreeOffset() );
+        newBtreeHeader.setBTreeHeaderOffset( btreeHeader.getBTreeHeaderOffset() );
         newBtreeHeader.setRevision( revision );
         newBtreeHeader.setNbElems( btreeHeader.getNbElems() );
         newBtreeHeader.setRootPage( btreeHeader.getRootPage() );

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java?rev=1572181&r1=1572180&r2=1572181&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java Wed Feb 26 18:19:22 2014
@@ -25,8 +25,6 @@ import java.io.IOException;
 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 net.sf.ehcache.Cache;
 import net.sf.ehcache.Status;
@@ -72,11 +70,8 @@ public class PersistedBTree<K, V> extend
     /*No qualifier*/static int valueThresholdUp = DEFAULT_VALUE_THRESHOLD_UP;
     /*No qualifier*/static int valueThresholdLow = DEFAULT_VALUE_THRESHOLD_LOW;
 
-    /** 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 );
+    /** The BtreeInfo offset */
+    private long btreeInfoOffset;
 
     /**
      * Creates a new BTree, with no initialization.
@@ -103,7 +98,6 @@ public class PersistedBTree<K, V> extend
             throw new IllegalArgumentException( "BTree name cannot be null" );
         }
 
-        BTreeHeader<K, V> btreeHeader = getBtreeHeader();
         setName( name );
         setPageSize( configuration.getPageSize() );
         setKeySerializer( configuration.getKeySerializer() );
@@ -122,9 +116,12 @@ public class PersistedBTree<K, V> extend
 
         // Create the first root page, with revision 0L. It will be empty
         // and increment the revision at the same time
-        // Create the first root page, with revision 0L. It will be empty
-        // and increment the revision at the same time
-        btreeHeader.setRootPage( new PersistedLeaf<K, V>( this ) );
+        Page<K, V> rootPage = new PersistedLeaf<K, V>( this );
+
+        // Create a B-tree header, and initialize it
+        BTreeHeader<K, V> btreeHeader = new BTreeHeader<K, V>();
+        btreeHeader.setRootPage( rootPage );
+        btreeHeader.setBtree( this );
 
         if ( btreeType == BTreeTypeEnum.PERSISTED_SUB )
         {
@@ -133,6 +130,9 @@ public class PersistedBTree<K, V> extend
             readTransactions = new ConcurrentLinkedQueue<ReadTransaction<K, V>>();
         }
 
+        // Add the B-tree header into the revisions
+        btreeRevisions.put( 0L, btreeHeader );
+
         // Now, initialize the BTree
         init();
     }
@@ -213,16 +213,16 @@ public class PersistedBTree<K, V> extend
      */
     /* No qualifier*/long getBtreeOffset()
     {
-        return getBtreeHeader().getBTreeOffset();
+        return getBtreeHeader().getBTreeInfoOffset();
     }
 
 
     /**
-     * @param btreeOffset the btreeOffset to set
+     * @param btreeOffset the B-tree header Offset to set
      */
-    /* No qualifier*/void setBtreeOffset( long btreeOffset )
+    /* No qualifier*/void setBtreeHeaderOffset( long btreeHeaderOffset )
     {
-        getBtreeHeader().setBTreeOffset( btreeOffset );
+        getBtreeHeader().setBTreeHeaderOffset( btreeHeaderOffset );
     }
 
 
@@ -236,15 +236,6 @@ public class PersistedBTree<K, V> extend
 
 
     /**
-     * @param rootPageOffset the rootPageOffset to set
-     */
-    /* No qualifier*/void setRootPageOffset( long rootPageOffset )
-    {
-        getBtreeHeader().setRootPageOffset( rootPageOffset );
-    }
-
-
-    /**
      * Gets the RecordManager for a managed BTree
      *
      * @return The recordManager if the B-tree is managed
@@ -280,12 +271,7 @@ public class PersistedBTree<K, V> extend
      */
     /* no qualifier */ Tuple<K, V> delete( K key, V value, long revision ) throws IOException
     {
-        boolean inTransaction = recordManager.isTransactionStarted();
-
-        if ( !inTransaction )
-        {
-            recordManager.beginTransaction();
-        }
+        recordManager.beginTransaction();
 
         // Try to delete the entry starting from the root page. Here, the root
         // page may be either a Node or a Leaf
@@ -295,10 +281,7 @@ public class PersistedBTree<K, V> extend
         if ( result instanceof NotPresentResult )
         {
             // We haven't found the element in the B-tree, just get out
-            if ( !inTransaction )
-            {
-                recordManager.commit();
-            }
+            recordManager.commit();
 
             return null;
         }
@@ -321,7 +304,7 @@ public class PersistedBTree<K, V> extend
 
             case PERSISTED_MANAGEMENT :
                 // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
-                getBtreeHeader().setBTreeOffset( newBtreeHeaderOffset );
+                getBtreeHeader().setBTreeHeaderOffset( newBtreeHeaderOffset );
 
                 break;
 
@@ -335,10 +318,7 @@ public class PersistedBTree<K, V> extend
 
         // If the B-tree is managed, we have to update the rootPage on disk
         // Update the RecordManager header
-        if ( !inTransaction )
-        {
-            recordManager.commit();
-        }
+        recordManager.commit();
 
         // Return the value we have found if it was modified
         return tuple;
@@ -380,7 +360,7 @@ public class PersistedBTree<K, V> extend
                 .getLastOffset() );
 
         // This is a new root
-        rootPage = modifiedPage;
+        //rootPage = modifiedPage;
 
         // Decrease the number of elements in the current tree
         getBtreeHeader().decrementNbElems();
@@ -416,55 +396,24 @@ public class PersistedBTree<K, V> extend
 
         // 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;
         }
 
-
-        if ( !inTransaction )
-        {
-            recordManager.beginTransaction();
-        }
+        recordManager.beginTransaction();
 
         // 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 = processInsert( key, value, revision );
 
-        // Update the B-tree header, creating a new BtreeHeader page now
-        long newBtreeHeaderOffset = recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) getBtreeHeader().getRootPage() ).getOffset() );
-
-        // Update the B-tree of B-trees with this new offset, if we are not already doing so
-        switch ( btreeType )
-        {
-            case PERSISTED :
-                // We have a new B-tree header to inject into the B-tree of btrees
-                recordManager.addInBtreeOfBtrees( getName(), revision, newBtreeHeaderOffset );
-                break;
-
-            case PERSISTED_MANAGEMENT :
-                // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
-                getBtreeHeader().setBTreeOffset( newBtreeHeaderOffset );
-
-                break;
-
-            default:
-                // Nothing to do for sub-btrees
-                break;
-        }
-
         // We can safely free the copied pages
-        recordManager.freePages( this, revision, result.getCopiedPages() );
+        //recordManager.freePages( this, revision, result.getCopiedPages() );
 
         // If the B-tree is managed, we have to update the rootPage on disk
         // Update the RecordManager header
-        if ( !inTransaction )
-        {
-            recordManager.commit();
-        }
+        commit();
 
         // Return the value we have found if it was modified
         return result;
@@ -476,7 +425,24 @@ public class PersistedBTree<K, V> extend
      */
     private InsertResult<K, V> processInsert( K key, V value, long revision ) throws IOException
     {
-        InsertResult<K, V> result = getBtreeHeader().getRootPage().insert( key, value, revision );
+        BTreeHeader<K, V> btreeHeader = getBtreeHeader();
+        InsertResult<K, V> result = btreeHeader.getRootPage().insert( key, value, revision );
+
+        // Create a new BTreeHeader
+        BTreeHeader<K, V> newBtreeHeader = btreeHeader.copy();
+
+        // Inject the old btreeHeader into the pages to be freed
+        // if we are inserting an element in a management BTree
+        if ( btreeType == BTreeTypeEnum.PERSISTED_MANAGEMENT )
+        {
+            PageIO[] pageIos = recordManager.readPageIOs( btreeHeader.getBTreeHeaderOffset(), -1L );
+
+            for ( PageIO pageIo : pageIos )
+            {
+                recordManager.freedPages.add( pageIo );
+            }
+        }
+
         Page<K, V> newRootPage;
 
         if ( result instanceof ModifyResult )
@@ -486,14 +452,12 @@ public class PersistedBTree<K, V> extend
             newRootPage = modifyResult.getModifiedPage();
 
             // Write the new root page on disk
-            // Note that we don't use the holder, the new root page will
-            // remain in memory.
-            writePage( newRootPage, revision );
+            PageHolder<K, V> newRootPageHolder = writePage( newRootPage, revision );
 
             // Increment the counter if we have inserted a new value
             if ( modifyResult.getModifiedValue() == null )
             {
-                getBtreeHeader().incrementNbElems();
+                newBtreeHeader.incrementNbElems();
             }
         }
         else
@@ -515,17 +479,46 @@ public class PersistedBTree<K, V> extend
             // Create the new rootPage
             newRootPage = new PersistedNode<K, V>( this, revision, pivot, holderLeft, holderRight );
 
-            // If the B-tree is managed, we now have to write the page on disk
-            // and to add this page to the list of modified pages
-            writePage( newRootPage, revision );
-
             // Always increment the counter : we have added a new value
-            getBtreeHeader().incrementNbElems();
+            newBtreeHeader.incrementNbElems();
         }
 
-        // Get the new root page and make it the current root page
-        rootPage = newRootPage;
+        // Update the new B-tree header
+        long newRootPageOffset = ((AbstractPage<K, V>)newRootPage).getOffset();
+        newBtreeHeader.setRootPage( newRootPage );
+        newBtreeHeader.setRootPageOffset( newRootPageOffset );
+        newBtreeHeader.setRevision( revision );
 
+        // Write down the data on disk
+        long newBtreeHeaderOffset = recordManager.writeBtreeHeader( this, newBtreeHeader );
+
+        // Update the B-tree of B-trees with this new offset, if we are not already doing so
+        switch ( btreeType )
+        {
+            case PERSISTED :
+                // We have a new B-tree header to inject into the B-tree of btrees
+                recordManager.addInBtreeOfBtrees( getName(), revision, newBtreeHeaderOffset );
+
+                // Store the new revision
+                storeRevision( newBtreeHeader );
+
+                break;
+
+            case PERSISTED_MANAGEMENT :
+                // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+                recordManager.updateRecordManagerHeader( newBtreeHeaderOffset, -1L );
+
+                // Store the new revision
+                storeRevision( newBtreeHeader );
+
+                break;
+
+            default:
+                // Nothing to do for sub-btrees
+                break;
+        }
+
+        // Get the new root page and make it the current root page
         return result;
     }
 
@@ -613,54 +606,37 @@ public class PersistedBTree<K, V> extend
 
 
     /**
-     * Starts a transaction
+     * @return the btreeInfoOffset
      */
-    public void beginTransaction()
+    public long getBtreeInfoOffset()
     {
-        automaticTransaction.set( false );
-        beginTransaction( getRevision() + 1 );
+        return btreeInfoOffset;
     }
 
 
     /**
-     * Starts a transaction
+     * @param btreeInfoOffset the btreeInfoOffset to set
      */
-    private boolean beginTransaction( long revision )
+    public void setBtreeInfoOffset( long btreeInfoOffset )
     {
-        createTransaction.lock();
-
-        if ( writeTransaction == null )
-        {
-            writeTransaction = new WriteTransaction();
-        }
-
-        if ( isTransactionStarted() && !automaticTransaction.get() )
-        {
-            createTransaction.unlock();
-
-            return true;
-        }
-
-        createTransaction.unlock();
-
-        writeTransaction.start();
-
-        return false;
+        this.btreeInfoOffset = btreeInfoOffset;
     }
 
 
     /**
-     * Tells if a transaction has been started or not
+     * Starts a transaction
      */
-    private boolean isTransactionStarted()
+    public void beginTransaction()
     {
-        createTransaction.lock();
-
-        boolean started = ( writeTransaction != null ) && ( writeTransaction.isStarted() );
+        beginTransaction( getRevision() + 1 );
+    }
 
-        createTransaction.unlock();
 
-        return started;
+    /**
+     * Starts a transaction
+     */
+    private void beginTransaction( long revision )
+    {
     }
 
 

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java?rev=1572181&r1=1572180&r2=1572181&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java Wed Feb 26 18:19:22 2014
@@ -33,6 +33,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
@@ -174,14 +175,14 @@ public class RecordManager
     /** The offset on the previous copied pages B-tree */
     private long previousCopiedPagesBtreeOffset = NO_PAGE;
 
-    /** The current transaction */
-    private WriteTransaction writeTransaction;
+    /** A lock to protect the transaction handling */
+    private Lock transactionLock = new ReentrantLock();
 
-    /** A lock to protect the creation of the transaction */
-    protected ReentrantLock createTransaction = new ReentrantLock();
+    /** A counter used to remember how many times a transaction has been started */
+    private int lockHeldCounter = 0;
 
     /** The list of PageIO that can be freed after a commit */
-    private List<PageIO> freedPages = new ArrayList<PageIO>();
+    List<PageIO> freedPages = new ArrayList<PageIO>();
 
     /** The list of PageIO that can be freed after a roolback */
     private List<PageIO> allocatedPages = new ArrayList<PageIO>();
@@ -342,13 +343,13 @@ public class RecordManager
         {
             manage( btreeOfBtrees, INTERNAL_BTREE );
 
-            currentBtreeOfBtreesOffset = ((PersistedBTree<NameRevision, Long>)btreeOfBtrees).getBtreeOffset();
+            currentBtreeOfBtreesOffset = ((PersistedBTree<NameRevision, Long>)btreeOfBtrees).getBtreeHeader().getBTreeHeaderOffset();
             updateRecordManagerHeader();
 
             // The FreePage B-tree
             manage( copiedPageBtree, INTERNAL_BTREE );
 
-            currentCopiedPagesBtreeOffset = ((PersistedBTree<RevisionName, long[]>)copiedPageBtree).getBtreeOffset();
+            currentCopiedPagesBtreeOffset = ((PersistedBTree<RevisionName, long[]>)copiedPageBtree).getBtreeHeader().getBTreeHeaderOffset();
             updateRecordManagerHeader();
         }
         catch ( BTreeAlreadyManagedException btame )
@@ -454,14 +455,14 @@ public class RecordManager
             PageIO[] bobPageIos = readPageIOs( currentBtreeOfBtreesOffset, Long.MAX_VALUE );
 
             btreeOfBtrees = BTreeFactory.<NameRevision, Long> createPersistedBTree();
-            ( ( PersistedBTree<NameRevision, Long> ) btreeOfBtrees ).setBtreeOffset( currentBtreeOfBtreesOffset );
+            ( ( PersistedBTree<NameRevision, Long> ) btreeOfBtrees ).setBtreeHeaderOffset( currentBtreeOfBtreesOffset );
             loadBtree( bobPageIos, btreeOfBtrees );
 
             // read the copied page B-tree
             PageIO[] copiedPagesPageIos = readPageIOs( currentCopiedPagesBtreeOffset, Long.MAX_VALUE );
 
             copiedPageBtree = BTreeFactory.<RevisionName, long[]> createPersistedBTree();
-            ( ( PersistedBTree<RevisionName, long[]> ) copiedPageBtree ).setBtreeOffset( currentCopiedPagesBtreeOffset );
+            ( ( PersistedBTree<RevisionName, long[]> ) copiedPageBtree ).setBtreeHeaderOffset( currentCopiedPagesBtreeOffset );
             loadBtree( copiedPagesPageIos, copiedPageBtree );
 
             // Now, read all the B-trees from the btree of btrees
@@ -510,7 +511,7 @@ public class RecordManager
                 PageIO[] btreePageIos = readPageIOs( btreeOffset, Long.MAX_VALUE );
 
                 BTree<?, ?> btree = BTreeFactory.<NameRevision, Long> createPersistedBTree();
-                ( ( PersistedBTree<NameRevision, Long> ) btree ).setBtreeOffset( btreeOffset );
+                ( ( PersistedBTree<NameRevision, Long> ) btree ).setBtreeHeaderOffset( btreeOffset );
                 loadBtree( btreePageIos, btree );
 
                 // Add the btree into the map of managed B-trees
@@ -528,31 +529,9 @@ public class RecordManager
      */
     /*No Qualifier*/void beginTransaction()
     {
-        createTransaction.lock();
+        transactionLock.lock();
 
-        if ( writeTransaction == null )
-        {
-            writeTransaction = new WriteTransaction();
-        }
-
-        createTransaction.unlock();
-
-        writeTransaction.start();
-    }
-
-
-    /**
-     * Tells if a transaction has been started or not
-     */
-    /*No Qualifier*/boolean isTransactionStarted()
-    {
-        createTransaction.lock();
-
-        boolean started = ( writeTransaction != null ) && ( writeTransaction.isStarted() );
-
-        createTransaction.unlock();
-
-        return started;
+        lockHeldCounter++;
     }
 
 
@@ -561,38 +540,37 @@ public class RecordManager
      */
     public void commit()
     {
-        createTransaction.lock();
+        lockHeldCounter--;
 
-        if ( writeTransaction == null )
+        if ( lockHeldCounter == 0 )
         {
-            throw new RuntimeException( "Cannot commit a transaction which hasn't been started");
-        }
-
-        createTransaction.unlock();
-
-        updateRecordManagerHeader();
+            // We are done with the transaction
+            // First update the RMHeader to be sure that we have a way to restore from a crash
+            updateRecordManagerHeader();
 
-        // We can now free pages
-        for ( PageIO pageIo : freedPages )
-        {
-            try
+            // We can now free pages
+            for ( PageIO pageIo : freedPages )
             {
-                free( pageIo );
-            }
-            catch ( IOException ioe )
-            {
-                throw new RecordManagerException( ioe.getMessage() );
+                try
+                {
+                    free( pageIo );
+                }
+                catch ( IOException ioe )
+                {
+                    throw new RecordManagerException( ioe.getMessage() );
+                }
             }
-        }
 
-        // Release the allocated and freed pages list
-        freedPages.clear();
-        allocatedPages.clear();
+            // Release the allocated and freed pages list
+            freedPages.clear();
+            allocatedPages.clear();
 
-        // And update the RMHeader again
-        updateRecordManagerHeader();
+            // And update the RMHeader again, removing the old references to BOB and CPB b-tree headers
+            // here, we have to erase the old references to keep only the new ones.
+            updateRecordManagerHeader();
+        }
 
-        writeTransaction.commit();
+        transactionLock.unlock();
     }
 
 
@@ -601,36 +579,32 @@ public class RecordManager
      */
     public void rollback()
     {
-        createTransaction.lock();
+        lockHeldCounter--;
 
-        if ( writeTransaction == null )
+        if ( lockHeldCounter == 0 )
         {
-            throw new RuntimeException( "Cannot rollback a transaction which hasn't been started");
-        }
-
-        createTransaction.unlock();
-
-        // We can now free allocated pages
-        for ( PageIO pageIo : allocatedPages )
-        {
-            try
-            {
-                free( pageIo );
-            }
-            catch ( IOException ioe )
+            // We can now free allocated pages, this is the end of the transaction
+            for ( PageIO pageIo : allocatedPages )
             {
-                throw new RecordManagerException( ioe.getMessage() );
+                try
+                {
+                    free( pageIo );
+                }
+                catch ( IOException ioe )
+                {
+                    throw new RecordManagerException( ioe.getMessage() );
+                }
             }
-        }
 
-        // Release the allocated and freed pages list
-        freedPages.clear();
-        allocatedPages.clear();
+            // Release the allocated and freed pages list
+            freedPages.clear();
+            allocatedPages.clear();
 
-        // And update the RMHeader
-        updateRecordManagerHeader();
+            // And update the RMHeader
+            updateRecordManagerHeader();
+        }
 
-        writeTransaction.rollback();
+        transactionLock.unlock();
     }
 
 
@@ -706,6 +680,7 @@ public class RecordManager
 
     /**
      * Read a B-tree from the disk. The meta-data are at the given position in the list of pages.
+     * We load a B-tree in two steps : first, we load the B-tree header, then the common informations
      *
      * @param pageIos The list of pages containing the meta-data
      * @param btree The B-tree we have to initialize
@@ -721,6 +696,7 @@ public class RecordManager
     {
         long dataPos = 0L;
 
+        // Process teh B-tree header
         // The B-tree current revision
         long revision = readLong( pageIos, dataPos );
         BTreeFactory.setRevision( btree, revision );
@@ -736,19 +712,26 @@ public class RecordManager
         BTreeFactory.setRootPageOffset( btree, rootPageOffset );
         dataPos += LONG_SIZE;
 
+        // The B-tree information offset
+        long btreeInfoOffset = readLong( pageIos, dataPos );
+
+        // Now, process the common informations
+        PageIO[] infoPageIos = readPageIOs( btreeInfoOffset, Long.MAX_VALUE );
+        dataPos = 0L;
+
         // The B-tree page size
-        int btreePageSize = readInt( pageIos, dataPos );
+        int btreePageSize = readInt( infoPageIos, dataPos );
         BTreeFactory.setPageSize( btree, btreePageSize );
         dataPos += INT_SIZE;
 
         // The tree name
-        ByteBuffer btreeNameBytes = readBytes( pageIos, dataPos );
+        ByteBuffer btreeNameBytes = readBytes( infoPageIos, dataPos );
         dataPos += INT_SIZE + btreeNameBytes.limit();
         String btreeName = Strings.utf8ToString( btreeNameBytes );
         BTreeFactory.setName( btree, btreeName );
 
         // The keySerializer FQCN
-        ByteBuffer keySerializerBytes = readBytes( pageIos, dataPos );
+        ByteBuffer keySerializerBytes = readBytes( infoPageIos, dataPos );
         dataPos += INT_SIZE + keySerializerBytes.limit();
 
         String keySerializerFqcn = "";
@@ -761,7 +744,7 @@ public class RecordManager
         BTreeFactory.setKeySerializer( btree, keySerializerFqcn );
 
         // The valueSerialier FQCN
-        ByteBuffer valueSerializerBytes = readBytes( pageIos, dataPos );
+        ByteBuffer valueSerializerBytes = readBytes( infoPageIos, dataPos );
 
         String valueSerializerFqcn = "";
         dataPos += INT_SIZE + valueSerializerBytes.limit();
@@ -774,12 +757,12 @@ public class RecordManager
         BTreeFactory.setValueSerializer( btree, valueSerializerFqcn );
 
         // The B-tree allowDuplicates flag
-        int allowDuplicates = readInt( pageIos, dataPos );
+        int allowDuplicates = readInt( infoPageIos, dataPos );
         ( ( PersistedBTree<K, V> ) btree ).setAllowDuplicates( allowDuplicates != 0 );
         dataPos += INT_SIZE;
 
         // Now, init the B-tree
-        btree.init();
+        //btree.init();
 
         ( ( PersistedBTree<K, V> ) btree ).setRecordManager( this );
 
@@ -1228,19 +1211,11 @@ public class RecordManager
      */
     public synchronized <K, V> void manage( BTree<K, V> btree ) throws BTreeAlreadyManagedException, IOException
     {
-        boolean inTransaction = isTransactionStarted();
-
-        if ( !inTransaction )
-        {
-            beginTransaction();
-        }
+        beginTransaction();
 
         manage( ( BTree<Object, Object> ) btree, NORMAL_BTREE );
 
-        if ( !inTransaction )
-        {
-            commit();
-        }
+        commit();
     }
 
 
@@ -1270,7 +1245,28 @@ public class RecordManager
             throw new BTreeAlreadyManagedException( name );
         }
 
-        long btreeOffset = writeBtreeHeader( btree );
+        // Now, write the B-tree informations
+        long btreeInfoOffset = writeBtreeInfo( btree );
+        BTreeHeader<K, V> btreeHeader = ((AbstractBTree<K,V>)btree).getBtreeHeader();
+        ((PersistedBTree<K, V>)btree).setBtreeInfoOffset( btreeInfoOffset );
+
+        // Serialize the B-tree root page
+        Page<K, V> rootPage = btreeHeader.getRootPage();
+
+        PageIO[] rootPageIos = serializePage( btree, btreeHeader.getRevision(), rootPage );
+
+        // Get the reference on the first page
+        long rootPageOffset =  rootPageIos[0].getOffset();
+
+        // Store the rootPageOffset into the Btree header and into the rootPage
+        btreeHeader.setRootPageOffset( rootPageOffset );
+        ( ( PersistedLeaf<K, V> ) rootPage ).setOffset( rootPageOffset );
+
+        LOG.debug( "Flushing the newly managed '{}' btree rootpage", btree.getName() );
+        flushPages( rootPageIos );
+
+        // And the B-tree header
+        long btreeHeaderOffset = writeBtreeHeader( btree, btreeHeader );
 
         // Now, if this is a new B-tree, add it to the B-tree of B-trees
         if ( treeType != INTERNAL_BTREE )
@@ -1285,7 +1281,7 @@ public class RecordManager
             NameRevision nameRevision = new NameRevision( name, 0L );
 
             // Inject it into the B-tree of B-tree
-            btreeOfBtrees.insert( nameRevision, btreeOffset );
+            btreeOfBtrees.insert( nameRevision, btreeHeaderOffset );
         }
 
         if ( LOG_CHECK.isDebugEnabled() )
@@ -1649,11 +1645,45 @@ public class RecordManager
 
         RECORD_MANAGER_HEADER_BUFFER.clear();
 
+        // Reset the old versions
+        previousBtreeOfBtreesOffset = -1L;
+        previousCopiedPagesBtreeOffset = -1L;
+
         nbUpdateRMHeader.incrementAndGet();
     }
 
 
     /**
+     * Update the RecordManager header, injecting the following data :
+     *
+     * <pre>
+     * +---------------------+
+     * | PageSize            | 4 bytes : The size of a physical page (default to 4096)
+     * +---------------------+
+     * | NbTree              | 4 bytes : The number of managed B-trees (at least 1)
+     * +---------------------+
+     * | FirstFree           | 8 bytes : The offset of the first free page
+     * +---------------------+
+     * | current BoB offset  | 8 bytes : The offset of the current B-tree of B-trees
+     * +---------------------+
+     * | previous BoB offset | 8 bytes : The offset of the previous B-tree of B-trees
+     * +---------------------+
+     * | current CP offset   | 8 bytes : The offset of the current CopiedPages B-tree
+     * +---------------------+
+     * | previous CP offset  | 8 bytes : The offset of the previous CopiedPages B-tree
+     * +---------------------+
+     * </pre>
+     */
+    public void updateRecordManagerHeader( long newBtreeOfBtreeOffset, long newCopiedPageBtreeOffset )
+    {
+        previousBtreeOfBtreesOffset = currentBtreeOfBtreesOffset;
+        currentBtreeOfBtreesOffset = newBtreeOfBtreeOffset;
+        previousCopiedPagesBtreeOffset = currentCopiedPagesBtreeOffset;
+        currentCopiedPagesBtreeOffset = newCopiedPageBtreeOffset;
+    }
+
+
+    /**
      * Inject an int into a byte[] at a given position.
      */
     private int writeData( byte[] buffer, int position, int value )
@@ -1701,7 +1731,7 @@ public class RecordManager
         btreeOfBtrees.insert( nameRevision, btreeHeaderOffset );
 
         // Update the B-tree of B-trees
-        currentBtreeOfBtreesOffset = ((PersistedBTree<NameRevision, Long>)btreeOfBtrees).getBtreeOffset();
+        currentBtreeOfBtreesOffset = ((AbstractBTree<K, V>)btreeOfBtrees).getBtreeHeader().getBTreeHeaderOffset();
     }
 
 
@@ -1726,6 +1756,63 @@ public class RecordManager
      * +------------+
      * | rootPage   | The root page offset
      * +------------+
+     * | BtreeInfo  | The B-tree info offset
+     * +------------+
+     * </pre>
+     * @param btree The B-tree which header has to be written
+     * @param btreeInfoOffset The offset of the B-tree informations
+     * @return The B-tree header offset
+     * @throws IOException If we weren't able to write the B-tree header
+     */
+    /* no qualifier */ <K, V> long writeBtreeHeader( BTree<K, V> btree, BTreeHeader<K, V> btreeHeader ) throws IOException
+    {
+        int bufferSize =
+            LONG_SIZE +                     // The revision
+            LONG_SIZE +                     // the number of element
+            LONG_SIZE +                     // The root page offset
+            LONG_SIZE;                      // The B-tree info page offset
+
+        // Get the pageIOs we need to store the data. We may need more than one.
+        PageIO[] btreeHeaderPageIos = getFreePageIOs( bufferSize );
+
+        // Store the B-tree header Offset into the B-tree
+        long btreeHeaderOffset = btreeHeaderPageIos[0].getOffset();
+
+        // Now store the B-tree data in the pages :
+        // - the B-tree revision
+        // - the B-tree number of elements
+        // - the B-tree root page offset
+        // - the B-tree info page offset
+        // Starts at 0
+        long position = 0L;
+
+        // The B-tree current revision
+        position = store( position, btreeHeader.getRevision(), btreeHeaderPageIos );
+
+        // The nb elems in the tree
+        position = store( position, btreeHeader.getNbElems(), btreeHeaderPageIos );
+
+
+        // Now, we can inject the B-tree rootPage offset into the B-tree header
+        position = store( position, btreeHeader.getRootPageOffset(), btreeHeaderPageIos );
+
+        // The B-tree info page offset
+        position = store( position, ((PersistedBTree<K, V>)btree).getBtreeInfoOffset(), btreeHeaderPageIos );
+
+        // And flush the pages to disk now
+        LOG.debug( "Flushing the newly managed '{}' btree header", btree.getName() );
+        flushPages( btreeHeaderPageIos );
+
+        btreeHeader.setBTreeHeaderOffset( btreeHeaderOffset );
+
+        return btreeHeaderOffset;
+    }
+
+
+    /**
+     * Write the B-tree informations on disk. We will write the following informations :
+     * <pre>
+     * +------------+
      * | pageSize   | The B-tree page size (ie, the number of elements per page max)
      * +------------+
      * | nameSize   | The B-tree name size
@@ -1747,7 +1834,7 @@ public class RecordManager
      * @return The B-tree header offset
      * @throws IOException If we weren't able to write the B-tree header
      */
-    private <K, V> long writeBtreeHeader( BTree<K, V> btree ) throws IOException
+    private <K, V> long writeBtreeInfo( BTree<K, V> btree ) throws IOException
     {
         // We will add the newly managed B-tree at the end of the header.
         byte[] btreeNameBytes = Strings.getBytesUtf8( btree.getName() );
@@ -1755,9 +1842,6 @@ public class RecordManager
         byte[] valueSerializerBytes = Strings.getBytesUtf8( btree.getValueSerializerFQCN() );
 
         int bufferSize =
-            LONG_SIZE +                     // The revision
-            LONG_SIZE +                     // the number of element
-            LONG_SIZE +                     // The root page offset
             INT_SIZE +                      // The page size
             INT_SIZE +                      // The name size
             btreeNameBytes.length +         // The name
@@ -1770,14 +1854,10 @@ public class RecordManager
         // Get the pageIOs we need to store the data. We may need more than one.
         PageIO[] btreeHeaderPageIos = getFreePageIOs( bufferSize );
 
-        // Store the B-tree header Offset into the B-tree
-        long btreeOffset = btreeHeaderPageIos[0].getOffset();
-        ( ( PersistedBTree<K, V> ) btree ).setBtreeOffset( btreeOffset );
+        // Keep the B-tree header Offset into the B-tree
+        long btreeInfoOffset = btreeHeaderPageIos[0].getOffset();
 
-        // Now store the B-tree data in the pages :
-        // - the B-tree revision
-        // - the B-tree number of elements
-        // - the B-tree root page offset
+        // Now store the B-tree information data in the pages :
         // - the B-tree page size
         // - the B-tree name
         // - the keySerializer FQCN
@@ -1786,25 +1866,6 @@ public class RecordManager
         // Starts at 0
         long position = 0L;
 
-        // The B-tree current revision
-        position = store( position, btree.getRevision(), btreeHeaderPageIos );
-
-        // The nb elems in the tree
-        position = store( position, btree.getNbElems(), btreeHeaderPageIos );
-
-        // Serialize the B-tree root page
-        Page<K, V> rootPage = BTreeFactory.getRootPage( btree );
-
-        PageIO[] rootPageIos = serializePage( btree, btree.getRevision(), rootPage );
-
-        // Get the reference on the first page
-        PageIO rootPageIo = rootPageIos[0];
-
-        // Now, we can inject the B-tree rootPage offset into the B-tree header
-        position = store( position, rootPageIo.getOffset(), btreeHeaderPageIos );
-        ( ( PersistedBTree<K, V> ) btree ).setRootPageOffset( rootPageIo.getOffset() );
-        ( ( PersistedLeaf<K, V> ) rootPage ).setOffset( rootPageIo.getOffset() );
-
         // The B-tree page size
         position = store( position, btree.getPageSize(), btreeHeaderPageIos );
 
@@ -1824,10 +1885,7 @@ public class RecordManager
         LOG.debug( "Flushing the newly managed '{}' btree header", btree.getName() );
         flushPages( btreeHeaderPageIos );
 
-        LOG.debug( "Flushing the newly managed '{}' btree rootpage", btree.getName() );
-        flushPages( rootPageIos );
-
-        return btreeOffset;
+        return btreeInfoOffset;
     }
 
 
@@ -1843,16 +1901,16 @@ public class RecordManager
      * <br/>
      * As a result, a new version of the BtreHeader will be created, which will replace the previous
      * B-tree header
-     * @param btree TheB-treeto update
-     * @param rootPageOffset The offset of the modified rootPage
+     * @param btree TheB-tree to update
+     * @param btreeHeaderOffset The offset of the modified btree header
      * @return The offset of the new B-tree Header
      * @throws IOException If we weren't able to write the file on disk
      * @throws EndOfFileExceededException If we tried to write after the end of the file
      */
-    /* no qualifier */ <K, V> long updateBtreeHeader( BTree<K, V> btree, long rootPageOffset )
+    /* no qualifier */ <K, V> long updateBtreeHeader( BTree<K, V> btree, long btreeHeaderOffset )
         throws EndOfFileExceededException, IOException
     {
-        return updateBtreeHeader( btree, rootPageOffset, false );
+        return updateBtreeHeader( btree, btreeHeaderOffset, false );
     }
 
 
@@ -1869,16 +1927,16 @@ public class RecordManager
      * <br/>
      * As a result, we new version of the BtreHeader will be created
      * @param btree The B-tree to update
-     * @param rootPageOffset The offset of the modified rootPage
+     * @param btreeHeaderOffset The offset of the modified btree header
      * @return The offset of the new B-tree Header if it has changed (ie, when the onPlace flag is set to true)
      * @throws IOException
      * @throws EndOfFileExceededException
      */
-    /* no qualifier */ <K, V> void updateBtreeHeaderOnPlace( BTree<K, V> btree, long rootPageOffset )
+    /* no qualifier */ <K, V> void updateBtreeHeaderOnPlace( BTree<K, V> btree, long btreeHeaderOffset )
         throws EndOfFileExceededException,
         IOException
     {
-        updateBtreeHeader( btree, rootPageOffset, true );
+        updateBtreeHeader( btree, btreeHeaderOffset, true );
     }
 
 
@@ -1904,7 +1962,7 @@ public class RecordManager
      * @throws EndOfFileExceededException If we tried to write after the end of the file
      * @throws IOException If tehre were some error while writing the data on disk
      */
-    private <K, V> long updateBtreeHeader( BTree<K, V> btree, long rootPageOffset, boolean onPlace )
+    private <K, V> long updateBtreeHeader( BTree<K, V> btree, long btreeHeaderOffset, boolean onPlace )
         throws EndOfFileExceededException, IOException
     {
         // Read the pageIOs associated with this B-tree
@@ -1924,14 +1982,14 @@ public class RecordManager
 
             position = store( position, btree.getRevision(), pageIos );
             position = store( position, btree.getNbElems(), pageIos );
-            position = store( position, rootPageOffset, pageIos );
+            position = store( position, btreeHeaderOffset, pageIos );
 
             // Write the pages on disk
             if ( LOG.isDebugEnabled() )
             {
                 LOG.debug( "-----> Flushing the '{}' B-treeHeader", btree.getName() );
-                LOG.debug( "  revision : " + btree.getRevision() + ", NbElems : " + btree.getNbElems() + ", root offset : "
-                    + rootPageOffset );
+                LOG.debug( "  revision : " + btree.getRevision() + ", NbElems : " + btree.getNbElems() + ", btreeHeader offset : 0x"
+                    + Long.toHexString( btreeHeaderOffset ) );
             }
 
             // Get new place on disk to store the modified BTreeHeader if it's not onPlace
@@ -1971,13 +2029,13 @@ public class RecordManager
                 pos++;
             }
 
-            // store the new rootPage offset
-            // Now, update the revision
+            // store the new btree header offset
+            // and update the revision
             long position = 0;
 
             position = store( position, btree.getRevision(), newPageIOs );
             position = store( position, btree.getNbElems(), newPageIOs );
-            position = store( position, rootPageOffset, newPageIOs );
+            position = store( position, btreeHeaderOffset, newPageIOs );
 
             // Get new place on disk to store the modified BTreeHeader if it's not onPlace
             // Flush the new B-treeHeader on disk
@@ -2618,14 +2676,7 @@ public class RecordManager
      */
     public void close() throws IOException
     {
-        if ( isTransactionStarted() )
-        {
-            // Wait for the transaction to finish
-        }
-        else
-        {
-            beginTransaction();
-        }
+        beginTransaction();
 
         // Close all the managed B-trees
         for ( BTree<Object, Object> tree : managedBtrees.values() )
@@ -2644,6 +2695,8 @@ public class RecordManager
 
         // And close the channel
         fileChannel.close();
+
+        commit();
     }
 
 
@@ -3692,14 +3745,14 @@ public class RecordManager
      * @param offset the offset of the B-tree header
      * @return the deserialized B-tree
      */
-    /* No qualifier */<K, V> BTree<K, V> loadDupsBtree( long offset )
+    /* No qualifier */<K, V> BTree<K, V> loadDupsBtree( long btreeHeaderOffset )
     {
         try
         {
-            PageIO[] pageIos = readPageIOs( offset, Long.MAX_VALUE );
+            PageIO[] pageIos = readPageIOs( btreeHeaderOffset, Long.MAX_VALUE );
 
             BTree<K, V> subBtree = BTreeFactory.createPersistedBTree();
-            ( ( PersistedBTree<K, V> ) subBtree ).setBtreeOffset( offset );
+            ( ( PersistedBTree<K, V> ) subBtree ).setBtreeHeaderOffset( btreeHeaderOffset );
 
             loadBtree( pageIos, subBtree );
 



Mime
View raw message