Author: elecharny
Date: Fri Mar 15 10:58:16 2013
New Revision: 1456886

URL: http://svn.apache.org/r1456886
Log:
o Added a method in AbtsractPage to inject a key into a specific position (used 
by the deserialization process)
o Added a method in Leaf and Node to store a value at a given position (used by 
the deserialization process)
o Moved all the BTree common data into a BTreeHeader class
o Added the NextBtreeOffset field to manage the links between btrees
o Made the MemoryValueHolder public
o Improved the ReferenceValueHolder toString() method
o Now manage the link between BTrees in the RM
o Fixed the Page serialization/deserialization

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/ReferenceValueHolder.java
    
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/store/RecordManager.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=1456886&r1=1456885&r2=1456886&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
 Fri Mar 15 10:58:16 2013
@@ -276,6 +276,17 @@ public abstract class AbstractPage<K, V>
 
 
     /**
+     * Set the key at a give position
+     * @param pos The position in the keys array
+     * @param key the key to inject
+     */
+    /* No qualifier*/void setKey( int pos, K key )
+    {
+        keys[pos] = key;
+    }
+
+
+    /**
      * @return the offset
      */
     /* No qualifier */long getOffset()

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=1456886&r1=1456885&r2=1456886&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 
Fri Mar 15 10:58:16 2013
@@ -34,13 +34,13 @@ import java.util.LinkedList;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.mavibot.btree.exception.KeyNotFoundException;
 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.BTreeHeader;
 import org.apache.mavibot.btree.store.RecordManager;
 
 
@@ -54,6 +54,9 @@ import org.apache.mavibot.btree.store.Re
  */
 public class BTree<K, V>
 {
+    /** The Hader for a managed BTree */
+    private BTreeHeader btreeHeader;
+
     /** Default page size (number of entries per node) */
     public static final int DEFAULT_PAGE_SIZE = 16;
 
@@ -69,12 +72,6 @@ public class BTree<K, V>
     /** The default journal file suffix */
     public static final String JOURNAL_SUFFIX = ".log";
 
-    /** The BTree name */
-    private String name;
-
-    /** A field used to generate new revisions in a thread safe way */
-    private AtomicLong revision = new AtomicLong( 0L );
-
     /** Comparator used to index entries. */
     private Comparator<K> comparator;
 
@@ -84,12 +81,6 @@ public class BTree<K, V>
     /** The list of read transactions being executed */
     private ConcurrentLinkedQueue<Transaction<K, V>> readTransactions;
 
-    /** 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;
 
@@ -117,9 +108,6 @@ public class BTree<K, V>
     /** The associated journal. If null, this is an in-memory btree  */
     private File journal;
 
-    /** The number of elements in the current revision */
-    private AtomicLong nbElems = new AtomicLong( 0L );
-
     /** A lock used to protect the write operation against concurrent access */
     private ReentrantLock writeLock;
 
@@ -319,6 +307,8 @@ public class BTree<K, V>
      */
     public BTree()
     {
+        btreeHeader = new BTreeHeader( null );
+        type = BTreeTypeEnum.MANAGED;
     }
 
 
@@ -357,7 +347,8 @@ public class BTree<K, V>
             type = BTreeTypeEnum.PERSISTENT;
         }
 
-        pageSize = configuration.getPageSize();
+        btreeHeader = new BTreeHeader( configuration.getName() );
+        btreeHeader.setPageSize( configuration.getPageSize() );
         keySerializer = configuration.getKeySerializer();
         valueSerializer = configuration.getValueSerializer();
         comparator = keySerializer.getComparator();
