Author: elecharny
Date: Wed Mar  6 14:20:52 2013
New Revision: 1453341

URL: http://svn.apache.org/r1453341
Log:
o Added some setters in the BTree class (we need them in order to create a 
BTree when we deserialize it)
o Removed the HEADER_BUFFER static field, it's useless
o Added the readInt() method
o Added the readPages(offset) method
o Added some Javadoc
o Added a test for readInt()

Added:
    
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/ReadTest.java
Modified:
    labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/BTree.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/store/RecordManagerTest.java

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=1453341&r1=1453340&r2=1453341&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  6 14:20:52 2013
@@ -311,6 +311,14 @@ public class BTree<K, V>
 
 
     /**
+     * Creates a new BTree, with no initialization. 
+     */
+    public BTree() throws IOException
+    {
+    }
+
+
+    /**
      * Creates a new in-memory BTree using the BTreeConfiguration to 
initialize the 
      * BTree
      * 
@@ -1402,6 +1410,15 @@ public class BTree<K, V>
     }
 
 
+    /**
+     * @param revision the revision to set
+     */
+    public void setRevision( long revision )
+    {
+        this.revision.set( revision );
+    }
+
+
     /** 
      * @return The current number of elements in the BTree
      */
@@ -1412,6 +1429,15 @@ public class BTree<K, V>
 
 
     /**
+     * @param nbElems the nbElems to set
+     */
+    public void setNbElems( long nbElems )
+    {
+        this.nbElems.set( nbElems );
+    }
+
+
+    /**
      * @see Object#toString()
      */
     public String 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=1453341&r1=1453340&r2=1453341&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  6 14:20:52 2013
@@ -25,7 +25,9 @@ import java.io.IOException;
 import java.io.RandomAccessFile;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.apache.mavibot.btree.BTree;
@@ -101,7 +103,6 @@ public class RecordManager
     private static final int LAST_FREE_PAGE_SIZE = 8;
 
     private static final int HEADER_SIZE = NB_TREE_SIZE + PAGE_SIZE + 
FIRST_FREE_PAGE_SIZE + LAST_FREE_PAGE_SIZE;
-    private static final ByteBuffer HEADER_BUFFER = ByteBuffer.allocate( 
HEADER_SIZE );
 
     /** The default page size */
     private static final int DEFAULT_PAGE_SIZE = 4 * 1024;
