Author: elecharny
Date: Wed Mar 13 08:38:12 2013
New Revision: 1455840

URL: http://svn.apache.org/r1455840
Log:
o Added a enum to define the BTree type (in-memory, persisted and managed)
o Injected the RM into the BTree
o Added an Offset field in the BTree for when it's managed
o Update the BTree Header on disk when we modify the content of a Managed BTree
o Added toString() methods to the ValueHolder classes
o Injected the BTree in the ValueHolder classes
o Made the ValueHolder interface public
o Added an Offset in the BTree Pages to be able to retrieve them on disk
o First drop of code to save a Page on disk for Managed BTrees
o Added a method to access a ValueHolder from a Leaf, and the reference to the 
children from a Node
o At the moment, Leaf store the values in memory only
o Modify the order in which the BTree header's element are stored, to be able 
to update them with fixed position : the variable length fields are stored 
after the fixed size ones
o Modified the readPages() so that we have an upper limit when we want to read 
only a limited number of pages, to avoid spurious I/O
o Added the serailization of BTree pages
o Added a method to compute the number of pages needed to store some data
o Fixed various tests accordingly to those modifications

Added:
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeTypeEnum.java
Modified:
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractPage.java
    labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeFactory.java
    labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/MemoryValueHolder.java
    labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java
    labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ReferenceValueHolder.java
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ValueHolder.java
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/store/RecordManager.java
    
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/BTreeFlushTest.java
    
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java
    
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerPrivateMethodTest.java
    
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerTest.java

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractPage.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractPage.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractPage.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractPage.java
 Wed Mar 13 08:38:12 2013
@@ -46,6 +46,9 @@ public abstract class AbstractPage<K, V>
     /** The number of current values in the Page */
     protected int nbElems;
 
+    /** The Page offset on disk if the BTree is managed */
+    private long offset;
+
 
     /**
      * Creates a default empty AbstractPage
@@ -273,6 +276,24 @@ public abstract class AbstractPage<K, V>
 
 
     /**
+     * @return the offset
+     */
+    /* No qualifier */long getOffset()
+    {
+        return offset;
+    }
+
+
+    /**
+     * @param offset the offset to set
+     */
+    /* No qualifier */void setOffset( long offset )
+    {
+        this.offset = offset;
+    }
+
+
+    /**
      * @see Object#toString()
      */
     public String toString()

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java 
(original)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTree.java 
Wed Mar 13 08:38:12 2013
@@ -41,6 +41,7 @@ import org.apache.mavibot.btree.exceptio
 import org.apache.mavibot.btree.serializer.BufferHandler;
 import org.apache.mavibot.btree.serializer.ElementSerializer;
 import org.apache.mavibot.btree.serializer.LongSerializer;
+import org.apache.mavibot.btree.store.RecordManager;
 
 
 /**
@@ -86,6 +87,9 @@ public class BTree<K, V>
     /** Number of entries in each Page. */
     protected int pageSize;
 
+    /** The position on disk where this BTree is stored */
+    private long btreeOffset;
+
     /** The size of the buffer used to write data in disk */
     private int writeBufferSize;
 
@@ -101,8 +105,11 @@ public class BTree<K, V>
     /** The associated file. If null, this is an in-memory btree  */
     private File file;
 
-    /** A flag set to true when the BTree is a in-memory BTree */
-    private boolean inMemory;
+    /** The RecordManager if the BTree is managed */
+    private RecordManager recordManager;
+
+    /** The BTree type : either in-memory, persistent or managed */
+    private BTreeTypeEnum type;
 
     /** A flag used to tell the BTree that the journal is activated */
     private boolean withJournal;
@@ -328,7 +335,7 @@ public class BTree<K, V>
 
         if ( fileName == null )
         {
-            inMemory = true;
+            type = BTreeTypeEnum.IN_MEMORY;
         }
         else
         {
@@ -347,7 +354,7 @@ public class BTree<K, V>
             }
 
             journal = new File( journalPath, journalName );
-            inMemory = false;
+            type = BTreeTypeEnum.PERSISTENT;
         }
 
         pageSize = configuration.getPageSize();
@@ -427,7 +434,7 @@ public class BTree<K, V>
 
         if ( ( path == null ) && ( file == null ) )
         {
-            inMemory = true;
+            type = BTreeTypeEnum.IN_MEMORY;
         }
         else
         {
@@ -449,7 +456,7 @@ public class BTree<K, V>
                 this.journal = new File( path, file + JOURNAL_SUFFIX );
             }
 
-            inMemory = false;
+            type = BTreeTypeEnum.PERSISTENT;
         }
 
         setPageSize( pageSize );
@@ -479,7 +486,7 @@ public class BTree<K, V>
         readTransactions = new ConcurrentLinkedQueue<Transaction<K, V>>();
 
         // Create the queue containing the modifications, if it's not a 
in-memory btree
-        if ( !inMemory )
+        if ( type == BTreeTypeEnum.PERSISTENT )
         {
             modificationsQueue = new LinkedBlockingDeque<Modification<K, V>>();
         }
@@ -551,7 +558,7 @@ public class BTree<K, V>
         createTransactionManager();
 
         // Initialize the Journal manager thread if it's not a in-memory btree
-        if ( !inMemory && withJournal )
+        if ( ( type == BTreeTypeEnum.PERSISTENT ) && withJournal )
         {
             createJournalManager();
         }
@@ -567,7 +574,7 @@ public class BTree<K, V>
         readTransactionsThread.interrupt();
         readTransactions.clear();
 