@@ -430,7 +421,7 @@ public class BTree<K, V>
         int pageSize )
         throws IOException
     {
-        this.name = name;
+        btreeHeader = new BTreeHeader( name );
 
         if ( ( path == null ) && ( file == null ) )
         {
@@ -463,7 +454,13 @@ public class BTree<K, V>
         writeBufferSize = DEFAULT_WRITE_BUFFER_SIZE;
 
         this.keySerializer = keySerializer;
+
+        btreeHeader.setKeySerializerFQCN( keySerializer.getClass().getName() );
+
         this.valueSerializer = valueSerializer;
+
+        btreeHeader.setValueSerializerFQCN( 
valueSerializer.getClass().getName() );
+
         comparator = keySerializer.getComparator();
 
         // Create the first root page, with revision 0L. It will be empty
@@ -594,7 +591,7 @@ public class BTree<K, V>
      */
     public long getBtreeOffset()
     {
-        return btreeOffset;
+        return btreeHeader.getBTreeOffset();
     }
 
 
@@ -603,7 +600,43 @@ public class BTree<K, V>
      */
     public void setBtreeOffset( long btreeOffset )
     {
-        this.btreeOffset = btreeOffset;
+        btreeHeader.setBTreeOffset( btreeOffset );
+    }
+
+
+    /**
+     * @return the rootPageOffset
+     */
+    public long getRootPageOffset()
+    {
+        return btreeHeader.getRootPageOffset();
+    }
+
+
+    /**
+     * @param rootPageOffset the rootPageOffset to set
+     */
+    public void setRootPageOffset( long rootPageOffset )
+    {
+        btreeHeader.setRootPageOffset( rootPageOffset );
+    }
+
+
+    /**
+     * @return the nextBTreeOffset
+     */
+    public long getNextBTreeOffset()
+    {
+        return btreeHeader.getNextBTreeOffset();
+    }
+
+
+    /**
+     * @param nextBTreeOffset the nextBTreeOffset to set
+     */
+    public void setNextBTreeOffset( long nextBTreeOffset )
+    {
+        btreeHeader.setNextBTreeOffset( nextBTreeOffset );
     }
 
 
@@ -636,14 +669,14 @@ public class BTree<K, V>
      */
     public void setPageSize( int pageSize )
     {
-        this.pageSize = pageSize;
-
         if ( pageSize <= 2 )
         {
-            this.pageSize = DEFAULT_PAGE_SIZE;
+            btreeHeader.setPageSize( DEFAULT_PAGE_SIZE );
+        }
+        else
+        {
+            btreeHeader.setPageSize( getPowerOf2( pageSize ) );
         }
-
-        this.pageSize = getPowerOf2( pageSize );
     }
 
 
@@ -687,7 +720,7 @@ public class BTree<K, V>
      */
     public int getPageSize()
     {
-        return pageSize;
+        return btreeHeader.getPageSize();
     }
 
 
@@ -699,7 +732,7 @@ public class BTree<K, V>
     /** No qualifier */
     long generateRevision()
     {
-        return revision.incrementAndGet();
+        return btreeHeader.incrementRevision();
     }
 
 
@@ -731,7 +764,7 @@ public class BTree<K, V>
             // and does not replace an element
             if ( existingValue == null )
             {
-                nbElems.getAndIncrement();
+                btreeHeader.incrementNbElems();
             }
 
             // If the BTree is managed, we have to update the rootPage on disk
@@ -772,7 +805,7 @@ public class BTree<K, V>
         // Decrease the number of element in the current tree if the delete is 
successful
         if ( deleted != null )
         {
-            nbElems.getAndDecrement();
+            btreeHeader.decrementNbElems();
         }
 
         return deleted;
@@ -806,7 +839,7 @@ public class BTree<K, V>
         // Decrease the number of element in the current tree if the delete is 
successful
         if ( deleted != null )
         {
-            nbElems.getAndDecrement();
+            btreeHeader.decrementNbElems();
         }
 
         return deleted;
@@ -1009,7 +1042,7 @@ public class BTree<K, V>
      */
     private Transaction<K, V> beginReadTransaction()
     {
-        Transaction<K, V> readTransaction = new Transaction<K, V>( rootPage, 
revision.get() - 1,
+        Transaction<K, V> readTransaction = new Transaction<K, V>( rootPage, 
btreeHeader.getRevision() - 1,
             System.currentTimeMillis() );
 
         readTransactions.add( readTransaction );
@@ -1051,6 +1084,7 @@ public class BTree<K, V>
     public void setKeySerializer( ElementSerializer<K> keySerializer )
     {
         this.keySerializer = keySerializer;
+        btreeHeader.setKeySerializerFQCN( keySerializer.getClass().getName() );
     }
 
 
@@ -1060,6 +1094,7 @@ public class BTree<K, V>
     public void setValueSerializer( ElementSerializer<V> valueSerializer )
     {
         this.valueSerializer = valueSerializer;
+        btreeHeader.setValueSerializerFQCN( 
valueSerializer.getClass().getName() );
     }
 
 
@@ -1143,7 +1178,7 @@ public class BTree<K, V>
         }
 
         // Write the number of elements first
-        bb.putLong( nbElems.get() );
+        bb.putLong( btreeHeader.getNbElems() );
 
         while ( cursor.hasNext() )
         {
@@ -1266,7 +1301,7 @@ public class BTree<K, V>
         BufferHandler bufferHandler = new BufferHandler( channel, buffer );
 
         long nbElems = LongSerializer.deserialize( bufferHandler.read( 8 ) );
-        this.nbElems.set( nbElems );
+        btreeHeader.setNbElems( nbElems );
 
         // Prepare a list of keys and values read from the disk
         //List<K> keys = new ArrayList<K>();
@@ -1345,7 +1380,7 @@ public class BTree<K, V>
      */
     public String getName()
     {
-        return name;
+        return btreeHeader.getName();
     }
 
 
@@ -1354,7 +1389,7 @@ public class BTree<K, V>
      */
     public void setName( String name )
     {
-        this.name = name;
+        btreeHeader.setName( name );
     }
 
 
@@ -1450,6 +1485,15 @@ public class BTree<K, V>
 
 
     /**
+     * @return the keySerializer FQCN
+     */
+    public String getKeySerializerFQCN()
+    {
+        return btreeHeader.getKeySerializerFQCN();
+    }
+
+
+    /**
      * @return the valueSerializer
      */
     public ElementSerializer<V> getValueSerializer()
@@ -1458,12 +1502,21 @@ public class BTree<K, V>
     }
 
 
+    /**
+     * @return the valueSerializer FQCN
+     */
+    public String getValueSerializerFQCN()
+    {
+        return btreeHeader.getValueSerializerFQCN();
+    }
+
+
     /** 
      * @return The current BTree revision
      */
     public long getRevision()
     {
-        return revision.get();
+        return btreeHeader.getRevision();
     }
 
 
@@ -1472,7 +1525,7 @@ public class BTree<K, V>
      */
     /* No qualifier */void setRevision( long revision )
     {
-        this.revision.set( revision );
+        btreeHeader.setRevision( revision );
     }
 
 
@@ -1481,7 +1534,7 @@ public class BTree<K, V>
      */
     public long getNbElems()
     {
-        return nbElems.get();
+        return btreeHeader.getNbElems();
     }
 
 
@@ -1490,7 +1543,7 @@ public class BTree<K, V>
      */
     /* No qualifier */void setNbElems( long nbElems )
     {
-        this.nbElems.set( nbElems );
+        btreeHeader.setNbElems( nbElems );
     }
 
 
@@ -1518,11 +1571,11 @@ public class BTree<K, V>
         }
 
         sb.append( "BTree" );
-        sb.append( "( pageSize:" ).append( pageSize );
+        sb.append( "( pageSize:" ).append( btreeHeader.getPageSize() );
 
         if ( rootPage != null )
         {
-            sb.append( ", nbEntries:" ).append( nbElems );
+            sb.append( ", nbEntries:" ).append( btreeHeader.getNbElems() );
         }
         else
         {

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=1456886&r1=1456885&r2=1456886&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
 Fri Mar 15 10:58:16 2013
@@ -122,6 +122,24 @@ public class BTreeFactory
 
 
     /**
+     * @param rootPageOffset the rootPageOffset to set
+     */
+    public static void setRootPageOffset( BTree<?, ?> btree, long 
rootPageOffset )
+    {
+        btree.setRootPageOffset( rootPageOffset );
+    }
+
+
+    /**
+     * @param nextBTreeOffset the nextBTreeOffset to set
+     */
+    public static void setNextBTreeOffset( BTree<?, ?> btree, long 
nextBTreeOffset )
+    {
+        btree.setNextBTreeOffset( nextBTreeOffset );
+    }
+
+
+    /**
      * @param name the name to set
      */
     public static void setName( BTree<?, ?> btree, String name )
@@ -187,4 +205,37 @@ public class BTreeFactory
     {
         btree.setRecordManager( recordManager );
     }
+
+
+    /**
+     * Set the key at a give position
+     * @param pos The position in the keys array
+     * @param key the key to inject
+     */
+    public static void setKey( Page page, int pos, Object key )
+    {
+        ( ( AbstractPage ) page ).setKey( pos, key );
+    }
+
+
+    /**
+     * Set the value at a give position
+     * @param pos The position in the values array
+     * @param value the value to inject
+     */
+    public static void setValue( Leaf page, int pos, ValueHolder value )
+    {
+        page.setValue( pos, value );
+    }
+
+
+    /**
+     * Set the value at a give position
+     * @param pos The position in the values array
+     * @param value the value to inject
+     */
+    public static void setValue( Node page, int pos, ValueHolder value )
+    {
+        page.setValue( pos, value );
+    }
 }

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=1456886&r1=1456885&r2=1456886&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 
Fri Mar 15 10:58:16 2013
@@ -85,7 +85,7 @@ public class Leaf<K, V> extends Abstract
         }
 
         // The key is not present in the leaf. We have to add it in the page
-        if ( nbElems < btree.pageSize )
+        if ( nbElems < btree.getPageSize() )
         {
             // The current page is not full, it can contain the added element.
             // We insert it into a copied page and return the result
@@ -153,7 +153,7 @@ public class Leaf<K, V> extends Abstract
         {
             // The current page is not the root. Check if the leaf has more 
than N/2
             // elements
-            int halfSize = btree.pageSize / 2;
+            int halfSize = btree.getPageSize() / 2;
 
             if ( nbElems == halfSize )
             {
@@ -216,7 +216,7 @@ public class Leaf<K, V> extends Abstract
     {
         // Create the new page. It will contain N - 1 elements (the maximum 
number)
         // as we merge two pages that contain N/2 elements minus the one we 
remove
-        Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, btree.pageSize - 
1 );
+        Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, 
btree.getPageSize() - 1 );
         Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos], 
values[pos].getValue( btree ) );
 
         if ( isLeft )