@@ -216,29 +217,50 @@ public class RecordManager
 
 
     /**
-     * We will create a brand new RecordManager file, containing nothing
+     * We will create a brand new RecordManager file, containing nothing, but 
the header and
+     * a BTree used to manage pages associated with old versions.
+     * <br/>
+     * The Header contains the following informations :
+     * <pre>
+     * +-----------+
+     * | PageSize  | 4 bytes : The size of a physical page (default to 4096)
+     * +-----------+
+     * |  NbTree   | 4 bytes : The number of managed BTrees (at least 1)
+     * +-----------+ 
+     * | FirstFree | 8 bytes : The offset of the first free page
+     * +-----------+
+     * | LastFree  | 8 bytes : The offset of the last free page
+     * +-----------+
+     * </pre>
+     * 
+     * We then store the BTree managing the pages that have been copied when 
we have added
+     * or deleted an element in the BTree. They are associated with a version.
      */
     public void initRecordManager() throws IOException
     {
         // Create a new Header
         // The page size
-        HEADER_BUFFER.clear();
-        HEADER_BUFFER.putInt( pageSize );
+        ByteBuffer header = ByteBuffer.allocate( HEADER_SIZE );
+
+        // The page size
+        header.putInt( pageSize );
 
         // The number of managed BTree (currently we have only one : the 
discardedPage BTree
-        HEADER_BUFFER.putInt( 1 );
+        header.putInt( 1 );
 
         // The first free page
-        HEADER_BUFFER.putLong( NO_PAGE );
+        header.putLong( NO_PAGE );
         firstFreePage = NO_PAGE;
 
         // The last free page
-        HEADER_BUFFER.putLong( NO_PAGE );
+        header.putLong( NO_PAGE );
         lastFreePage = NO_PAGE;
 
         // Write the header on disk
-        HEADER_BUFFER.rewind();
-        fileChannel.write( HEADER_BUFFER );
+        header.rewind();
+        fileChannel.write( header );
+
+        // Set the offset of the end of the file
         endOfFileOffset = fileChannel.size();
 
         // Now, initialize the Discarded Page BTree, which is a in-memory BTree
@@ -261,36 +283,221 @@ public class RecordManager
 
 
     /**
-     * We will load all the existing BTrees in this record manager.
+     * We will load the header and all the existing BTrees in this record 
manager.
      */
     public void loadRecordManager() throws IOException
     {
         if ( fileChannel.size() != 0 )
         {
+            ByteBuffer header = ByteBuffer.allocate( HEADER_SIZE );
+
             // The file exists, we have to load the data now 
-            fileChannel.read( HEADER_BUFFER );
+            fileChannel.read( header );
+
+            header.rewind();
 
             // The page size
-            pageSize = HEADER_BUFFER.getInt();
+            pageSize = header.getInt();
 
-            blockBuffer = ByteBuffer.allocate( pageSize );
+            // The number of managed BTrees
+            nbBtree = header.getInt();
 
-            // The number of stored BTrees
-            nbBtree = HEADER_BUFFER.getInt();
+            // The first and last free page
+            firstFreePage = header.getLong();
+            lastFreePage = header.getLong();
+
+            // Now read each BTree. The first one is the one which
+            // 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( 0L );
+            long position = loadBTree( pageIos, 0L, copiedPageBTree );
 
-            // The first free page
-            firstFreePage = HEADER_BUFFER.getLong();
-            lastFreePage = HEADER_BUFFER.getLong();
+            // Then process the next ones
+            for ( int i = 0; i < nbBtree; i++ )
+            {
+                BTree<?, ?> btree = new BTree();
+                position = loadBTree( pageIos, position, btree );
 
-            // Read the meta-data header
-            ByteBuffer header = readHeader();
+                // Store it into the managedBtrees map
+                managedBTrees.put( btree.getName(), btree );
+            }
 
-            // Read the btrees
-            for ( int i = 0; i < nbBtree; i++ )
+            // We are done ! Let's finish with the last initilization parts
+            endOfFileOffset = fileChannel.size();
+        }
+    }
+
+
+    /**
+     * Reads all the pages that are linked to the page at the given position, 
including
+     * the first page.
+     * 
+     * @param position The position of the first page
+     * @return An array of pages
+     */
+    private PageIO[] readPages( long position ) throws IOException, 
EndOfFileExceededException
+    {
+        PageIO firstPage = fetchPage( position );
+        long nextPage = 0L;
+        List<PageIO> listPages = new ArrayList<PageIO>();
+        listPages.add( firstPage );
+
+        // Iterate on the pages
+        while ( ( nextPage = firstPage.getNextPage() ) != NO_PAGE )
+        {
+            PageIO page = fetchPage( nextPage );
+            listPages.add( page );
+        }
+
+        // Return 
+        return listPages.toArray( new PageIO[]
+            {} );
+    }
+
+
+    /**
+     * 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
+     */
+    private long loadBTree( PageIO[] pageIos, long position, BTree<?, ?> btree 
)
+    {
+        // The tree name
+        /*
+        byte[] btreeNameBytes = readBytes( pageIos, position );
+
+        position += INT_SIZE;
+
+        if ( btreeNameBytes != null )
+        {
+            position += btreeNameBytes.length;
+            String btreeName = Strings.utf8ToString( btreeNameBytes );
+            btree.setName( btreeName );
+        }
+        else
+        {
+            btree.setName( "" );
+        }
+
+        // The keySerializer FQCN
+        byte[] keySerializerBytes = readBytes( pageIos, position );
+
+        String keySerializerFqcn = null;
+        position += INT_SIZE;
+
+        if ( keySerializerBytes != null )
+        {
+            position += keySerializerBytes.length;
+            keySerializerFqcn = Strings.utf8ToString( keySerializerBytes );
+        }
+        else
+        {
+            keySerializerFqcn = "";
+        }
+
+        // The valueSerialier FQCN
+        byte[] valueSerializerBytes = readBytes( pageIos, position );
+
+        String valueSerializerFqcn = null;
+        position += INT_SIZE;
+
+        if ( valueSerializerBytes != null )
+        {
+            position += valueSerializerBytes.length;
+            valueSerializerFqcn = Strings.utf8ToString( valueSerializerBytes );
+        }
+        else
+        {
+            valueSerializerFqcn = "";
+        }
+
+        // The BTree page size
+        int pagSize = readInt( pageIos, position );
+        btree.setPageSize( pagSize );
+        position += INT_SIZE;
+
+        // The BTree current revision
+        long revision = readLong( pageIos, position );
+        btree.setRevision( revision );
+        position += LONG_SIZE;
+
+        // The nb elems in the tree
+        long nbElems = readLong( pageIos, position );
+        btree.setNbElems( nbElems )
+        position += LONG_SIZE;
+
+        // The BTree rootPage offset
+        long rootPageOffset = readLong( pageIos, position );
+        
+        List<PageIO> rootPage =  readPages( rootPageOffset );
+        position += LONG_SIZE;
+        */
+
+        return position;
+    }
+
+
+    private int readInt( PageIO[] pageIos, long position )
+    {
+        // Compute the page in which we will store the data given the 
+        // current position
+        int pageNb = computePageNb( position );
+
+        // Compute the position in the current page
+        int pagePos = ( int ) ( position + ( pageNb + 1 ) * 8 + 4 ) - pageNb * 
pageSize;
+
+        ByteBuffer pageData = pageIos[pageNb].getData();
+        int remaining = pageData.capacity() - pagePos;
+        int value = 0;
+
+        if ( remaining >= INT_SIZE )
+        {
+            value = pageData.getInt( pagePos );
+        }
+        else
+        {
+            value = 0;
+
+            switch ( remaining )
             {
-                //----
+                case 3:
+                    value += ( ( pageData.get( pagePos + 2 ) & 0x00FF ) << 8 );
+                    // Fallthrough !!!
+
+                case 2:
+                    value += ( ( pageData.get( pagePos + 1 ) & 0x00FF ) << 16 
);
+                    // Fallthrough !!!
+
+                case 1:
+                    value += ( pageData.get( pagePos ) << 24 );
+                    break;
+            }
+
+            // Now deal with the next page
+            pageData = pageIos[pageNb + 1].getData();
+            pagePos = LINK_SIZE;
+
+            switch ( remaining )
+            {
+                case 1:
+                    value += ( pageData.get( pagePos ) & 0x00FF ) << 16;
+                    // fallthrough !!!
+
+                case 2:
+                    value += ( pageData.get( pagePos + 2 - remaining ) & 
0x00FF ) << 8;
+                    // fallthrough !!!
+
+                case 3:
+                    value += ( pageData.get( pagePos + 3 - remaining ) & 
0x00FF );
+                    break;
             }
         }
+
+        return value;
     }
 
 
@@ -377,6 +584,13 @@ public class RecordManager
     }
 
 