-        if ( !inMemory )
+        if ( type == BTreeTypeEnum.PERSISTENT )
         {
             // Stop the journal manager thread, by injecting a poison pill into
             // the queue this thread is using, so that all the epnding data
@@ -583,6 +590,24 @@ public class BTree<K, V>
 
 
     /**
+     * @return the btreeOffset
+     */
+    public long getBtreeOffset()
+    {
+        return btreeOffset;
+    }
+
+
+    /**
+     * @param btreeOffset the btreeOffset to set
+     */
+    public void setBtreeOffset( long btreeOffset )
+    {
+        this.btreeOffset = btreeOffset;
+    }
+
+
+    /**
      * Gets the number which is a power of 2 immediately above the given 
positive number.
      */
     private int getPowerOf2( int size )
@@ -635,6 +660,29 @@ public class BTree<K, V>
 
 
     /**
+     * Gets the RecordManager for a managed BTree
+     * 
+     * @return The recordManager if the BTree is managed
+     */
+    /* No qualifier */RecordManager getRecordManager()
+    {
+        return recordManager;
+    }
+
+
+    /**
+     * Inject a RecordManager for a managed BTree
+     * 
+     * @param recordManager The injected RecordManager
+     */
+    /* No qualifier */void setRecordManager( RecordManager recordManager )
+    {
+        this.recordManager = recordManager;
+        this.type = BTreeTypeEnum.MANAGED;
+    }
+
+
+    /**
      * @return the pageSize
      */
     public int getPageSize()
@@ -784,7 +832,7 @@ public class BTree<K, V>
                 tuple = removeResult.getRemovedElement();
             }
 
-            if ( !inMemory )
+            if ( type == BTreeTypeEnum.PERSISTENT )
             {
                 // Inject the modification into the modification queue
                 modificationsQueue.add( new Deletion<K, V>( key ) );
@@ -913,6 +961,13 @@ public class BTree<K, V>
                 rootPage = modifyResult.getModifiedPage();
 
                 modifiedValue = modifyResult.getModifiedValue();
+
+                // If the BTree is managed, we have to update the rootPage on 
disk
+                if ( isManaged() )
+                {
+                    // Update the BTree header now
+                    recordManager.updateBtreeHeader( this, btreeOffset );
+                }
             }
             else
             {
@@ -929,7 +984,7 @@ public class BTree<K, V>
             }
 
             // Inject the modification into the modification queue
-            if ( !inMemory )
+            if ( type == BTreeTypeEnum.PERSISTENT )
             {
                 modificationsQueue.add( new Addition<K, V>( key, value ) );
             }