@@ -438,6 +438,17 @@ public class Leaf<K, V> extends Abstract
 
 
     /**
+     * Set the value at a give position
+     * @param pos The position in the values array
+     * @param value the value to inject
+     */
+    public void setValue( int pos, ValueHolder<K, V> value )
+    {
+        values[pos] = value;
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Cursor<K, V> browse( K key, Transaction<K, V> transaction, 
LinkedList<ParentPos<K, V>> stack )
@@ -615,7 +626,7 @@ public class Leaf<K, V> extends Abstract
      */
     private InsertResult<K, V> addAndSplit( long revision, K key, V value, int 
pos )
     {
-        int middle = btree.pageSize >> 1;
+        int middle = btree.getPageSize() >> 1;
         Leaf<K, V> leftLeaf = null;
         Leaf<K, V> rightLeaf = null;
         ValueHolder<K, V> valueHolder = btree.createHolder( value );

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=1456886&r1=1456885&r2=1456886&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
 Fri Mar 15 10:58:16 2013
@@ -27,7 +27,7 @@ package org.apache.mavibot.btree;
  *
  * @author <a href="mailto:[email protected]";>Mavibot labs Project</a>
  */
-/* No qualifier */class MemoryValueHolder<K, V> implements ValueHolder<K, V>
+public class MemoryValueHolder<K, V> implements ValueHolder<K, V>
 {
     /** The BTree */
     private BTree<K, V> btree;
@@ -66,7 +66,7 @@ package org.apache.mavibot.btree;
     {
         StringBuilder sb = new StringBuilder();
 
-        sb.append( btree.getName() ).append( " : '" );
+        sb.append( "'" );
 
         V value = getValue( btree );
 

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=1456886&r1=1456885&r2=1456886&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 
Fri Mar 15 10:58:16 2013
@@ -381,9 +381,9 @@ public class Node<K, V> extends Abstract
     {
         // Create the new node. It will contain N - 1 elements (the maximum 
number)
         // as we merge two nodes that contain N/2 elements minus the one we 
remove
-        Node<K, V> newNode = new Node<K, V>( btree, revision, btree.pageSize );
+        Node<K, V> newNode = new Node<K, V>( btree, revision, 
btree.getPageSize() );
         Tuple<K, V> removedElement = mergedResult.getRemovedElement();
-        int half = btree.pageSize / 2;
+        int half = btree.getPageSize() / 2;
         int index = Math.abs( pos );
 
         if ( isLeft )
@@ -553,7 +553,7 @@ public class Node<K, V> extends Abstract
             }
 
             // We have some parent. Check if the current page is not half full
-            int halfSize = btree.pageSize / 2;
+            int halfSize = btree.getPageSize() / 2;
 
             if ( nbElems > halfSize )
             {
@@ -772,6 +772,17 @@ public class Node<K, V> extends Abstract
 
 
     /**
+     * Set the value at a give position
+     * @param pos The position in the values array
+     * @param value the value to inject
+     */
+    public void setValue( int pos, ValueHolder<K, V> value )
+    {
+        children[pos] = ( Page<K, V> ) value.getValue( btree );
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Page<K, V> getReference( int pos )
@@ -908,7 +919,7 @@ public class Node<K, V> extends Abstract
      */
     private InsertResult<K, V> addAndSplit( long revision, K pivot, Page<K, V> 
leftPage, Page<K, V> rightPage, int pos )
     {
-        int middle = btree.pageSize >> 1;
+        int middle = btree.getPageSize() >> 1;
 
         // Create two new pages
         Node<K, V> newLeftPage = new Node<K, V>( btree, revision, middle );

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=1456886&r1=1456885&r2=1456886&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
 Fri Mar 15 10:58:16 2013
@@ -99,13 +99,16 @@ public class ReferenceValueHolder<K, V> 
     {
         StringBuilder sb = new StringBuilder();
 
-        sb.append( btree.getName() ).append( "[" ).append( offset ).append( "] 
: '" );
+        V value = reference.get();
 
-        V value = getValue( btree );
-
-        sb.append( value );
-
-        sb.append( "'" );
+        if ( value != null )
+        {
+            sb.append( value );
+        }
+        else
+        {
+            sb.append( btree.getName() ).append( "[" ).append( offset 
).append( "]" );
+        }
 
         return sb.toString();
     }

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=1456886&r1=1456885&r2=1456886&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
 Fri Mar 15 10:58:16 2013
@@ -26,8 +26,8 @@ import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -35,6 +35,7 @@ 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.MemoryValueHolder;
 import org.apache.mavibot.btree.Node;
 import org.apache.mavibot.btree.Page;
 import org.apache.mavibot.btree.ReferenceValueHolder;
@@ -123,7 +124,10 @@ public class RecordManager
     private ByteBuffer blockBuffer;
 
     /** The set of managed BTrees */
-    private Map<String, BTree<?, ?>> managedBTrees = new HashMap<String, 
BTree<?, ?>>();
+    private Map<String, BTree<?, ?>> managedBTrees = new LinkedHashMap<String, 
BTree<?, ?>>();
+
+    /** The offset on the last added BTree */
+    private long lastAddedBTreeOffset = NO_PAGE;
 
     /** The default file name */
     private static final String DEFAULT_FILE_NAME = "mavibot.db";
@@ -316,23 +320,22 @@ public class RecordManager
             copiedPageBTree = BTreeFactory.createBTree();
             copiedPageBTree.setBtreeOffset( btreeOffset );
 
-            position = loadBTree( pageIos, position, copiedPageBTree );
-            btreeOffset = position;
+            loadBTree( pageIos, copiedPageBTree );
+            long nextBtreeOffset = copiedPageBTree.getNextBTreeOffset();
 
             // Then process the next ones
             for ( int i = 1; i < nbBtree; i++ )
             {
                 // Create the BTree
                 BTree<?, ?> btree = BTreeFactory.createBTree();
-                btree.setBtreeOffset( btreeOffset );
+                btree.setBtreeOffset( nextBtreeOffset );
 
                 // Read the associated pages
-                pageIos = readPages( position, Long.MAX_VALUE );
-                position = pageIos.length * pageSize;
+                pageIos = readPages( nextBtreeOffset, Long.MAX_VALUE );
 
                 // Load the BTree
-                position = loadBTree( pageIos, position, btree );
-                btreeOffset = position;
+                loadBTree( pageIos, btree );
+                nextBtreeOffset = btree.getNextBTreeOffset();
 
                 // Store it into the managedBtrees map
                 managedBTrees.put( btree.getName(), btree );
@@ -388,14 +391,12 @@ public class RecordManager
      * Read a BTree from the disk. The meta-data are at the given position in 
the list of pages.
      * 
      * @param pageIos The list of pages containing the meta-data
-     * @param position The position in the pageIos
      * @param btree The BTree we have to initialize
-     * @return The new position in the list of given pages
      * @throws InstantiationException 
      * @throws IllegalAccessException 
      * @throws ClassNotFoundException 
      */
-    private long loadBTree( PageIO[] pageIos, long position, BTree<?, ?> btree 
) throws EndOfFileExceededException,
+    private void loadBTree( PageIO[] pageIos, BTree<?, ?> btree ) throws 
EndOfFileExceededException,
         IOException, ClassNotFoundException, IllegalAccessException, 
InstantiationException
     {
         long dataPos = 0L;
@@ -406,12 +407,18 @@ public class RecordManager
         dataPos += LONG_SIZE;
 
         // The nb elems in the tree
-        int nbElems = readInt( pageIos, dataPos );
+        long nbElems = readLong( pageIos, dataPos );
         BTreeFactory.setNbElems( btree, nbElems );
         dataPos += LONG_SIZE;
 
         // The BTree rootPage offset
         long rootPageOffset = readLong( pageIos, dataPos );
+        BTreeFactory.setRootPageOffset( btree, rootPageOffset );
+        dataPos += LONG_SIZE;
+
+        // The next BTree offset
+        long nextBTreeOffset = readLong( pageIos, dataPos );
+        BTreeFactory.setNextBTreeOffset( btree, nextBTreeOffset );
         dataPos += LONG_SIZE;
 
         // The BTree page size
@@ -479,13 +486,10 @@ public class RecordManager
 
         // Read the rootPage pages on disk
         PageIO[] rootPageIos = readPages( rootPageOffset, Long.MAX_VALUE );
-        position += rootPageIos.length * pageSize;
 
-        Page btreeRoot = readPage( btree, revision, rootPageIos );
+        Page btreeRoot = readPage( btree, rootPageIos );
 
         BTreeFactory.setRoot( btree, btreeRoot );
-
-        return position;
     }
 
 
@@ -500,19 +504,50 @@ public class RecordManager
     }
 
 
-    private Page readPage( BTree btree, long revision, PageIO[] pageIos ) 
throws IOException
+    private Page readPage( BTree btree, PageIO[] pageIos ) throws IOException
     {
         // Deserialize the rootPage now
         long position = 0L;
 
+        // The revision
+        long revision = readLong( pageIos, position );
+        position += LONG_SIZE;
+
+        // The number of elements in the page
         int nbElems = readInt( pageIos, position );
+        position += INT_SIZE;
 
+        // The size of the data containing the keys and values
         Page page = null;
+        ByteBuffer byteBuffer = null;
+
+        // Reads the bytes containing all the keys and values, if we have some
+        byte[] data = readBytes( pageIos, position );
+
+        if ( data != null )
+        {
+            byteBuffer = ByteBuffer.allocate( data.length );
+            byteBuffer.put( data );
+            byteBuffer.rewind();
+        }
 
         if ( nbElems >= 0 )
         {
             // Its a leaf
             page = BTreeFactory.createLeaf( btree, revision, nbElems );
+
+            // Read each value and key
+            for ( int i = 0; i < nbElems; i++ )
+            {
+                Object value = btree.getValueSerializer().deserialize( 
byteBuffer );
+
+                ValueHolder valueHolder = new MemoryValueHolder( btree, value 
);
+                BTreeFactory.setValue( ( ( Leaf ) page ), i, valueHolder );
+
+                Object key = btree.getKeySerializer().deserialize( byteBuffer 
);
+
+                BTreeFactory.setKey( page, i, key );
+            }
         }
         else
         {
@@ -770,10 +805,8 @@ public class RecordManager
 
         // We will add the newly managed BTree at the end of the header.
         byte[] btreeNameBytes = Strings.getBytesUtf8( name );
-        String keySerializerFqcn = 
btree.getKeySerializer().getClass().getName();
-        byte[] keySerializerBytes = Strings.getBytesUtf8( keySerializerFqcn );
-        String valueSerializerFqcn = 
btree.getValueSerializer().getClass().getName();
-        byte[] valueSerializerBytes = Strings.getBytesUtf8( 
valueSerializerFqcn );
+        byte[] keySerializerBytes = Strings.getBytesUtf8( 
btree.getKeySerializerFQCN() );
+        byte[] valueSerializerBytes = Strings.getBytesUtf8( 
btree.getValueSerializerFQCN() );
 
         int bufferSize =
             INT_SIZE + // The name size
@@ -785,6 +818,7 @@ public class RecordManager
                 INT_SIZE + // The page size
                 LONG_SIZE + // The revision
                 LONG_SIZE + // the number of element
+                LONG_SIZE + // the nextBtree offset
                 LONG_SIZE; // The root offset
 
         // Get the pageIOs we need to store the data. We may need more than 
one.
@@ -821,6 +855,10 @@ public class RecordManager
 
         // Now, we can inject the BTree rootPage offset into the BTree header
         position = store( position, rootPageIo.getOffset(), pageIos );
+        btree.setRootPageOffset( rootPageIo.getOffset() );
+
+        // The next BTree Header offset (-1L, as it's a new BTree)
+        position = store( position, NO_PAGE, pageIos );
 
         // The BTree page size
         position = store( position, btree.getPageSize(), pageIos );
@@ -840,6 +878,20 @@ public class RecordManager
 
         nbBtree++;
 
+        // Now, if this added BTree is not the first BTree, we have to link it 
with the 
+        // latest added BTree
+        if ( lastAddedBTreeOffset != NO_PAGE )
+        {
+            // We have to update the nextBtreeOffset from the previous 
BTreeHeader
+            pageIos = readPages( lastAddedBTreeOffset, LONG_SIZE + LONG_SIZE + 
LONG_SIZE + LONG_SIZE );
+            store( LONG_SIZE + LONG_SIZE + LONG_SIZE, btreeOffset, pageIos );
+
+            // Write the pages on disk
+            flushPages( pageIos );
+        }
+
+        lastAddedBTreeOffset = btreeOffset;
+
         // Last, not last, update the number of managed BTrees in the header
         updateRecordManagerHeader();
     }
@@ -850,6 +902,7 @@ public class RecordManager
      * <ul>
      * <li>the revision : a long</li>
      * <li>the number of elements : an int (if <= 0, it's a Node, otherwise 
it's a Leaf)</li>
+     * <li>the size of the values/keys when serialized
      * <li>the keys : an array of serialized keys</li>
      * <li>the values : an array of references to the children pageIO offset 
(stored as long)
      * if it's a Node, or a list of values if it's a Leaf</li>
@@ -899,8 +952,9 @@ public class RecordManager
         else
         {
             // Prepare a list of byte[] that will contain the serialized page
-            int nbBuffers = 1 + 1 + nbElems * 2;
+            int nbBuffers = 1 + 1 + 1 + nbElems * 2;
             int dataSize = 0;
+            int serializedSize = 0;
 
             if ( page instanceof Node )
             {
@@ -914,12 +968,12 @@ public class RecordManager
             // The revision
             byte[] buffer = LongSerializer.serialize( revision );
             serializedData.add( buffer );
-            dataSize += buffer.length;
+            serializedSize += buffer.length;
 
             // The number of elements
             buffer = IntSerializer.serialize( nbElems );
             serializedData.add( buffer );
-            dataSize += buffer.length;
+            serializedSize += buffer.length;
 
             // Iterate on the keys
             for ( int pos = 0; pos < nbElems; pos++ )
@@ -950,8 +1004,15 @@ public class RecordManager
                 // TODO
             }
 
+            // Store the data size
+            buffer = IntSerializer.serialize( dataSize );
+            serializedData.add( 2, buffer );
+            serializedSize += buffer.length;
+
+            serializedSize += dataSize;
+
             // We are done. Allocate the pages we need to store the data
-            PageIO[] pageIos = getFreePageIOs( dataSize );
+            PageIO[] pageIos = getFreePageIOs( serializedSize );
 
             // And store the data into those pages
             long position = 0L;



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

Reply via email to