+    /**
+     * Write the pages in the disk, either at the end of the file, or at
+     * the position they were taken from.
+     * 
+     * @param pageIos The list of pages to write
+     * @throws IOException If the write failed
+     */
     private void flushPages( PageIO... pageIos ) throws IOException
     {
         for ( PageIO pageIo : pageIos )

Added: 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/ReadTest.java
URL: 
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/ReadTest.java?rev=1453341&view=auto
==============================================================================
--- 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/ReadTest.java
 (added)
+++ 
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/store/ReadTest.java
 Wed Mar  6 14:20:52 2013
@@ -0,0 +1,112 @@
+/*
+ *  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.store;
+
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+
+import org.junit.Test;
+
+
+/**
+ * Test the RecordManager.readXXX() methods using reflection
+ * 
+ * @author <a href="mailto:[email protected]";>Mavibot labs Project</a>
+ */
+public class ReadTest
+{
+    /**
+     * Test the readInt method
+     */
+    @Test
+    public void testReadInt() throws Exception
+    {
+        File tempFile = File.createTempFile( "mavibot", ".db" );
+        String tempFileName = tempFile.getAbsolutePath();
+        tempFile.deleteOnExit();
+
+        // Create page size of 32 only
+        RecordManager recordManager = new RecordManager( tempFileName, 32 );
+        Method storeMethod = RecordManager.class.getDeclaredMethod( "store", 
PageIO[].class, long.class, int.class );
+        Method readIntMethod = RecordManager.class.getDeclaredMethod( 
"readInt", PageIO[].class, long.class );
+        storeMethod.setAccessible( true );
+        readIntMethod.setAccessible( true );
+
+        // Allocate some Pages
+        PageIO[] pageIos = new PageIO[2];
+        pageIos[0] = new PageIO();
+        pageIos[0].setData( ByteBuffer.allocate( recordManager.getPageSize() ) 
);
+        pageIos[1] = new PageIO();
+        pageIos[1].setData( ByteBuffer.allocate( recordManager.getPageSize() ) 
);
+
+        // Set the int at the beginning
+        long position = ( Long ) storeMethod.invoke( recordManager, pageIos, 
0, 0x12345678 );
+
+        // Read it back
+        int readValue = ( Integer ) readIntMethod.invoke( recordManager, 
pageIos, 0 );
+
+        assertEquals( 0x12345678, readValue );
+
+        // Set the int at the end of the first page
+        position = ( Long ) storeMethod.invoke( recordManager, pageIos, 16, 
0x12345678 );
+
+        // Read it back
+        readValue = ( Integer ) readIntMethod.invoke( recordManager, pageIos, 
16 );
+
+        assertEquals( 0x12345678, readValue );
+
+        // Set the int at the end of the first page and overlapping on the 
second page
+        // 1 byte overlapping
+        position = ( Long ) storeMethod.invoke( recordManager, pageIos, 17, 
0x12345678 );
+
+        // Read it back
+        readValue = ( Integer ) readIntMethod.invoke( recordManager, pageIos, 
17 );
+
+        assertEquals( 0x12345678, readValue );
+
+        // Set the int at the end of the first page and overlapping on the 
second page
+        // 2 bytes overlapping
+        position = ( Long ) storeMethod.invoke( recordManager, pageIos, 18, 
0x12345678 );
+
+        // Read it back
+        readValue = ( Integer ) readIntMethod.invoke( recordManager, pageIos, 
18 );
+
+        assertEquals( 0x12345678, readValue );
+
+        // Set the int at the end of the first page and overlapping on the 
second page
+        // 3 bytes overlapping
+        position = ( Long ) storeMethod.invoke( recordManager, pageIos, 19, 
0x12345678 );
+
+        // Read it back
+        readValue = ( Integer ) readIntMethod.invoke( recordManager, pageIos, 
19 );
+
+        assertEquals( 0x12345678, readValue );
+
+        // Set the int at the beginning of the second page
+        position = ( Long ) storeMethod.invoke( recordManager, pageIos, 20, 
0x12345678 );
+
+        // Read it back
+        readValue = ( Integer ) readIntMethod.invoke( recordManager, pageIos, 
20 );
+    }
+}

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=1453341&r1=1453340&r2=1453341&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  6 14:20:52 2013
@@ -20,6 +20,8 @@
 package org.apache.mavibot.btree.store;
 
 
+import static org.junit.Assert.assertNotNull;
+
 import java.io.File;
 import java.io.IOException;
 
@@ -41,6 +43,8 @@ public class RecordManagerTest
         tempFile.deleteOnExit();
 
         RecordManager recordManager = new RecordManager( tempFileName );
+
+        assertNotNull( recordManager );
     }
 
 }



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

Reply via email to