@@ -1251,7 +1306,7 @@ public class BTree<K, V>
      */
     public void flush() throws IOException
     {
-        if ( !inMemory )
+        if ( type == BTreeTypeEnum.PERSISTENT )
         {
             // Then flush the file
             flush( file );
@@ -1338,11 +1393,29 @@ public class BTree<K, V>
 
 
     /**
-     * @return the inMemory flag
+     * @return true if the BTree is fully in memory
      */
     public boolean isInMemory()
     {
-        return inMemory;
+        return type == BTreeTypeEnum.IN_MEMORY;
+    }
+
+
+    /**
+     * @return true if the BTree is persisted on disk
+     */
+    public boolean isPersistent()
+    {
+        return type == BTreeTypeEnum.IN_MEMORY;
+    }
+
+
+    /**
+     * @return true if the BTree is managed by a RecordManager
+     */
+    public boolean isManaged()
+    {
+        return type == BTreeTypeEnum.MANAGED;
     }
 
 
@@ -1354,13 +1427,13 @@ public class BTree<K, V>
      */
     /* no qualifier */ValueHolder<K, V> createHolder( V value )
     {
-        if ( inMemory )
+        if ( type == BTreeTypeEnum.MANAGED )
         {
-            return new MemoryValueHolder<K, V>( value );
+            return new ReferenceValueHolder<K, V>( this, value, -1L );
         }
         else
         {
-            return new ReferenceValueHolder<K, V>( this, value );
+            return new MemoryValueHolder<K, V>( this, value );
         }
     }
 
@@ -1426,9 +1499,20 @@ public class BTree<K, V>
     {
         StringBuilder sb = new StringBuilder();
 
-        if ( inMemory )
+        switch ( type )
         {
-            sb.append( "In-memory " );
+            case IN_MEMORY:
+                sb.append( "In-memory " );
+                break;
+
+            case MANAGED:
+                sb.append( "Managed " );
+                break;
+
+            case PERSISTENT:
+                sb.append( "Persistent " );
+                break;
+
         }
 
         sb.append( "BTree" );
@@ -1436,7 +1520,7 @@ public class BTree<K, V>
 
         if ( rootPage != null )
         {
-            sb.append( ", nbEntries:" ).append( rootPage.getNbElems() );
+            sb.append( ", nbEntries:" ).append( nbElems );
         }
         else
         {
@@ -1454,7 +1538,7 @@ public class BTree<K, V>
             sb.append( comparator.getClass().getSimpleName() );
         }
 
-        if ( !inMemory )
+        if ( type == BTreeTypeEnum.PERSISTENT )
         {
             try
             {

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeFactory.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeFactory.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeFactory.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeFactory.java
 Wed Mar 13 08:38:12 2013
@@ -21,6 +21,7 @@ package org.apache.mavibot.btree;
 
 
 import org.apache.mavibot.btree.serializer.ElementSerializer;
+import org.apache.mavibot.btree.store.RecordManager;
 
 
 /**
@@ -175,4 +176,15 @@ public class BTreeFactory
     {
         btree.setPageSize( pageSize );
     }
+
+
+    /**
+     * Set the RecordManager
+     * 
+     * @param recordManager The injected RecordManager
+     */
+    public static void setRecordManager( BTree<?, ?> btree, RecordManager 
recordManager )
+    {
+        btree.setRecordManager( recordManager );
+    }
 }

Added: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeTypeEnum.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeTypeEnum.java?rev=1455840&view=auto
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeTypeEnum.java
 (added)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTreeTypeEnum.java
 Wed Mar 13 08:38:12 2013
@@ -0,0 +1,43 @@
+/*
+ *  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.mavibot.btree;
+
+
+/**
+ * An enum to describe the BTree type. We have three possible type :
+ * <ul>
+ * <li>IN_MEMORY : the BTree will remain in memory, and won't be persisted on 
disk</li>
+ * <li>PERSISTENT : the BTree is in memory, but will be persisted on disk</li>
+ * <li>MANAGED : the BTree is managed by a RecordManager, and some pages may
+ * be swapped out from memory on demand</li>
+ * </ul>
+ * @author <a href="mailto:[email protected]";>Mavibot labs Project</a>
+ */
+public enum BTreeTypeEnum
+{
+    /** Pure in-memory BTree, not persisted on disk */
+    IN_MEMORY,
+
+    /** In-memory BTree but persisted on disk */
+    PERSISTENT,
+
+    /** A BTree associated with a RecordManager */
+    MANAGED
+}

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java 
(original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java 
Wed Mar 13 08:38:12 2013
@@ -20,6 +20,7 @@
 package org.apache.mavibot.btree;
 
 
+import java.io.IOException;
 import java.lang.reflect.Array;
 import java.util.LinkedList;
 
@@ -64,8 +65,9 @@ public class Leaf<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
+     * @throws IOException 
      */
-    public InsertResult<K, V> insert( long revision, K key, V value )
+    public InsertResult<K, V> insert( long revision, K key, V value ) throws 
IOException
     {
         // Find the key into this leaf
         int pos = findPos( key );
@@ -89,6 +91,17 @@ public class Leaf<K, V> extends Abstract
             // We insert it into a copied page and return the result
             Page<K, V> modifiedPage = addElement( revision, key, value, pos );
 
+            // If the BTree is managed, we now have to write the page on disk
+            // and to add this page to the list of modified pages
+            if ( btree.isManaged() )
+            {
+                ValueHolder holder = btree.getRecordManager()
+                    .modifyPage( btree, this, revision, modifiedPage, revision 
);
+
+                // Store the offset on disk in the page
+                ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( 
ReferenceValueHolder ) holder ).getOffset() );
+            }
+
             InsertResult<K, V> result = new ModifyResult<K, V>( modifiedPage, 
null );
 
             return result;
@@ -411,6 +424,22 @@ public class Leaf<K, V> extends Abstract
     /**
      * {@inheritDoc}
      */
+    public ValueHolder<K, V> getValue( int pos )
+    {
+        if ( pos < nbElems )
+        {
+            return values[pos];
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public Cursor<K, V> browse( K key, Transaction<K, V> transaction, 
LinkedList<ParentPos<K, V>> stack )
     {
         int pos = findPos( key );
@@ -538,7 +567,10 @@ public class Leaf<K, V> extends Abstract
     {
         // First copy the current page, but add one element in the copied page
         Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems + 1 );
-        ValueHolder<K, V> valueHolder = btree.createHolder( value );
+
+        // Atm, store the value in memory 
+        ValueHolder<K, V> valueHolder = new MemoryValueHolder<K, V>( btree, 
value );
+        //ValueHolder<K, V> valueHolder = btree.createHolder( value );
 
         // Deal with the special case of an empty page
         if ( nbElems == 0 )

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/MemoryValueHolder.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/MemoryValueHolder.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/MemoryValueHolder.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/MemoryValueHolder.java
 Wed Mar 13 08:38:12 2013
@@ -20,8 +20,6 @@
 package org.apache.mavibot.btree;
 
 
-
-
 /**
  * A In-Memory Value holder. The value is always present in memory.
  * 
@@ -31,6 +29,9 @@ package org.apache.mavibot.btree;
  */
 /* No qualifier */class MemoryValueHolder<K, V> implements ValueHolder<K, V>
 {
+    /** The BTree */
+    private BTree<K, V> btree;
+
     /** The reference to the Value instance, or null if it's not present */
     private V reference;
 
@@ -41,8 +42,9 @@ package org.apache.mavibot.btree;
      * @param offset The offset in disk for this value
      * @param value The value to store into a SoftReference
      */
-    public MemoryValueHolder( V value )
+    public MemoryValueHolder( BTree<K, V> btree, V value )
     {
+        this.btree = btree;
         this.reference = value;
     }
 
@@ -55,4 +57,23 @@ package org.apache.mavibot.btree;
     {
         return reference;
     }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( btree.getName() ).append( " : '" );
+
+        V value = getValue( btree );
+
+        sb.append( value );
+
+        sb.append( "'" );
+
+        return sb.toString();
+    }
 }

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java 
(original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java 
Wed Mar 13 08:38:12 2013
@@ -95,7 +95,7 @@ public class Node<K, V> extends Abstract
     /**
      * {@inheritDoc}
      */
-    public InsertResult<K, V> insert( long revision, K key, V value )
+    public InsertResult<K, V> insert( long revision, K key, V value ) throws 
IOException
     {
         // Find the key into this leaf
         int pos = findPos( key );
@@ -774,6 +774,22 @@ public class Node<K, V> extends Abstract
     /**
      * {@inheritDoc}
      */
+    public Page<K, V> getReference( int pos )
+    {
+        if ( pos < nbElems + 1 )
+        {
+            return children[pos];
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
     public Cursor<K, V> browse( K key, Transaction<K, V> transaction, 
LinkedList<ParentPos<K, V>> stack )
     {
         int pos = findPos( key );

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java 
(original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java 
Wed Mar 13 08:38:12 2013
@@ -59,7 +59,7 @@ public interface Page<K, V>
      * @param value Inserted value
      * @return Either a modified Page or an Overflow element if the Page was 
full
      */
-    InsertResult<K, V> insert( long revision, K key, V value );
+    InsertResult<K, V> insert( long revision, K key, V value ) throws 
IOException;
 
 
     /**

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ReferenceValueHolder.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ReferenceValueHolder.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ReferenceValueHolder.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ReferenceValueHolder.java
 Wed Mar 13 08:38:12 2013
@@ -32,8 +32,11 @@ import java.lang.ref.SoftReference;
  *
  * @author <a href="mailto:[email protected]";>Mavibot labs Project</a>
  */
-/* No qualifier */class ReferenceValueHolder<K, V> implements ValueHolder<K, V>
+public class ReferenceValueHolder<K, V> implements ValueHolder<K, V>
 {
+    /** The BTree */
+    private BTree<K, V> btree;
+
     /** The offset for a value stored on disk */
     private long offset;
 
@@ -47,9 +50,10 @@ import java.lang.ref.SoftReference;
      * @param offset The offset in disk for this value
      * @param value The value to store into a SoftReference
      */
-    public ReferenceValueHolder( BTree<K, V> btree, V value )
+    public ReferenceValueHolder( BTree<K, V> btree, V value, long offset )
     {
-        //this.offset = btree.getOffset();
+        this.btree = btree;
+        this.offset = offset;
         this.reference = new SoftReference<V>( value );
     }
 
@@ -80,4 +84,29 @@ import java.lang.ref.SoftReference;
     {
         return null;
     }
+
+
+    /* No qualifier */long getOffset()
+    {
+        return offset;
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( btree.getName() ).append( "[" ).append( offset ).append( "] 
: '" );
+
+        V value = getValue( btree );
+
+        sb.append( value );
+
+        sb.append( "'" );
+
+        return sb.toString();
+    }
 }

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ValueHolder.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ValueHolder.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ValueHolder.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ValueHolder.java
 Wed Mar 13 08:38:12 2013
@@ -29,7 +29,7 @@ package org.apache.mavibot.btree;
  *
  * @author <a href="mailto:[email protected]";>Mavibot labs Project</a>
  */
-/* No qualifier */interface ValueHolder<K, V>
+public interface ValueHolder<K, V>
 {
     /**
      * @param btree The Btree storing the value

Modified: 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/store/RecordManager.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/store/RecordManager.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/store/RecordManager.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/store/RecordManager.java
 Wed Mar 13 08:38:12 2013
@@ -34,12 +34,16 @@ import java.util.Set;
 
 import org.apache.mavibot.btree.BTree;
 import org.apache.mavibot.btree.BTreeFactory;
+import org.apache.mavibot.btree.Leaf;
 import org.apache.mavibot.btree.Node;
 import org.apache.mavibot.btree.Page;
+import org.apache.mavibot.btree.ReferenceValueHolder;
+import org.apache.mavibot.btree.ValueHolder;
 import org.apache.mavibot.btree.exception.BTreeAlreadyManagedException;
 import org.apache.mavibot.btree.exception.EndOfFileExceededException;
 import org.apache.mavibot.btree.serializer.IntSerializer;
 import org.apache.mavibot.btree.serializer.LongArraySerializer;
+import org.apache.mavibot.btree.serializer.LongSerializer;
 import org.apache.mavinot.btree.utils.Strings;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -216,6 +220,7 @@ public class RecordManager
         }
         catch ( Exception e )
         {
+            e.printStackTrace();
             LOG.error( "Error while initializing the RecordManager : {}", 
e.getMessage() );
         }
     }
@@ -247,7 +252,7 @@ public class RecordManager
         nbBtree = 0;
         firstFreePage = NO_PAGE;
         lastFreePage = NO_PAGE;
-        updateHeader();
+        updateRecordManagerHeader();
 
         // Set the offset of the end of the file
         endOfFileOffset = fileChannel.size();
@@ -302,12 +307,16 @@ public class RecordManager
             // manage the modified pages. Once read, we can discard all
             // the pages that are stored in it, as we have restarted 
             // the RecordManager.
-            PageIO[] pageIos = readPages( HEADER_SIZE );
+            long btreeOffset = HEADER_SIZE;
+
+            PageIO[] pageIos = readPages( HEADER_SIZE, Long.MAX_VALUE );
             long position = pageIos.length * pageSize + HEADER_SIZE;
 
             // Create the BTree
             copiedPageBTree = BTreeFactory.createBTree();
+            copiedPageBTree.setBtreeOffset( btreeOffset );
 
+            btreeOffset = position;
             position = loadBTree( pageIos, position, copiedPageBTree );
 
             // Then process the next ones
@@ -315,13 +324,15 @@ public class RecordManager
             {
                 // Create the BTree
                 BTree<?, ?> btree = BTreeFactory.createBTree();
+                btree.setBtreeOffset( btreeOffset );
 
                 // Read the associated pages
-                pageIos = readPages( position );
+                pageIos = readPages( position, Long.MAX_VALUE );
                 position = pageIos.length * pageSize;
 
                 // Load the BTree
                 position = loadBTree( pageIos, position, btree );
+                btreeOffset = position;
 
                 // Store it into the managedBtrees map
                 managedBTrees.put( btree.getName(), btree );
@@ -340,21 +351,31 @@ public class RecordManager
      * @param position The position of the first page
      * @return An array of pages
      */
-    private PageIO[] readPages( long position ) throws IOException, 
EndOfFileExceededException
+    private PageIO[] readPages( long position, long limit ) throws 
IOException, EndOfFileExceededException
     {
+        if ( limit <= 0 )
+        {
+            limit = Long.MAX_VALUE;
+        }
+
         PageIO firstPage = fetchPage( position );
         firstPage.setSize();
         List<PageIO> listPages = new ArrayList<PageIO>();
         listPages.add( firstPage );
+        long dataRead = pageSize - LONG_SIZE - INT_SIZE;
 
-        // Iterate on the pages
-        long nextPage = firstPage.getNextPage();
-
-        while ( nextPage != NO_PAGE )
+        // Iterate on the pages, if needed
+        if ( dataRead < limit )
         {
-            PageIO page = fetchPage( nextPage );
-            listPages.add( page );
-            nextPage = page.getNextPage();
+            long nextPage = firstPage.getNextPage();
+
+            while ( ( nextPage != NO_PAGE ) && ( dataRead < limit ) )
+            {
+                PageIO page = fetchPage( nextPage );
+                listPages.add( page );
+                nextPage = page.getNextPage();
+                dataRead += pageSize - LONG_SIZE;
+            }
         }
 
         // Return 
@@ -379,9 +400,27 @@ public class RecordManager
     {
         long dataPos = 0L;
 
+        // The BTree current revision
+        long revision = readLong( pageIos, dataPos );
+        BTreeFactory.setRevision( btree, revision );
+        dataPos += LONG_SIZE;
+
+        // The nb elems in the tree
+        int nbElems = readInt( pageIos, dataPos );
+        BTreeFactory.setNbElems( btree, nbElems );
+        dataPos += LONG_SIZE;
+
+        // The BTree rootPage offset
+        long rootPageOffset = readLong( pageIos, dataPos );
+        dataPos += LONG_SIZE;
+
+        // The BTree page size
+        int btreePageSize = readInt( pageIos, dataPos );
+        BTreeFactory.setPageSize( btree, btreePageSize );
+        dataPos += INT_SIZE;
+
         // The tree name
         byte[] btreeNameBytes = readBytes( pageIos, dataPos );
-
         dataPos += INT_SIZE;
 
         if ( btreeNameBytes != null )
@@ -431,33 +470,15 @@ public class RecordManager
 
         BTreeFactory.setValueSerializer( btree, valueSerializerFqcn );
 
-        // The BTree page size
-        int btreePageSize = readInt( pageIos, dataPos );
-        BTreeFactory.setPageSize( btree, btreePageSize );
-        dataPos += INT_SIZE;
-
-        // The BTree current revision
-        long revision = readLong( pageIos, dataPos );
-        BTreeFactory.setRevision( btree, revision );
-        dataPos += LONG_SIZE;
-
-        // The nb elems in the tree
-        int nbElems = readInt( pageIos, dataPos );
-        BTreeFactory.setNbElems( btree, nbElems );
-        dataPos += LONG_SIZE;
-
-        // Now, int the BTree
+        // Now, init the BTree
         btree.init();
 
-        // The BTree rootPage offset
-        long rootPageOffset = readLong( pageIos, dataPos );
-
         // Now, load the rootPage, which can be a Leaf or a Node, depending 
         // on the number of elements in the tree : if it's above the pageSize,
         // it's a Node, otherwise it's a Leaf
 
         // Read the rootPage pages on disk
-        PageIO[] rootPageIos = readPages( rootPageOffset );
+        PageIO[] rootPageIos = readPages( rootPageOffset, Long.MAX_VALUE );
         position += rootPageIos.length * pageSize;
 
         Page btreeRoot = readPage( btree, revision, rootPageIos );
@@ -473,7 +494,7 @@ public class RecordManager
         Page node = BTreeFactory.createNode( btree, revision, nbElems );
 
         // Read the rootPage pages on disk
-        PageIO[] pageIos = readPages( offset );
+        PageIO[] pageIos = readPages( offset, Long.MAX_VALUE );
 
         return node;
     }
@@ -734,6 +755,8 @@ public class RecordManager
      */
     public synchronized void manage( BTree<?, ?> btree ) throws 
BTreeAlreadyManagedException, IOException
     {
+        BTreeFactory.setRecordManager( btree, this );
+
         String name = btree.getName();
 
         if ( managedBTrees.containsKey( name ) )
@@ -767,6 +790,10 @@ public class RecordManager
         // Get the pageIOs we need to store the data. We may need more than 
one.
         PageIO[] pageIos = getFreePageIOs( bufferSize );
 
+        // Store the BTree Offset into the BTree
+        long btreeOffset = pageIos[0].getOffset();
+        btree.setBtreeOffset( btreeOffset );
+
         // Now store the BTree data in the pages :
         // - the BTree name
         // - the keySerializer FQCN
@@ -778,18 +805,6 @@ public class RecordManager
         // Starts at 0
         long position = 0L;
 
-        // The tree name
-        position = store( position, btreeNameBytes, pageIos );
-
-        // The keySerializer FQCN
-        position = store( position, keySerializerBytes, pageIos );
-
-        // The valueSerialier FQCN
-        position = store( position, valueSerializerBytes, pageIos );
-
-        // The BTree page size
-        position = store( position, btree.getPageSize(), pageIos );
-
         // The BTree current revision
         position = store( position, btree.getRevision(), pageIos );
 
@@ -799,7 +814,7 @@ public class RecordManager
         // Serialize the BTree root page
         Page rootPage = BTreeFactory.getRoot( btree );
 
-        PageIO[] rootPageIos = createSerializedPage( btree.getRevision(), 
rootPage );
+        PageIO[] rootPageIos = serializePage( btree, btree.getRevision(), 
rootPage );
 
         // Get the reference on the first page
         PageIO rootPageIo = rootPageIos[0];
@@ -807,6 +822,18 @@ public class RecordManager
         // Now, we can inject the BTree rootPage offset into the BTree header
         position = store( position, rootPageIo.getOffset(), pageIos );
 
+        // The BTree page size
+        position = store( position, btree.getPageSize(), pageIos );
+
+        // The tree name
+        position = store( position, btreeNameBytes, pageIos );
+
+        // The keySerializer FQCN
+        position = store( position, keySerializerBytes, pageIos );
+
+        // The valueSerialier FQCN
+        position = store( position, valueSerializerBytes, pageIos );
+
         // And flush the pages to disk now
         flushPages( pageIos );
         flushPages( rootPageIos );
@@ -814,7 +841,7 @@ public class RecordManager
         nbBtree++;
 
         // Last, not last, update the number of managed BTrees in the header
-        updateHeader();
+        updateRecordManagerHeader();
     }
 
 
@@ -835,7 +862,7 @@ public class RecordManager
      * @return An array of pages containing the serialized node
      * @throws IOException
      */
-    private PageIO[] createSerializedPage( long revision, Page page ) throws 
IOException
+    private PageIO[] serializePage( BTree btree, long revision, Page page ) 
throws IOException
     {
         int nbElems = page.getNbElems();
 
@@ -871,8 +898,68 @@ public class RecordManager
         }
         else
         {
-            // Allocate the array to store the result
-            PageIO[] pageIos = new PageIO[1];
+            // Prepare a list of byte[] that will contain the serialized page
+            int nbBuffers = 1 + 1 + nbElems * 2;
+            int dataSize = 0;
+
+            if ( page instanceof Node )
+            {
+                // A Node has one more value to store
+                nbBuffers++;
+            }
+
+            // Now, we can create the list with the right size
+            List<byte[]> serializedData = new ArrayList<byte[]>( nbBuffers );
+
+            // The revision
+            byte[] buffer = LongSerializer.serialize( revision );
+            serializedData.add( buffer );
+            dataSize += buffer.length;
+
+            // The number of elements
+            buffer = IntSerializer.serialize( nbElems );
+            serializedData.add( buffer );
+            dataSize += buffer.length;
+
+            // Iterate on the keys
+            for ( int pos = 0; pos < nbElems; pos++ )
+            {
+                // Start with the value
+                if ( page instanceof Node )
+                {
+                    Page child = ( ( Node ) page ).getReference( pos );
+                    //serializedData.add( 
btree.getValueSerializer().serialize( child..get );
+                }
+                else
+                {
+                    ValueHolder value = ( ( Leaf ) page ).getValue( pos );
+                    buffer = btree.getValueSerializer().serialize( 
value.getValue( btree ) );
+                    serializedData.add( buffer );
+                    dataSize += buffer.length;
+                }
+
+                // and the key
+                buffer = btree.getKeySerializer().serialize( page.getKey( pos 
) );
+                serializedData.add( buffer );
+                dataSize += buffer.length;
+            }
+
+            // Nodes have one mor evalue to serialize
+            if ( page instanceof Node )
+            {
+                // TODO
+            }
+
+            // We are done. Allocate the pages we need to store the data
+            PageIO[] pageIos = getFreePageIOs( dataSize );
+
+            // And store the data into those pages
+            long position = 0L;
+
+            for ( byte[] bytes : serializedData )
+            {
+                position = storeRaw( position, bytes, pageIos );
+            }
 
             return pageIos;
         }
@@ -882,7 +969,7 @@ public class RecordManager
     /**
      * Update the header, injecting the nbBtree, firstFreePage and lastFreePage
      */
-    private void updateHeader() throws IOException
+    private void updateRecordManagerHeader() throws IOException
     {
         // The page size
         ByteBuffer header = ByteBuffer.allocate( HEADER_SIZE );
@@ -906,6 +993,43 @@ public class RecordManager
 
 
     /**
+     * Update the BTree header after a BTree modification. We update the 
following fields :
+     * <ul>
+     * <li>the revision</li>
+     * <li>the number of elements</li>
+     * <li>the rootPage offset</li>
+     * </ul>
+     * @param btree
+     * @throws IOException 
+     * @throws EndOfFileExceededException 
+     */
+    public void updateBtreeHeader( BTree btree, long rootPageOffset ) throws 
EndOfFileExceededException, IOException
+    {
+        // Read the pageIOs associated with this BTree
+        long offset = btree.getBtreeOffset();
+        long headerSize = LONG_SIZE + LONG_SIZE + LONG_SIZE;
+
+        PageIO[] pageIos = readPages( offset, headerSize );
+
+        // Now, update the revision
+        long position = 0;
+
+        position = store( position, btree.getRevision(), pageIos );
+        position = store( position, btree.getNbElems(), pageIos );
+        position = store( position, rootPageOffset, pageIos );
+
+        // Flush only the needed pages : we have stored the revision, the 
number of elements 
+        // and the rootPage offset, three longs.
+        int nbPages = computeNbPages( ( int ) headerSize );
+
+        for ( int i = 0; i < nbPages; i++ )
+        {
+            flushPages( pageIos[i] );
+        }
+    }
+
+
+    /**
      * Write the pages in the disk, either at the end of the file, or at
      * the position they were taken from.
      * 
@@ -1026,6 +1150,72 @@ public class RecordManager
 
 
     /**
+     * Stores a byte[] into one ore more pageIO (depending if the long is 
stored
+     * across a boundary or not). We don't add the byte[] size, it's already 
present
+     * in the received byte[].
+     * 
+     * @param position The position in a virtual byte[] if all the pages were 
contiguous
+     * @param bytes The byte[] to serialize
+     * @param pageIos The pageIOs we have to store the data in
+     * @return The new position
+     */
+    private long storeRaw( long position, byte[] bytes, PageIO... pageIos )
+    {
+        if ( bytes != null )
+        {
+            // Compute the page in which we will store the data given the 
+            // current position
+            int pageNb = computePageNb( position );
+
+            // Get back the buffer in this page
+            ByteBuffer pageData = pageIos[pageNb].getData();
+
+            // Compute the position in the current page
+            int pagePos = ( int ) ( position + ( pageNb + 1 ) * LONG_SIZE + 
INT_SIZE ) - pageNb * pageSize;
+
+            // Compute the remaining size in the page
+            int remaining = pageData.capacity() - pagePos;
+            int nbStored = bytes.length;
+
+            // And now, write the bytes until we have none
+            while ( nbStored > 0 )
+            {
+                if ( remaining > nbStored )
+                {
+                    pageData.mark();
+                    pageData.position( pagePos );
+                    pageData.put( bytes, bytes.length - nbStored, nbStored );
+                    pageData.reset();
+                    nbStored = 0;
+                }
+                else
+                {
+                    pageData.mark();
+                    pageData.position( pagePos );
+                    pageData.put( bytes, bytes.length - nbStored, remaining );
+                    pageData.reset();
+                    pageNb++;
+                    pageData = pageIos[pageNb].getData();
+                    pagePos = LINK_SIZE;
+                    nbStored -= remaining;
+                    remaining = pageData.capacity() - pagePos;
+                }
+            }
+
+            // We are done
+            position += bytes.length;
+        }
+        else
+        {
+            // No bytes : write 0 and return
+            position = store( position, 0, pageIos );
+        }
+
+        return position;
+    }
+
+
+    /**
      * Stores an Integer into one ore more pageIO (depending if the int is 
stored
      * across a boundary or not)
      * 
@@ -1208,21 +1398,47 @@ public class RecordManager
 
 
     /**
-     * Get as many pages as needed to store the data which size is provided
-     *  
-     * @param dataSize The data size
-     * @return An array of pages, enough to store the full data
+     * Stores a new page on disk. We will add the modified page into the tree 
of copied pages.
+     * The new page is serialized and saved on disk.
+     * 
+     * @param oldPage
+     * @param oldRevision
+     * @param newPage
+     * @param newRevision
+     * @return The offset of the new page
+     * @throws IOException 
      */
-    private PageIO[] getFreePageIOs( int dataSize ) throws IOException
+    public ValueHolder modifyPage( BTree btree, Page oldPage, long 
oldRevision, Page newPage, long newRevision )
+        throws IOException
     {
-        if ( dataSize == 0 )
+        // We first need to save the new page on disk
+        PageIO[] pageIos = serializePage( btree, newRevision, newPage );
+
+        // Write the page on disk
+        flushPages( pageIos );
+
+        // Build the resulting reference
+        ValueHolder valueHolder = new ReferenceValueHolder( btree, newPage, 
pageIos[0].getOffset() );
+
+        return valueHolder;
+    }
+
+
+    /**
+     * Compute the number of pages needed to store some specific size of data.
+     * 
+     * @param dataSize The size of the data we want to store in pages
+     * @return The number of pages needed
+     */
+    private int computeNbPages( int dataSize )
+    {
+        if ( dataSize <= 0 )
         {
-            return new PageIO[]
-                {};
+            return 0;
         }
 
         // Compute the number of pages needed.
-        // Considering that each page coan contain PageSize bytes,
+        // Considering that each page can contain PageSize bytes,
         // but that the first 8 bytes are used for links and we 
         // use 4 bytes to store the data size, the number of needed
         // pages is :
@@ -1244,6 +1460,26 @@ public class RecordManager
             }
         }
 
+        return nbNeededPages;
+    }
+
+
+    /**
+     * Get as many pages as needed to store the data which size is provided
+     *  
+     * @param dataSize The data size
+     * @return An array of pages, enough to store the full data
+     */
+    private PageIO[] getFreePageIOs( int dataSize ) throws IOException
+    {
+        if ( dataSize == 0 )
+        {
+            return new PageIO[]
+                {};
+        }
+
+        int nbNeededPages = computeNbPages( dataSize );
+
         PageIO[] pageIOs = new PageIO[nbNeededPages];
 
         // The first page : set the size
@@ -1474,7 +1710,7 @@ public class RecordManager
         for ( int i = 0; i < nbBTree; i++ )
         {
             System.out.println( "  Btree[" + i + "]" );
-            PageIO[] pageIos = readPages( position );
+            PageIO[] pageIos = readPages( position, Long.MAX_VALUE );
 
             for ( PageIO pageIo : pageIos )
             {

Modified: 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/BTreeFlushTest.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/BTreeFlushTest.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/BTreeFlushTest.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/BTreeFlushTest.java
 Wed Mar 13 08:38:12 2013
@@ -33,7 +33,6 @@ import org.apache.mavibot.btree.exceptio
 import org.apache.mavibot.btree.serializer.IntSerializer;
 import org.apache.mavibot.btree.serializer.LongSerializer;
 import org.apache.mavibot.btree.serializer.StringSerializer;
-import org.junit.BeforeClass;
 import org.junit.Test;
 
 
@@ -44,9 +43,6 @@ import org.junit.Test;
  */
 public class BTreeFlushTest
 {
-    /** A file containing 100 000 elements */
-    private static String data100K;
-
     // Some values to inject in a btree
     private static int[] sortedValues = new int[]
         {
@@ -116,7 +112,7 @@ public class BTreeFlushTest
     };
 
 
-    private static void create1MElementsFile() throws IOException
+    private String create100KElementsFile() throws IOException
     {
         Random random = new Random( System.nanoTime() );
 
@@ -146,7 +142,7 @@ public class BTreeFlushTest
                 System.out.println( "Error while adding " + value );
                 nbError++;
 
-                return;
+                return null;
             }
 
             if ( i % 10000 == 0 )
@@ -181,14 +177,7 @@ public class BTreeFlushTest
         System.out.println( "Time to flush 100 000 elements : " + ( t1 - t0 ) 
+ "ms" );
         btree.close();
 
-        data100K = tempFile.getCanonicalPath();
-    }
-
-
-    @BeforeClass
-    public static void setup() throws IOException
-    {
-        create1MElementsFile();
+        return tempFile.getCanonicalPath();
     }
 
 
@@ -294,6 +283,7 @@ public class BTreeFlushTest
     @Test
     public void testLoadBTreeFromFile() throws Exception
     {
+        String data100K = create100KElementsFile();
         File dataFile = new File( data100K );
         BTree<Long, String> btree = new BTree<Long, String>(
             "test",

Modified: 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java 
(original)
+++ 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/LeafTest.java 
Wed Mar 13 08:38:12 2013
@@ -64,8 +64,9 @@ public class LeafTest
 
     /**
      * A helper method to insert elements in a Leaf
+     * @throws IOException 
      */
-    private Leaf<Long, String> insert( Leaf<Long, String> leaf, long key, 
String value )
+    private Leaf<Long, String> insert( Leaf<Long, String> leaf, long key, 
String value ) throws IOException
     {
         InsertResult<Long, String> result = leaf.insert( 1L, key, value );
 
@@ -206,9 +207,10 @@ public class LeafTest
     /**
      * Check that deleting an element from a leaf with N/2 element works when 
we borrow
      * an element in a left page with more than N/2 elements
+     * @throws IOException 
      */
     @Test
-    public void testDeleteBorrowingFromLeftSibling()
+    public void testDeleteBorrowingFromLeftSibling() throws IOException
     {
         Node<Long, String> parent = new Node<Long, String>( btree, 1L, 2 );
         Leaf<Long, String> left = new Leaf<Long, String>( btree );
@@ -275,9 +277,10 @@ public class LeafTest
     /**
      * Check that deleting an element from a leaf with N/2 element works when 
we borrow
      * an element in a right page with more than N/2 elements
+     * @throws IOException 
      */
     @Test
-    public void testDeleteBorrowingFromRightSibling()
+    public void testDeleteBorrowingFromRightSibling() throws IOException
     {
         Node<Long, String> parent = new Node<Long, String>( btree, 1L, 2 );
         Leaf<Long, String> left = new Leaf<Long, String>( btree );
@@ -345,9 +348,10 @@ public class LeafTest
     /**
      * Check that deleting an element from a leaf with N/2 element works when 
we merge
      * it with one of its sibling, if both has N/2 elements
+     * @throws IOException 
      */
     @Test
-    public void testDeleteMergeWithSibling()
+    public void testDeleteMergeWithSibling() throws IOException
     {
         Node<Long, String> parent = new Node<Long, String>( btree, 1L, 2 );
         Leaf<Long, String> left = new Leaf<Long, String>( btree );

Modified: 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerPrivateMethodTest.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerPrivateMethodTest.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerPrivateMethodTest.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerPrivateMethodTest.java
 Wed Mar 13 08:38:12 2013
@@ -73,4 +73,38 @@ public class RecordManagerPrivateMethodT
             assertEquals( 3, pages.length );
         }
     }
+
+
+    /**
+     * Test the ComputeNbPages method
+     */
+    @Test
+    public void testComputeNbPages() throws IOException, SecurityException, 
NoSuchMethodException,
+        IllegalArgumentException, IllegalAccessException, 
InvocationTargetException
+    {
+        File tempFile = File.createTempFile( "mavibot", ".db" );
+        String tempFileName = tempFile.getAbsolutePath();
+        tempFile.deleteOnExit();
+
+        RecordManager recordManager = new RecordManager( tempFileName, 32 );
+        Method computeNbPagesMethod = RecordManager.class.getDeclaredMethod( 
"computeNbPages", int.class );
+        computeNbPagesMethod.setAccessible( true );
+
+        assertEquals( 0, ( ( Integer ) computeNbPagesMethod.invoke( 
recordManager, 0 ) ).intValue() );
+
+        for ( int i = 1; i < 21; i++ )
+        {
+            assertEquals( 1, ( ( Integer ) computeNbPagesMethod.invoke( 
recordManager, i ) ).intValue() );
+        }
+
+        for ( int i = 21; i < 45; i++ )
+        {
+            assertEquals( 2, ( ( Integer ) computeNbPagesMethod.invoke( 
recordManager, i ) ).intValue() );
+        }
+
+        for ( int i = 45; i < 68; i++ )
+        {
+            assertEquals( 3, ( ( Integer ) computeNbPagesMethod.invoke( 
recordManager, i ) ).intValue() );
+        }
+    }
 }

Modified: 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerTest.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerTest.java?rev=1455840&r1=1455839&r2=1455840&view=diff
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerTest.java
 (original)
+++ 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/RecordManagerTest.java
 Wed Mar 13 08:38:12 2013
@@ -36,12 +36,14 @@ import org.junit.Test;
 
 
 /**
- * 
+ * test the RecordManager
  * @author <a href="mailto:[email protected]";>Mavibot labs Project</a>
  */
 public class RecordManagerTest
 {
-
+    /**
+     * Test the creation of a RecordManager, and that we can read it back.  
+     */
     @Test
     public void testRecordManager() throws IOException, 
BTreeAlreadyManagedException
     {
@@ -83,5 +85,57 @@ public class RecordManagerTest
         assertEquals( btree.getPageSize(), btree1.getPageSize() );
         assertEquals( btree.getRevision(), btree1.getRevision() );
         assertEquals( btree.getValueSerializer().getClass().getName(), 
btree1.getValueSerializer().getClass().getName() );
+
+        recordManager1.close();
+    }
+
+
+    /**
+     * Test the creation of a RecordManager with a BTree containing data.
+     */
+    @Test
+    public void testRecordManagerWithBTree() throws IOException, 
BTreeAlreadyManagedException
+    {
+        File tempFile = File.createTempFile( "mavibot", ".db" );
+        String tempFileName = tempFile.getAbsolutePath();
+        tempFile.deleteOnExit();
+
+        RecordManager recordManager = new RecordManager( tempFileName, 32 );
+
+        assertNotNull( recordManager );
+
+        // Create a new BTree
+        BTree<Long, String> btree = new BTree<Long, String>( "test", new 
LongSerializer(), new StringSerializer() );
+
+        // And make it managed by the RM
+        recordManager.manage( btree );
+
+        // Now, add some elemnts in the BTree
+        btree.insert( 1L, "V1" );
+
+        // Close the recordManager
+        recordManager.close();
+
+        // Now, try to reload the file back
+        RecordManager recordManager1 = new RecordManager( tempFileName );
+
+        assertEquals( 1, recordManager1.getNbManagedTrees() );
+
+        Set<String> managedBTrees = recordManager1.getManagedTrees();
+
+        assertEquals( 1, managedBTrees.size() );
+        assertTrue( managedBTrees.contains( "test" ) );
+
+        BTree btree1 = recordManager1.getManagedTree( "test" );
+
+        assertNotNull( btree1 );
+        assertEquals( btree.getComparator().getClass().getName(), 
btree1.getComparator().getClass().getName() );
+        assertEquals( btree.getFile(), btree1.getFile() );
+        assertEquals( btree.getKeySerializer().getClass().getName(), 
btree1.getKeySerializer().getClass().getName() );
+        assertEquals( btree.getName(), btree1.getName() );
+        assertEquals( btree.getNbElems(), btree1.getNbElems() );
+        assertEquals( btree.getPageSize(), btree1.getPageSize() );
+        assertEquals( btree.getRevision(), btree1.getRevision() );
+        assertEquals( btree.getValueSerializer().getClass().getName(), 
btree1.getValueSerializer().getClass().getName() );
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to