directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1536066 [2/3] - in /directory/mavibot/trunk/mavibot/src: main/java/org/apache/directory/mavibot/btree/ main/java/org/apache/directory/mavibot/btree/managed/ main/java/org/apache/directory/mavibot/btree/memory/ main/java/org/apache/director...
Date Sun, 27 Oct 2013 08:48:08 GMT
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RecordManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RecordManager.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RecordManager.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RecordManager.java Sun Oct 27 08:48:07 2013
@@ -131,6 +131,13 @@ public class RecordManager
     /** A global buffer used to store the header */
     private static ByteBuffer HEADER_BUFFER;
 
+    /** A static buffer used to store the header */
+    private static byte[] HEADER_BYTES;
+
+    /** The length of an Offset, as a nagative value */
+    private static byte[] LONG_LENGTH = new byte[]
+        { ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xF8 };
+
     /** The RecordManager underlying page size. */
     private int pageSize = DEFAULT_PAGE_SIZE;
 
@@ -180,6 +187,7 @@ public class RecordManager
         managedBTrees = new LinkedHashMap<String, BTree<Object, Object>>();
 
         HEADER_BUFFER = ByteBuffer.allocate( pageSize );
+        HEADER_BYTES = new byte[pageSize];
         HEADER_SIZE = pageSize;
 
         // Open the file or create it
@@ -580,94 +588,140 @@ public class RecordManager
         // this ByteBuffer
         ByteBuffer byteBuffer = readBytes( pageIos, position );
 
-        // Now, deserialize the data block
+        // Now, deserialize the data block. If the number of elements
+        // is positive, it's a Leaf, otherwise it's a Node
+        // Note that only a leaf can have 0 elements, and it's the root page then.
         if ( nbElems >= 0 )
         {
-            // Its a leaf, create it
-            page = BTreeFactory.createLeaf( btree, revision, nbElems );
+            // It's a leaf
+            page = readLeaf( btree, nbElems, revision, byteBuffer, pageIos );
+        }
+        else
+        {
+            // It's a node
+            page = readNode( btree, -nbElems, revision, byteBuffer, pageIos );
+        }
 
-            // Store the page offset on disk
-            ( ( AbstractPage<K, V> ) page ).setOffset( pageIos[0].getOffset() );
-            ( ( AbstractPage<K, V> ) page ).setLastOffset( pageIos[pageIos.length - 1].getOffset() );
+        return page;
+    }
 
-            int[] keyLengths = new int[nbElems];
-            int[] valueLengths = new int[nbElems];
 
-            // Read each key and value
-            for ( int i = 0; i < nbElems; i++ )
-            {
-                //valueLengths[i] = byteBuffer.getInt();
+    /**
+     * Deserialize a Leaf from some PageIOs
+     */
+    private <K, V> Leaf<K, V> readLeaf( BTree<K, V> btree, int nbElems, long revision, ByteBuffer byteBuffer,
+        PageIO[] pageIos )
+    {
+        // Its a leaf, create it
+        Leaf<K, V> leaf = BTreeFactory.createLeaf( btree, revision, nbElems );
+
+        // Store the page offset on disk
+        leaf.setOffset( pageIos[0].getOffset() );
+        leaf.setLastOffset( pageIos[pageIos.length - 1].getOffset() );
+
+        int[] keyLengths = new int[nbElems];
+        int[] valueLengths = new int[nbElems];
 
-                ElementHolder<V, K, V> valueHolder;
+        // Read each key and value
+        for ( int i = 0; i < nbElems; i++ )
+        {
+            // Read the number of values
+            int nbValues = byteBuffer.getInt();
+            ValueHolder<V> valueHolder = null;
+
+            if ( nbValues < 0 )
+            {
+                // This is a sub-btree
+                long btreeOffset = byteBuffer.getLong();
 
-                if ( btree.isAllowDuplicates() )
+                // Load the BTree now.
+                try
                 {
-                    byte flag = byteBuffer.get();
+                    PageIO[] rootPageIos = readPageIOs( btreeOffset, Long.MAX_VALUE );
+
+                    BTree<V, V> subBtree = BTreeFactory.createBTree();
+                    subBtree.setBtreeOffset( btreeOffset );
 
-                    if ( flag == 0 )
+                    try
                     {
-                        V singleValue = btree.getValueSerializer().deserialize( byteBuffer );
-                        valueHolder = new MultipleMemoryHolder( btree, singleValue );
+                        loadBTree( rootPageIos, subBtree );
                     }
-                    else if ( flag == 1 )
+                    catch ( Exception e )
                     {
-                        long value = OFFSET_SERIALIZER.deserialize( byteBuffer );
+                        // should not happen
+                        throw new RuntimeException( e );
+                    }
 
-                        BTree<K, V> dupValueContainer = loadDupsBTree( value );
+                    valueHolder = new ValueHolder<V>( this, btree.getValueSerializer(), subBtree );
 
-                        valueHolder = new MultipleMemoryHolder( btree, dupValueContainer );
-                    }
-                    else
-                    {
-                        throw new IllegalStateException( "Unknown multiple value holder flag " + flag );
-                    }
+                    valueHolder.setSubBtree( subBtree );
                 }
-                else
+                catch ( EndOfFileExceededException e1 )
                 {
-                    Object value = btree.getValueSerializer().deserialize( byteBuffer );
-
-                    valueHolder = new MemoryHolder( btree, value );
+                    // TODO Auto-generated catch block
+                    e1.printStackTrace();
                 }
+                catch ( IOException e1 )
+                {
+                    // TODO Auto-generated catch block
+                    e1.printStackTrace();
+                }
+            }
+            else
+            {
+                // This is an array
+                // Read the value's array length
+                valueLengths[i] = byteBuffer.getInt();
 
-                BTreeFactory.setValue( ( ( Leaf<K, V> ) page ), i, valueHolder );
-
-                keyLengths[i] = byteBuffer.getInt();
-                ByteBuffer slice = byteBuffer.slice();
-                slice.limit( keyLengths[i] );
-                byteBuffer.position( byteBuffer.position() + keyLengths[i] );
-                BTreeFactory.setKey( page, i, slice, null );
+                // This is an Array of values, read the byte[] associated with it
+                byte[] valueBytes = new byte[valueLengths[i]];
+                byteBuffer.get( valueBytes );
+                valueHolder = new ValueHolder<V>( this, btree.getValueSerializer(), false, nbValues,
+                    valueBytes );
             }
-        }
-        else
-        {
-            // It's a node
-            int nodeNbElems = -nbElems;
 
-            page = BTreeFactory.createNode( btree, revision, nodeNbElems );
+            BTreeFactory.setValue( leaf, i, valueHolder );
 
-            // Read each value and key
-            for ( int i = 0; i < nodeNbElems; i++ )
-            {
-                // This is an Offset
-                long offset = OFFSET_SERIALIZER.deserialize( byteBuffer );
-                long lastOffset = OFFSET_SERIALIZER.deserialize( byteBuffer );
+            keyLengths[i] = byteBuffer.getInt();
+            byte[] data = new byte[keyLengths[i]];
+            byteBuffer.get( data );
+            BTreeFactory.setKey( leaf, i, data );
+        }
 
-                ElementHolder valueHolder = new PageHolder( btree, null, offset, lastOffset );
-                ( ( Node<K, V> ) page ).setValue( i, valueHolder );
+        return leaf;
+    }
 
-                K key = btree.getKeySerializer().deserialize( byteBuffer );
-                BTreeFactory.setKey( page, i, key );
-            }
 
-            // and read the last value, as it's a node
+    /**
+     * Deserialize a Node from some PageIos
+     */
+    private <K, V> Node<K, V> readNode( BTree<K, V> btree, int nbElems, long revision, ByteBuffer byteBuffer,
+        PageIO[] pageIos ) throws IOException
+    {
+        Node<K, V> node = BTreeFactory.createNode( btree, revision, nbElems );
+
+        // Read each value and key
+        for ( int i = 0; i < nbElems; i++ )
+        {
+            // This is an Offset
             long offset = OFFSET_SERIALIZER.deserialize( byteBuffer );
             long lastOffset = OFFSET_SERIALIZER.deserialize( byteBuffer );
 
-            ElementHolder valueHolder = new PageHolder( btree, null, offset, lastOffset );
-            ( ( Node<K, V> ) page ).setValue( nodeNbElems, valueHolder );
+            PageHolder<K, V> valueHolder = new PageHolder<K, V>( btree, null, offset, lastOffset );
+            node.setValue( i, valueHolder );
+
+            K key = btree.getKeySerializer().deserialize( byteBuffer );
+            BTreeFactory.setKey( node, i, key );
         }
 
-        return page;
+        // and read the last value, as it's a node
+        long offset = OFFSET_SERIALIZER.deserialize( byteBuffer );
+        long lastOffset = OFFSET_SERIALIZER.deserialize( byteBuffer );
+
+        PageHolder<K, V> valueHolder = new PageHolder<K, V>( btree, null, offset, lastOffset );
+        node.setValue( nbElems, valueHolder );
+
+        return node;
     }
 
 
@@ -1103,27 +1157,7 @@ public class RecordManager
 
         if ( nbElems == 0 )
         {
-            // We will have 1 single page if we have no elements
-            PageIO[] pageIos = new PageIO[1];
-
-            // This is either a new root page or a new page that will be filled later
-            PageIO newPage = fetchNewPage();
-
-            // We need first to create a byte[] that will contain all the data
-            // For the root page, this is easy, as we only have to store the revision, 
-            // and the number of elements, which is 0.
-            long position = 0L;
-
-            position = store( position, revision, newPage );
-            position = store( position, nbElems, newPage );
-
-            // Update the page size now
-            newPage.setSize( ( int ) position );
-
-            // Insert the result into the array of PageIO
-            pageIos[0] = newPage;
-
-            return pageIos;
+            return serializeRootPage( revision );
         }
         else
         {
@@ -1160,101 +1194,27 @@ public class RecordManager
             serializedSize += buffer.length;
 
             // Iterate on the keys and values. We first serialize the value, then the key
-            // until we are done with all of them. If w are serializing a page, we have
+            // until we are done with all of them. If we are serializing a page, we have
             // to serialize one more value
             for ( int pos = 0; pos < nbElems; pos++ )
             {
                 // Start with the value
                 if ( page instanceof Node )
                 {
-                    Page<K, V> child = ( ( Node<K, V> ) page ).getReference( pos );
-
-                    // The first offset
-                    buffer = LongSerializer.serialize( child.getOffset() );
-                    serializedData.add( buffer );
-                    dataSize += buffer.length;
-
-                    // The last offset
-                    buffer = LongSerializer.serialize( child.getLastOffset() );
-                    serializedData.add( buffer );
-                    dataSize += buffer.length;
-                }
-                else
-                {
-                    if ( btree.isAllowDuplicates() )
-                    {
-                        MultipleMemoryHolder<K, V> mvHolder = ( MultipleMemoryHolder<K, V> ) ( ( Leaf<K, V> ) page )
-                            .getValue( pos );
-                        if ( mvHolder.isSingleValue() )
-                        {
-                            buffer = btree.getValueSerializer().serialize( mvHolder.getValue( btree ) );
-
-                            //FIXME find a better way to avoid the copying
-                            byte[] tmp = new byte[buffer.length + 1];
-                            tmp[0] = 0; // single value flag
-                            System.arraycopy( buffer, 0, tmp, 1, buffer.length );
-                            buffer = tmp;
-                        }
-                        else
-                        {
-                            long duplicateContainerOffset = ( ( BTree<K, V> ) mvHolder.getValue( btree ) )
-                                .getBtreeOffset();
-                            buffer = new byte[8 + 1];
-                            buffer[0] = 1; // sub-tree flag
-                            buffer = LongSerializer.serialize( buffer, 1, duplicateContainerOffset );
-                        }
-                    }
-                    else
-                    {
-                        ElementHolder<V, K, V> value = ( ( Leaf<K, V> ) page ).getValue( pos );
-                        buffer = btree.getValueSerializer().serialize( value.getValue( btree ) );
-                    }
-
-                    serializedData.add( buffer );
-                    dataSize += buffer.length;
-                }
-
-                // and the key
-                if ( page instanceof Leaf )
-                {
-                    KeyHolder<K> keyHolder = ( ( Leaf<K, V> ) page ).getKeyHolder( pos );
-                    ByteBuffer keyData = keyHolder.getBuffer();
-
-                    if ( keyData != null )
-                    {
-                        serializedData.add( IntSerializer.serialize( keyData.limit() ) );
-                        serializedData.add( keyData.array() );
-                        dataSize += keyData.limit() + 4;
-                    }
-                    else
-                    {
-                        serializedData.add( IntSerializer.serialize( 4 ) );
-                        serializedData.add( Strings.EMPTY_BYTES );
-                        dataSize += 4;
-                    }
+                    dataSize += serializeNodeValue( ( Node<K, V> ) page, pos, serializedData );
+                    dataSize += serializeNodeKey( ( Node<K, V> ) page, pos, serializedData );
                 }
                 else
                 {
-                    buffer = btree.getKeySerializer().serialize( page.getKey( pos ) );
-                    serializedData.add( buffer );
-                    dataSize += buffer.length;
+                    dataSize += serializeLeafValue( ( Leaf<K, V> ) page, pos, serializedData );
+                    dataSize += serializeLeafKey( ( Leaf<K, V> ) page, pos, serializedData );
                 }
             }
 
             // Nodes have one more value to serialize
             if ( page instanceof Node )
             {
-                Page<K, V> child = ( ( Node<K, V> ) page ).getReference( nbElems );
-
-                // The first offset
-                buffer = LongSerializer.serialize( child.getOffset() );
-                serializedData.add( buffer );
-                dataSize += buffer.length;
-
-                // The last offset
-                buffer = LongSerializer.serialize( child.getLastOffset() );
-                serializedData.add( buffer );
-                dataSize += buffer.length;
+                dataSize += serializeNodeValue( ( Node<K, V> ) page, nbElems, serializedData );
             }
 
             // Store the data size
@@ -1281,32 +1241,204 @@ public class RecordManager
 
 
     /**
+     * Serialize a Node's key
+     */
+    private <K, V> int serializeNodeKey( Node<K, V> node, int pos, List<byte[]> serializedData )
+    {
+        byte[] buffer = node.btree.getKeySerializer().serialize( node.getKey( pos ) );
+        serializedData.add( buffer );
+
+        return buffer.length;
+    }
+
+
+    /**
+     * Serialize a Node's Value. We store the two offsets of the child page.
+     */
+    private <K, V> int serializeNodeValue( Node<K, V> node, int pos, List<byte[]> serializedData )
+        throws IOException
+    {
+        // For a node, we just store the children's offsets
+        Page<K, V> child = node.getReference( pos );
+
+        // The first offset
+        byte[] buffer = LongSerializer.serialize( child.getOffset() );
+        serializedData.add( buffer );
+        int dataSize = buffer.length;
+
+        // The last offset
+        buffer = LongSerializer.serialize( child.getLastOffset() );
+        serializedData.add( buffer );
+        dataSize += buffer.length;
+
+        return dataSize;
+    }
+
+
+    /**
+     * Serialize a Leaf's key
+     */
+    private <K, V> int serializeLeafKey( Leaf<K, V> leaf, int pos, List<byte[]> serializedData )
+    {
+        int dataSize = 0;
+        KeyHolder<K> keyHolder = leaf.getKeyHolder( pos );
+        byte[] keyData = keyHolder.getBuffer();
+
+        if ( keyData != null )
+        {
+            byte[] data = new byte[keyData.length];
+
+            // The key length
+            byte[] buffer = IntSerializer.serialize( data.length );
+            serializedData.add( buffer );
+            dataSize += buffer.length;
+
+            // The key data
+            serializedData.add( keyData );
+            dataSize += data.length;
+        }
+        else
+        {
+            serializedData.add( IntSerializer.serialize( 0 ) );
+            dataSize += 4;
+        }
+
+        return dataSize;
+    }
+
+
+    /**
+     * Serialize a Leaf's Value. We store 
+     */
+    private <K, V> int serializeLeafValue( Leaf<K, V> leaf, int pos, List<byte[]> serializedData )
+        throws IOException
+    {
+        // The value can be an Array or a sub-btree, but we don't care
+        // we just iterate on all the values
+        ValueHolder<V> valueHolder = leaf.getValue( pos );
+
+        // First take the number of values
+        int nbValues = valueHolder.size();
+        int dataSize = 0;
+
+        if ( nbValues == 0 )
+        {
+            // No value. 
+            byte[] buffer = IntSerializer.serialize( nbValues );
+            serializedData.add( buffer );
+
+            return buffer.length;
+        }
+
+        if ( valueHolder.isSubBtree() )
+        {
+            byte[] buffer = IntSerializer.serialize( -nbValues );
+            serializedData.add( buffer );
+            dataSize += buffer.length;
+
+            // the BTree offset
+            buffer = LongSerializer.serialize( valueHolder.getOffset() );
+            serializedData.add( buffer );
+            dataSize += buffer.length;
+        }
+        else
+        {
+            // This is an array, store the nb of values as a positive number
+            byte[] buffer = IntSerializer.serialize( nbValues );
+            serializedData.add( buffer );
+            dataSize += buffer.length;
+
+            // Now store each value
+            byte[] data = valueHolder.getRaw();
+            buffer = IntSerializer.serialize( data.length );
+            serializedData.add( buffer );
+            dataSize += buffer.length;
+
+            if ( data.length > 0 )
+            {
+                serializedData.add( data );
+            }
+
+            dataSize += data.length;
+        }
+
+        return dataSize;
+    }
+
+
+    /**
+     * Write a root page with no elements in it
+     */
+    private PageIO[] serializeRootPage( long revision ) throws IOException
+    {
+        // We will have 1 single page if we have no elements
+        PageIO[] pageIos = new PageIO[1];
+
+        // This is either a new root page or a new page that will be filled later
+        PageIO newPage = fetchNewPage();
+
+        // We need first to create a byte[] that will contain all the data
+        // For the root page, this is easy, as we only have to store the revision, 
+        // and the number of elements, which is 0.
+        long position = 0L;
+
+        position = store( position, revision, newPage );
+        position = store( position, 0, newPage );
+
+        // Update the page size now
+        newPage.setSize( ( int ) position );
+
+        // Insert the result into the array of PageIO
+        pageIos[0] = newPage;
+
+        return pageIos;
+    }
+
+
+    /**
      * Update the header, injecting the nbBtree, firstFreePage and lastFreePage
      */
     private void updateRecordManagerHeader() throws IOException
     {
-        HEADER_BUFFER.clear();
-
         // The page size
-        HEADER_BUFFER.putInt( pageSize );
+        HEADER_BYTES[0] = ( byte ) ( pageSize >>> 24 );
+        HEADER_BYTES[1] = ( byte ) ( pageSize >>> 16 );
+        HEADER_BYTES[2] = ( byte ) ( pageSize >>> 8 );
+        HEADER_BYTES[3] = ( byte ) ( pageSize );
 
         // The number of managed BTree (currently we have only one : the discardedPage BTree
-        HEADER_BUFFER.putInt( nbBtree );
+        HEADER_BYTES[4] = ( byte ) ( nbBtree >>> 24 );
+        HEADER_BYTES[5] = ( byte ) ( nbBtree >>> 16 );
+        HEADER_BYTES[6] = ( byte ) ( nbBtree >>> 8 );
+        HEADER_BYTES[7] = ( byte ) ( nbBtree );
 
         // The first free page
-        HEADER_BUFFER.putLong( firstFreePage );
+        HEADER_BYTES[8] = ( byte ) ( firstFreePage >>> 56 );
+        HEADER_BYTES[9] = ( byte ) ( firstFreePage >>> 48 );
+        HEADER_BYTES[10] = ( byte ) ( firstFreePage >>> 40 );
+        HEADER_BYTES[11] = ( byte ) ( firstFreePage >>> 32 );
+        HEADER_BYTES[12] = ( byte ) ( firstFreePage >>> 24 );
+        HEADER_BYTES[13] = ( byte ) ( firstFreePage >>> 16 );
+        HEADER_BYTES[14] = ( byte ) ( firstFreePage >>> 8 );
+        HEADER_BYTES[15] = ( byte ) ( firstFreePage );
 
         // The last free page
-        HEADER_BUFFER.putLong( lastFreePage );
-
-        // Set the limit to the end of the page
-        HEADER_BUFFER.limit( pageSize );
+        HEADER_BYTES[16] = ( byte ) ( lastFreePage >>> 56 );
+        HEADER_BYTES[17] = ( byte ) ( lastFreePage >>> 48 );
+        HEADER_BYTES[18] = ( byte ) ( lastFreePage >>> 40 );
+        HEADER_BYTES[19] = ( byte ) ( lastFreePage >>> 32 );
+        HEADER_BYTES[20] = ( byte ) ( lastFreePage >>> 24 );
+        HEADER_BYTES[21] = ( byte ) ( lastFreePage >>> 16 );
+        HEADER_BYTES[22] = ( byte ) ( lastFreePage >>> 8 );
+        HEADER_BYTES[23] = ( byte ) ( lastFreePage );
 
         // Write the header on disk
-        HEADER_BUFFER.rewind();
+        HEADER_BUFFER.put( HEADER_BYTES );
+        HEADER_BUFFER.flip();
 
         LOG.debug( "Update RM header, FF : {}, LF : {}", firstFreePage, lastFreePage );
         fileChannel.write( HEADER_BUFFER, 0 );
+        HEADER_BUFFER.clear();
 
         nbUpdateRMHeader.incrementAndGet();
     }

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RevisionNameSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RevisionNameSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RevisionNameSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/RevisionNameSerializer.java Sun Oct 27 08:48:07 2013
@@ -86,6 +86,42 @@ public class RevisionNameSerializer exte
 
 
     /**
+     * A method used to deserialize a RevisionName from a byte array.
+     * 
+     * @param in The byte array containing the RevisionName
+     * @return A RevisionName instance
+     */
+    public RevisionName fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A method used to deserialize a RevisionName from a byte array.
+     * 
+     * @param in The byte array containing the RevisionName
+     * @param start the position in the byte[] we will deserialize the RevisionName from
+     * @return A RevisionName instance
+     */
+    public RevisionName fromBytes( byte[] in, int start )
+    {
+        // The buffer must be 8 bytes plus 4 bytes long (the revision is a long, and the name is a String
+        if ( ( in == null ) || ( in.length < 12 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a RevisionName from a buffer with not enough bytes" );
+        }
+
+        long revision = LongSerializer.deserialize( in, start );
+        String name = StringSerializer.deserialize( in, 8 + start );
+
+        RevisionName revisionName = new RevisionName( revision, name );
+
+        return revisionName;
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     @Override

Added: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/ValueHolder.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/ValueHolder.java?rev=1536066&view=auto
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/ValueHolder.java (added)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/managed/ValueHolder.java Sun Oct 27 08:48:07 2013
@@ -0,0 +1,1076 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.mavibot.btree.managed;
+
+
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.util.Comparator;
+import java.util.UUID;
+
+import org.apache.directory.mavibot.btree.TupleCursor;
+import org.apache.directory.mavibot.btree.ValueCursor;
+import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
+import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
+import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
+import org.apache.directory.mavibot.btree.serializer.IntSerializer;
+import org.apache.directory.mavibot.btree.util.Strings;
+
+
+/**
+ * A holder to store the Values
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @param <V> The value type
+ */
+public class ValueHolder<V> implements Cloneable
+{
+    /** The deserialized value */
+    private V[] valueArray;
+
+    /** The BTree storing multiple value, if we have moe than a threashold values */
+    private BTree<V, V> valueBtree;
+
+    /** The serialized value */
+    private byte[] raw;
+
+    /** A flag set to true if the values are stored in a BTree */
+    private boolean isSubBtree = false;
+
+    /** The RecordManager */
+    private RecordManager recordManager;
+
+    /** The Value serializer */
+    private ElementSerializer<V> valueSerializer;
+
+    /** An internal flag used when the values are not yet deserialized */
+    private boolean isRaw = true;
+
+
+    /**
+     * Creates a new instance of a ValueHolder, containing the serialized values
+     * 
+     * @param valueSerializer The Value's serializer
+     * @param raw The raw data containing the values
+     */
+    /* No qualifier */ValueHolder( RecordManager recordManager, ElementSerializer<V> valueSerializer,
+        boolean isSubBtree, int nbValues,
+        byte[] raw )
+    {
+        this.valueSerializer = valueSerializer;
+        this.recordManager = recordManager;
+        this.raw = raw;
+        this.isSubBtree = isSubBtree;
+
+        if ( nbValues < BTree.valueThresholdUp )
+        {
+            // Keep an array
+            valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), nbValues );
+        }
+        else
+        {
+            // Use a sub btree
+
+            //raw = ByteBuffer.wrap( valueSerializer.serialize( key ) );
+        }
+    }
+
+
+    /**
+     * Creates a new instance of a ValueHolder, containing the serialized values
+     * 
+     * @param valueSerializer The Value's serializer
+     * @param raw The raw data containing the values
+     */
+    /* No qualifier */ValueHolder( RecordManager recordManager, ElementSerializer<V> valueSerializer,
+        BTree<V, V> subBtree )
+    {
+        this.valueSerializer = valueSerializer;
+        this.recordManager = recordManager;
+        raw = null;
+        isRaw = false;
+        isSubBtree = true;
+        valueBtree = subBtree;
+    }
+
+
+    /**
+     * Creates a new instance of a ValueHolder, containing Values
+     * 
+     * @param valueSerializer The Value's serializer
+     * @param values The Values stored in the ValueHolder
+     */
+    /* No qualifier */ValueHolder( RecordManager recordManager, ElementSerializer<V> valueSerializer, V... values )
+    {
+        this.valueSerializer = valueSerializer;
+        this.recordManager = recordManager;
+
+        if ( values != null )
+        {
+            int nbValues = values.length;
+
+            if ( nbValues < BTree.valueThresholdUp )
+            {
+                // Keep an array
+                valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), nbValues );
+
+                try
+                {
+                    System.arraycopy( values, 0, valueArray, 0, values.length );
+                }
+                catch ( ArrayStoreException ase )
+                {
+                    ase.printStackTrace();
+                    throw ase;
+                }
+
+                // Serialize the values
+                byte[][] data = new byte[nbValues][];
+                int pos = 0;
+                int length = 0;
+
+                for ( V value : values )
+                {
+                    byte[] serializedValue = valueSerializer.serialize( value );
+
+                    data[pos++] = serializedValue;
+                    length += serializedValue.length;
+                }
+
+                raw = new byte[length];
+                pos = 0;
+
+                for ( byte[] bytes : data )
+                {
+                    System.arraycopy( bytes, 0, raw, pos, bytes.length );
+                    pos += bytes.length;
+                }
+            }
+            else
+            {
+                // Use a sub btree, now that we have reached the threshold
+                createSubTree();
+
+                // Now inject all the values into it
+                for ( V value : values )
+                {
+                    try
+                    {
+                        valueBtree.insert( value, value );
+                    }
+                    catch ( IOException e )
+                    {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+        else
+        {
+            // No value, we create an empty array
+            valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), 0 );
+
+            //raw = ByteBuffer.wrap( valueSerializer.serialize( key ) );
+        }
+
+        isRaw = false;
+    }
+
+
+    /**
+     * @return a cursor on top of the values
+     */
+    public ValueCursor<V> getCursor()
+    {
+        checkRaw();
+
+        ValueCursor<V> cursor;
+
+        if ( isSubBtree )
+        {
+            cursor = new ValueBtreeCursor();
+        }
+        else
+        {
+            cursor = new ValueArrayCursor();
+        }
+
+        return cursor;
+    }
+
+    /**
+     * A class that encapsulate the values into an array
+     */
+    private class ValueArrayCursor implements ValueCursor<V>
+    {
+        /** Store the current position in the array or in the BTree */
+        private int currentPos;
+
+
+        /**
+         * Create an instance
+         */
+        private ValueArrayCursor()
+        {
+            // Start at -1 to be positioned before the first element
+            currentPos = -1;
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean hasNext()
+        {
+            if ( valueArray == null )
+            {
+                // Load the array from the raw data
+                return false;
+            }
+            else
+            {
+                return ( valueArray != null ) && ( currentPos < valueArray.length );
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        public V next()
+        {
+            if ( valueArray == null )
+            {
+                // Deserialize the array
+                return null;
+            }
+            else
+            {
+                currentPos++;
+
+                if ( currentPos == valueArray.length )
+                {
+                    // We have reached the end of the array
+                    return null;
+                }
+                else
+                {
+                    return valueArray[currentPos];
+                }
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public boolean hasPrev() throws EndOfFileExceededException, IOException
+        {
+            return false;
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void close()
+        {
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void beforeFirst() throws IOException
+        {
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public void afterLast() throws IOException
+        {
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public V prev() throws EndOfFileExceededException, IOException
+        {
+            return null;
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int size()
+        {
+            if ( valueArray != null )
+            {
+                return valueArray.length;
+            }
+            else
+            {
+                return 0;
+            }
+        }
+    }
+
+    /**
+     * A class that encapsulate the values into an sub-btree
+     */
+    private class ValueBtreeCursor implements ValueCursor<V>
+    {
+        /** Store the current position in the array or in the BTree */
+        private TupleCursor<V, V> cursor;
+
+
+        /**
+         * Create an instance
+         */
+        private ValueBtreeCursor()
+        {
+            // Start at -1 to be positionned before the first element
+            try
+            {
+                if ( valueBtree != null )
+                {
+                    cursor = valueBtree.browse();
+                }
+            }
+            catch ( IOException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}}
+         */
+        @Override
+        public boolean hasNext()
+        {
+            if ( cursor == null )
+            {
+                return false;
+            }
+            else
+            {
+                try
+                {
+                    return cursor.hasNext();
+                }
+                catch ( EndOfFileExceededException e )
+                {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    return false;
+                }
+                catch ( IOException e )
+                {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}}
+         */
+        public V next()
+        {
+            try
+            {
+                return cursor.next().getKey();
+            }
+            catch ( EndOfFileExceededException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return null;
+            }
+            catch ( IOException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return null;
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}}
+         */
+        @Override
+        public boolean hasPrev() throws EndOfFileExceededException, IOException
+        {
+            if ( cursor == null )
+            {
+                return false;
+            }
+            else
+            {
+                try
+                {
+                    return cursor.hasPrev();
+                }
+                catch ( EndOfFileExceededException e )
+                {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    return false;
+                }
+                catch ( IOException e )
+                {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                    return false;
+                }
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}}
+         */
+        @Override
+        public void close()
+        {
+            if ( cursor != null )
+            {
+                cursor.close();
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}}
+         */
+        @Override
+        public void beforeFirst() throws IOException
+        {
+            if ( cursor != null )
+            {
+                cursor.beforeFirst();
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}}
+         */
+        @Override
+        public void afterLast() throws IOException
+        {
+            if ( cursor != null )
+            {
+                cursor.afterLast();
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}}
+         */
+        @Override
+        public V prev() throws EndOfFileExceededException, IOException
+        {
+            try
+            {
+                return cursor.prev().getKey();
+            }
+            catch ( EndOfFileExceededException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return null;
+            }
+            catch ( IOException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+                return null;
+            }
+        }
+
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int size()
+        {
+            if ( valueBtree != null )
+            {
+                return ( int ) valueBtree.getNbElems();
+            }
+            else
+            {
+                return 0;
+            }
+        }
+    }
+
+
+    /**
+     * @return the raw representation of the value holder. 
+     */
+    public byte[] getRaw()
+    {
+        if ( isRaw )
+        {
+            // We don't have to serialize the ValueHolder, it has not been changed 
+            return raw;
+        }
+        else
+        {
+            // Ok, some values have been added/modified/removed, we have to serialize the ValueHolder
+            byte[][] valueBytes = new byte[valueArray.length * 2][];
+            int length = 0;
+            int pos = 0;
+
+            for ( V value : valueArray )
+            {
+                // Serialize the value
+                byte[] bytes = valueSerializer.serialize( value );
+                length += bytes.length;
+
+                // Serialize the value's length
+                byte[] sizeBytes = IntSerializer.serialize( bytes.length );
+                length += sizeBytes.length;
+
+                // And store the two byte[]
+                valueBytes[pos++] = sizeBytes;
+                valueBytes[pos++] = bytes;
+            }
+
+            raw = new byte[length];
+            pos = 0;
+
+            for ( byte[] bytes : valueBytes )
+            {
+                System.arraycopy( bytes, 0, raw, pos, bytes.length );
+                pos += bytes.length;
+            }
+
+            return raw;
+        }
+    }
+
+
+    /**
+     * @return the isSubBtree
+     */
+    public boolean isSubBtree()
+    {
+        return isSubBtree;
+    }
+
+
+    /**
+     * @return the number of stored values
+     */
+    public int size()
+    {
+        if ( isSubBtree )
+        {
+            return ( int ) valueBtree.getNbElems();
+        }
+        else
+        {
+            return valueArray.length;
+        }
+    }
+
+
+    /**
+     * Create a new Sub-BTree to store the values.
+     */
+    private void createSubTree()
+    {
+        try
+        {
+            valueBtree = new BTree<V, V>( UUID.randomUUID().toString(), valueSerializer, valueSerializer );
+
+            try
+            {
+                recordManager.manage( valueBtree, true );
+                isSubBtree = true;
+                isRaw = false;
+                raw = null;
+            }
+            catch ( BTreeAlreadyManagedException e )
+            {
+                // should never happen
+                throw new RuntimeException( e );
+            }
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    /**
+     * Set the subBtree in the ValueHolder
+     */
+    /* No qualifier*/void setSubBtree( BTree<V, V> subBtree )
+    {
+        valueBtree = subBtree;
+        raw = null;
+        isRaw = false;
+        isSubBtree = true;
+        valueArray = null;
+    }
+
+
+    /**
+     * Add a new value in the ValueHolder
+     * 
+     * @param value The added value
+     */
+    public void add( V value )
+    {
+        checkRaw();
+
+        if ( !isSubBtree )
+        {
+            // We have to check that we have reached the threshold or not
+            if ( valueArray.length + 1 > BTree.valueThresholdUp )
+            {
+                // Ok, transform the array into a btree
+                createSubTree();
+
+                try
+                {
+                    for ( V val : valueArray )
+                    {
+                        // Here, we should insert all the values in one shot then 
+                        // write the btree on disk only once.
+                        valueBtree.insert( val, null );
+                    }
+
+                    // We can delete the array now
+                    valueArray = null;
+
+                    // And inject the new value
+                    valueBtree.insert( value, null );
+                }
+                catch ( IOException e )
+                {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+            }
+            else
+            {
+                // First check that the value is not already present in the ValueHolder
+                int pos = findPos( value );
+
+                if ( pos >= 0 )
+                {
+                    // The value exists : nothing to do
+                    return;
+                }
+
+                // Ok, we just have to insert the new element at the right position
+                // We transform the position to a positive value 
+                pos = -( pos + 1 );
+                // First, copy the array
+                V[] newValueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), valueArray.length + 1 );
+
+                System.arraycopy( valueArray, 0, newValueArray, 0, pos );
+                newValueArray[pos] = value;
+                System.arraycopy( valueArray, pos, newValueArray, pos + 1, valueArray.length - pos );
+
+                // And switch the arrays
+                valueArray = newValueArray;
+            }
+        }
+        else
+        {
+            try
+            {
+                valueBtree.insert( value, null );
+            }
+            catch ( IOException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+    }
+
+
+    /**
+     * Add a new value in the ValueHolder
+     * 
+     * @param value The added value
+     */
+    public void remove( V value )
+    {
+        checkRaw();
+
+        if ( !isSubBtree )
+        {
+            // First check that the value is not already present in the ValueHolder
+            int pos = findPos( value );
+
+            if ( pos < 0 )
+            {
+                // The value does not exists : nothing to do
+                return;
+            }
+
+            // Ok, we just have to delete the new element at the right position
+            // First, copy the array
+            V[] newValueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), valueArray.length + 1 );
+
+            System.arraycopy( valueArray, 0, newValueArray, 0, pos );
+            System.arraycopy( valueArray, pos + 1, newValueArray, pos, valueArray.length - pos - 1 );
+
+            // And switch the arrays
+            valueArray = newValueArray;
+        }
+        else
+        {
+            try
+            {
+                valueBtree.delete( value );
+            }
+            catch ( IOException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+    }
+
+
+    /**
+     * Add a new value in the ValueHolder
+     * 
+     * @param value The added value
+     */
+    public boolean contains( V value )
+    {
+        checkRaw();
+
+        if ( isSubBtree )
+        {
+            try
+            {
+                return valueBtree.hasKey( value );
+            }
+            catch ( IOException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+        else
+        {
+            if ( valueArray.length == 0 )
+            {
+                return false;
+            }
+
+            // Do a search using dichotomy
+            return findPos( value ) >= 0;
+        }
+
+        return true;
+    }
+
+
+    /**
+     * Find the position of a given value in the array, or the position where we
+     * would insert the element (in this case, the position will be negative).
+     * As we use a 0-based array, the negative position for 0 is -1.
+     * -1 means the element can be added in position 0
+     * -2 means the element can be added in position 1
+     * ... 
+     */
+    private int findPos( V value )
+    {
+        if ( valueArray.length == 0 )
+        {
+            return -1;
+        }
+
+        // Do a search using dichotomy
+        int pivot = valueArray.length / 2;
+        int low = 0;
+        int high = valueArray.length - 1;
+        Comparator<V> comparator = valueSerializer.getComparator();
+
+        while ( high > low )
+        {
+            switch ( high - low )
+            {
+                case 1:
+                    // We have 2 elements
+                    int result = comparator.compare( value, valueArray[pivot] );
+
+                    if ( result == 0 )
+                    {
+                        return pivot;
+                    }
+
+                    if ( result < 0 )
+                    {
+                        if ( pivot == low )
+                        {
+                            return -( low + 1 );
+                        }
+                        else
+                        {
+                            result = comparator.compare( value, valueArray[low] );
+
+                            if ( result == 0 )
+                            {
+                                return low;
+                            }
+
+                            if ( result < 0 )
+                            {
+                                return -( low + 1 );
+                            }
+                            else
+                            {
+                                return -( low + 2 );
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if ( pivot == high )
+                        {
+                            return -( high + 2 );
+                        }
+                        else
+                        {
+                            result = comparator.compare( value, valueArray[high] );
+
+                            if ( result == 0 )
+                            {
+                                return high;
+                            }
+
+                            if ( result < 0 )
+                            {
+                                return -( high + 1 );
+                            }
+                            else
+                            {
+                                return -( high + 2 );
+                            }
+                        }
+                    }
+
+                default:
+                    // We have 3 elements
+                    result = comparator.compare( value, valueArray[pivot] );
+
+                    if ( result == 0 )
+                    {
+                        return pivot;
+                    }
+
+                    if ( result < 0 )
+                    {
+                        high = pivot - 1;
+                    }
+                    else
+                    {
+                        low = pivot + 1;
+                    }
+
+                    pivot = ( high + low ) / 2;
+
+                    continue;
+            }
+        }
+
+        int result = comparator.compare( value, valueArray[pivot] );
+
+        if ( result == 0 )
+        {
+            return pivot;
+        }
+
+        if ( result < 0 )
+        {
+            return -( pivot + 1 );
+        }
+        else
+        {
+            return -( pivot + 2 );
+        }
+    }
+
+
+    /**
+     * Create a clone of this instance
+     */
+    public ValueHolder<V> clone() throws CloneNotSupportedException
+    {
+        ValueHolder<V> copy = ( ValueHolder<V> ) super.clone();
+
+        //copy the valueArray if it's not null
+        // We don't clone the BTree, as we will create new revisions when 
+        //modifying it
+        if ( ( !isSubBtree ) && ( valueArray != null ) )
+        {
+            copy.valueArray = ( V[] ) Array.newInstance( valueSerializer.getType(), valueArray.length );
+            System.arraycopy( valueArray, 0, copy.valueArray, 0, valueArray.length );
+        }
+
+        return copy;
+    }
+
+
+    /**
+     * Check if we haven't yet deserialized the values, and if so, do it
+     */
+    private void checkRaw()
+    {
+        if ( isRaw )
+        {
+            // We haven't yet deserialized the values. Let's do it now
+            if ( isSubBtree )
+            {
+                // This is a sub BTree, we have to read the tree from the offsets
+
+            }
+            else
+            {
+                // We have to deserialize the array of values
+                int index = 0;
+                int pos = 0;
+
+                while ( pos < raw.length )
+                {
+                    try
+                    {
+                        int size = IntSerializer.deserialize( raw, pos );
+                        pos += 4;
+                        V value = valueSerializer.fromBytes( raw, pos );
+                        pos += size;
+                        valueArray[index++] = value;
+                    }
+                    catch ( IOException e )
+                    {
+                        System.out.println( Strings.dumpBytes( raw ) );
+                    }
+                }
+            }
+
+            isRaw = false;
+        }
+    }
+
+
+    /**
+     * @return The sub-btree offset
+     */
+    /* No qualifier */long getOffset()
+    {
+        if ( isSubBtree )
+        {
+            return valueBtree.getBtreeOffset();
+        }
+        else
+        {
+            return -1L;
+        }
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "ValueHolder[" ).append( valueSerializer.getClass().getSimpleName() );
+
+        if ( isRaw )
+        {
+            sb.append( ", isRaw[" ).append( raw.length ).append( "]" );
+        }
+        else
+        {
+            if ( isSubBtree )
+            {
+                sb.append( ", SubBTree" );
+            }
+            else
+            {
+                sb.append( ", array{" );
+
+                if ( valueArray == null )
+                {
+                    sb.append( "}" );
+                }
+                else
+                {
+                    boolean isFirst = true;
+
+                    for ( V value : valueArray )
+                    {
+                        if ( isFirst )
+                        {
+                            isFirst = false;
+                        }
+                        else
+                        {
+                            sb.append( "/" );
+                        }
+
+                        sb.append( value );
+                    }
+
+                    sb.append( "}" );
+                }
+            }
+        }
+
+        sb.append( "]" );
+
+        return sb.toString();
+    }
+}

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/BTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/BTree.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/BTree.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/BTree.java Sun Oct 27 08:48:07 2013
@@ -40,10 +40,10 @@ import net.sf.ehcache.config.CacheConfig
 
 import org.apache.directory.mavibot.btree.Addition;
 import org.apache.directory.mavibot.btree.BTreeHeader;
-import org.apache.directory.mavibot.btree.Cursor;
 import org.apache.directory.mavibot.btree.Deletion;
 import org.apache.directory.mavibot.btree.Modification;
 import org.apache.directory.mavibot.btree.Tuple;
+import org.apache.directory.mavibot.btree.TupleCursor;
 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
 import org.apache.directory.mavibot.btree.serializer.BufferHandler;
 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
@@ -935,14 +935,14 @@ public class BTree<K, V> implements Clos
      * @return A cursor on the btree
      * @throws IOException
      */
-    public Cursor<K, V> browse() throws IOException
+    public TupleCursor<K, V> browse() throws IOException
     {
         Transaction<K, V> transaction = beginReadTransaction();
 
         // Fetch the root page for this revision
         LinkedList<ParentPos<K, V>> stack = new LinkedList<ParentPos<K, V>>();
 
-        Cursor<K, V> cursor = rootPage.browse( transaction, stack );
+        TupleCursor<K, V> cursor = rootPage.browse( transaction, stack );
 
         return cursor;
     }
@@ -956,7 +956,7 @@ public class BTree<K, V> implements Clos
      * @throws IOException If we had an issue while fetching data from the disk
      * @throws KeyNotFoundException If the key is not found in the BTree
      */
-    public Cursor<K, V> browse( long revision ) throws IOException, KeyNotFoundException
+    public TupleCursor<K, V> browse( long revision ) throws IOException, KeyNotFoundException
     {
         Transaction<K, V> transaction = beginReadTransaction();
 
@@ -965,7 +965,7 @@ public class BTree<K, V> implements Clos
 
         // And get the cursor
         LinkedList<ParentPos<K, V>> stack = new LinkedList<ParentPos<K, V>>();
-        Cursor<K, V> cursor = revisionRootPage.browse( transaction, stack );
+        TupleCursor<K, V> cursor = revisionRootPage.browse( transaction, stack );
 
         return cursor;
     }
@@ -979,12 +979,12 @@ public class BTree<K, V> implements Clos
      * @return A cursor on the btree
      * @throws IOException
      */
-    public Cursor<K, V> browseFrom( K key ) throws IOException
+    public TupleCursor<K, V> browseFrom( K key ) throws IOException
     {
         Transaction<K, V> transaction = beginReadTransaction();
 
         // Fetch the root page for this revision
-        Cursor<K, V> cursor = rootPage.browse( key, transaction, new LinkedList<ParentPos<K, V>>() );
+        TupleCursor<K, V> cursor = rootPage.browse( key, transaction, new LinkedList<ParentPos<K, V>>() );
 
         return cursor;
     }
@@ -1000,7 +1000,7 @@ public class BTree<K, V> implements Clos
      * @throws IOException If wxe had an issue reading the BTree from disk
      * @throws KeyNotFoundException  If we can't find a rootPage for this revision
      */
-    public Cursor<K, V> browseFrom( long revision, K key ) throws IOException, KeyNotFoundException
+    public TupleCursor<K, V> browseFrom( long revision, K key ) throws IOException, KeyNotFoundException
     {
         Transaction<K, V> transaction = beginReadTransaction();
 
@@ -1009,7 +1009,7 @@ public class BTree<K, V> implements Clos
 
         // And get the cursor
         LinkedList<ParentPos<K, V>> stack = new LinkedList<ParentPos<K, V>>();
-        Cursor<K, V> cursor = revisionRootPage.browse( key, transaction, stack );
+        TupleCursor<K, V> cursor = revisionRootPage.browse( key, transaction, stack );
 
         return cursor;
     }
@@ -1222,7 +1222,7 @@ public class BTree<K, V> implements Clos
         // Create a buffer containing 200 4Kb pages (around 1Mb)
         ByteBuffer bb = ByteBuffer.allocateDirect( writeBufferSize );
 
-        Cursor<K, V> cursor = browse();
+        TupleCursor<K, V> cursor = browse();
 
         if ( keySerializer == null )
         {

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/CursorImpl.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/CursorImpl.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/CursorImpl.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/CursorImpl.java Sun Oct 27 08:48:07 2013
@@ -28,8 +28,8 @@ import java.io.IOException;
 import java.util.LinkedList;
 import java.util.NoSuchElementException;
 
-import org.apache.directory.mavibot.btree.Cursor;
 import org.apache.directory.mavibot.btree.Tuple;
+import org.apache.directory.mavibot.btree.TupleCursor;
 import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
 
 
@@ -44,7 +44,7 @@ import org.apache.directory.mavibot.btre
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class CursorImpl<K, V> implements Cursor<K, V>
+public class CursorImpl<K, V> implements TupleCursor<K, V>
 {
     /** The transaction used for this cursor */
     private Transaction<K, V> transaction;

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/Node.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/Node.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/Node.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/memory/Node.java Sun Oct 27 08:48:07 2013
@@ -884,7 +884,6 @@ import org.apache.directory.mavibot.btre
             if ( page == null )
             {
                 System.out.println( "Page is null for pos = " + pos + ", children = " + children[pos] );
-                System.out.println( "Key = " + key );
             }
 
             return page.hasKey( key );

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/AbstractElementSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/AbstractElementSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/AbstractElementSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/AbstractElementSerializer.java Sun Oct 27 08:48:07 2013
@@ -20,6 +20,8 @@
 package org.apache.directory.mavibot.btree.serializer;
 
 
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.util.Comparator;
@@ -60,9 +62,18 @@ public abstract class AbstractElementSer
         {
             Type[] argumentTypes = ( ( ParameterizedType ) types[0] ).getActualTypeArguments();
 
-            if ( ( argumentTypes != null ) && ( argumentTypes.length > 0 ) && ( argumentTypes[0] instanceof Class<?> ) )
+            if ( ( argumentTypes != null ) && ( argumentTypes.length > 0 ) )
             {
-                type = ( Class<?> ) argumentTypes[0];
+                if ( argumentTypes[0] instanceof Class<?> )
+                {
+                    type = ( Class<?> ) argumentTypes[0];
+                }
+                else if ( argumentTypes[0] instanceof GenericArrayType )
+                {
+                    Class<?> clazz = ( Class<?> ) ( ( GenericArrayType ) argumentTypes[0] ).getGenericComponentType();
+
+                    type = Array.newInstance( clazz, 0 ).getClass();
+                }
             }
         }
     }

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/BooleanSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/BooleanSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/BooleanSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/BooleanSerializer.java Sun Oct 27 08:48:07 2013
@@ -114,6 +114,36 @@ public class BooleanSerializer extends A
 
 
     /**
+     * A method used to deserialize a Boolean from a byte array.
+     * 
+     * @param in The byte array containing the boolean
+     * @return A boolean
+     */
+    public Boolean fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A method used to deserialize a Boolean from a byte array.
+     * 
+     * @param in The byte array containing the boolean
+     * @param start the position in the byte[] we will deserialize the boolean from
+     * @return A boolean
+     */
+    public Boolean fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length < 1 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a Boolean from a buffer with not enough bytes" );
+        }
+
+        return in[start] == 0x01;
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Boolean deserialize( ByteBuffer buffer ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteArraySerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteArraySerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteArraySerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteArraySerializer.java Sun Oct 27 08:48:07 2013
@@ -221,6 +221,73 @@ public class ByteArraySerializer extends
 
 
     /**
+     * A method used to deserialize a byte array from a byte array.
+     * 
+     * @param in The byte array containing the byte array
+     * @return A byte[]
+     */
+    public byte[] fromBytes( byte[] in )
+    {
+        if ( ( in == null ) || ( in.length < 4 ) )
+        {
+            throw new RuntimeException( "Cannot extract a byte[] from a buffer with not enough bytes" );
+        }
+
+        int len = IntSerializer.deserialize( in );
+
+        switch ( len )
+        {
+            case 0:
+                return new byte[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                byte[] result = new byte[len];
+                System.arraycopy( in, 4, result, 0, len );
+
+                return result;
+        }
+    }
+
+
+    /**
+     * A method used to deserialize a byte array from a byte array.
+     * 
+     * @param in The byte array containing the byte array
+     * @param start the position in the byte[] we will deserialize the byte[] from
+     * @return A byte[]
+     */
+    public byte[] fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length < 4 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a byte[] from a buffer with not enough bytes" );
+        }
+
+        int len = IntSerializer.deserialize( in, start );
+
+        switch ( len )
+        {
+            case 0:
+                return new byte[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                byte[] result = new byte[len];
+                System.arraycopy( in, 4 + start, result, 0, len );
+
+                return result;
+        }
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public byte[] deserialize( BufferHandler bufferHandler ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ByteSerializer.java Sun Oct 27 08:48:07 2013
@@ -112,6 +112,34 @@ public class ByteSerializer extends Abst
 
 
     /**
+     * A method used to deserialize a Byte from a byte array.
+     * @param in The byte array containing the Byte
+     * @return A Byte
+     */
+    public Byte fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A method used to deserialize a Byte from a byte array.
+     * @param in The byte array containing the Byte
+     * @param start the position in the byte[] we will deserialize the byte from
+     * @return A Byte
+     */
+    public Byte fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length < 1 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a Byte from a buffer with not enough bytes" );
+        }
+
+        return in[start];
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Byte deserialize( ByteBuffer buffer ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharArraySerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharArraySerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharArraySerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharArraySerializer.java Sun Oct 27 08:48:07 2013
@@ -137,6 +137,82 @@ public class CharArraySerializer extends
 
 
     /**
+     * A method used to deserialize a char array from a byte array.
+     * 
+     * @param in The byte array containing the char array
+     * @return A char[]
+     */
+    public char[] fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length - start < 4 ) )
+        {
+            throw new RuntimeException( "Cannot extract a byte[] from a buffer with not enough bytes" );
+        }
+
+        int len = IntSerializer.deserialize( in, start );
+
+        switch ( len )
+        {
+            case 0:
+                return new char[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                char[] result = new char[len];
+
+                for ( int i = 4; i < len * 2 + 4; i += 2 )
+                {
+                    result[i] = Character.valueOf( ( char ) ( ( in[i] << 8 ) +
+                        ( in[i + 1] & 0xFF ) ) );
+                }
+
+                return result;
+        }
+    }
+
+
+    /**
+     * A method used to deserialize a char array from a byte array.
+     * 
+     * @param in The byte array containing the char array
+     * @return A char[]
+     */
+    public char[] fromBytes( byte[] in )
+    {
+        if ( ( in == null ) || ( in.length < 4 ) )
+        {
+            throw new RuntimeException( "Cannot extract a byte[] from a buffer with not enough bytes" );
+        }
+
+        int len = IntSerializer.deserialize( in );
+
+        switch ( len )
+        {
+            case 0:
+                return new char[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                char[] result = new char[len];
+
+                for ( int i = 4; i < len * 2 + 4; i += 2 )
+                {
+                    result[i] = Character.valueOf( ( char ) ( ( in[i] << 8 ) +
+                        ( in[i + 1] & 0xFF ) ) );
+                }
+
+                return result;
+        }
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public char[] deserialize( BufferHandler bufferHandler ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/CharSerializer.java Sun Oct 27 08:48:07 2013
@@ -114,6 +114,35 @@ public class CharSerializer extends Abst
 
 
     /**
+     * A method used to deserialize a Character from a byte array.
+     * @param in The byte array containing the Character
+     * @return A Character
+     */
+    public Character fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A static method used to deserialize a Character from a byte array.
+     * @param in The byte array containing the Character
+    * @param start the position in the byte[] we will deserialize the char from
+     * @return A Character
+     */
+    public Character fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length < 2 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a Character from a buffer with not enough bytes" );
+        }
+
+        return Character.valueOf( ( char ) ( ( in[start] << 8 ) +
+            ( in[start + 1] & 0xFF ) ) );
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Character deserialize( ByteBuffer buffer ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ElementSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ElementSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ElementSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ElementSerializer.java Sun Oct 27 08:48:07 2013
@@ -64,6 +64,26 @@ public interface ElementSerializer<T>
 
 
     /**
+     * Deserialize an element from a byte[]
+     * 
+     * @param buffer The incoming byte[]
+     * @return The deserialized element
+     * @throws IOException If the deserialization failed
+     */
+    T fromBytes( byte[] buffer ) throws IOException;
+
+
+    /**
+     * Deserialize an element from a byte[]
+     * 
+     * @param buffer The incoming byte[]
+     * @return The deserialized element
+     * @throws IOException If the deserialization failed
+     */
+    T fromBytes( byte[] buffer, int pos ) throws IOException;
+
+
+    /**
      * Returns the comparison of two types. <br/>
      * <ul>
      * <li>If type1 < type2, return -1</li>

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/IntSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/IntSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/IntSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/IntSerializer.java Sun Oct 27 08:48:07 2013
@@ -74,6 +74,37 @@ public class IntSerializer extends Abstr
 
 
     /**
+     * A method used to deserialize an Integer from a byte array.
+     * @param in The byte array containing the Integer
+     * @return An Integer
+     */
+    public Integer fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A method used to deserialize an Integer from a byte array.
+     * @param in The byte array containing the Integer
+     * @param start the position in the byte[] we will deserialize the int from
+     * @return An Integer
+     */
+    public Integer fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length < 4 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a Integer from a buffer with not enough bytes" );
+        }
+
+        return ( in[start] << 24 ) +
+            ( ( in[start + 1] & 0xFF ) << 16 ) +
+            ( ( in[start + 2] & 0xFF ) << 8 ) +
+            ( in[start + 3] & 0xFF );
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Integer deserialize( ByteBuffer buffer ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongArraySerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongArraySerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongArraySerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongArraySerializer.java Sun Oct 27 08:48:07 2013
@@ -256,4 +256,62 @@ public class LongArraySerializer extends
             }
         }
     }
+
+
+    @Override
+    public long[] fromBytes( byte[] buffer ) throws IOException
+    {
+        int len = IntSerializer.deserialize( buffer );
+        int pos = 4;
+
+        switch ( len )
+        {
+            case 0:
+                return new long[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                long[] longs = new long[len];
+
+                for ( int i = 0; i < len; i++ )
+                {
+                    longs[i] = LongSerializer.deserialize( buffer, pos );
+                    pos += 8;
+                }
+
+                return longs;
+        }
+    }
+
+
+    @Override
+    public long[] fromBytes( byte[] buffer, int pos ) throws IOException
+    {
+        int newPos = pos;
+        int len = IntSerializer.deserialize( buffer, newPos );
+
+        switch ( len )
+        {
+            case 0:
+                return new long[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                long[] longs = new long[len];
+
+                for ( int i = 0; i < len; i++ )
+                {
+                    longs[i] = LongSerializer.deserialize( buffer, newPos );
+                    newPos += 8;
+                }
+
+                return longs;
+        }
+    }
 }

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/LongSerializer.java Sun Oct 27 08:48:07 2013
@@ -127,6 +127,44 @@ public class LongSerializer extends Abst
 
 
     /**
+     * A method used to deserialize a Long from a byte array.
+     * @param in The byte array containing the Long
+     * @param start the position in the byte[] we will deserialize the long from
+     * @return A Long
+     */
+    public Long fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A method used to deserialize an Integer from a byte array.
+     * @param in The byte array containing the Integer
+     * @param start the position in the byte[] we will deserialize the long from
+     * @return An Integer
+     */
+    public Long fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length < 8 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a Long from a buffer with not enough bytes" );
+        }
+
+        long result = ( ( long ) in[start] << 56 ) +
+            ( ( in[start + 1] & 0xFFL ) << 48 ) +
+            ( ( in[start + 2] & 0xFFL ) << 40 ) +
+            ( ( in[start + 3] & 0xFFL ) << 32 ) +
+            ( ( in[start + 4] & 0xFFL ) << 24 ) +
+            ( ( in[start + 5] & 0xFFL ) << 16 ) +
+            ( ( in[start + 6] & 0xFFL ) << 8 ) +
+            ( in[start + 7] & 0xFFL );
+
+        return result;
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Long deserialize( BufferHandler bufferHandler ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ShortSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ShortSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ShortSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/ShortSerializer.java Sun Oct 27 08:48:07 2013
@@ -113,6 +113,34 @@ public class ShortSerializer extends Abs
 
 
     /**
+     * A method used to deserialize a Short from a byte array.
+     * @param in The byte array containing the Short
+     * @return A Short
+     */
+    public Short fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A method used to deserialize a Short from a byte array.
+     * @param in The byte array containing the Short
+     * @param start the position in the byte[] we will deserialize the short from
+     * @return A Short
+     */
+    public Short fromBytes( byte[] in, int start )
+    {
+        if ( ( in == null ) || ( in.length < 2 + start ) )
+        {
+            throw new RuntimeException( "Cannot extract a Short from a buffer with not enough bytes" );
+        }
+
+        return ( short ) ( ( in[start] << 8 ) + ( in[start + 1] & 0xFF ) );
+    }
+
+
+    /**
      * {@inheritDoc}
      */
     public Short deserialize( ByteBuffer buffer ) throws IOException

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/StringSerializer.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/StringSerializer.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/StringSerializer.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/serializer/StringSerializer.java Sun Oct 27 08:48:07 2013
@@ -92,6 +92,40 @@ public class StringSerializer extends Ab
 
 
     /**
+     * A method used to deserialize a String from a byte array.
+     * @param in The byte array containing the String
+     * @return A String
+     */
+    public String fromBytes( byte[] in )
+    {
+        return deserialize( in, 0 );
+    }
+
+
+    /**
+     * A method used to deserialize a String from a byte array.
+     * @param in The byte array containing the String
+     * @return A String
+     */
+    public String fromBytes( byte[] in, int start )
+    {
+        int length = IntSerializer.deserialize( in, start );
+
+        if ( length == 0xFFFFFFFF )
+        {
+            return null;
+        }
+
+        if ( in.length < length + start )
+        {
+            throw new RuntimeException( "Cannot extract a String from a buffer with not enough bytes" );
+        }
+
+        return Strings.utf8ToString( in, start + 4, length );
+    }
+
+
+    /**
      * Serialize a String. We store the length on 4 bytes, then the String
      * 
      * @param buffer the Buffer that will contain the serialized value

Modified: directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerFreePageTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerFreePageTest.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerFreePageTest.java (original)
+++ directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerFreePageTest.java Sun Oct 27 08:48:07 2013
@@ -29,6 +29,7 @@ import java.util.Set;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.directory.mavibot.btree.Tuple;
+import org.apache.directory.mavibot.btree.TupleCursor;
 import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
 import org.apache.directory.mavibot.btree.serializer.LongSerializer;
 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
@@ -166,7 +167,7 @@ public class RecordManagerFreePageTest
 
         assertTrue( nbElems == btree.getNbElems() );
 
-        CursorImpl<Long, String> cursor = btree.browse();
+        TupleCursor<Long, String> cursor = btree.browse();
 
         long i = 0;
         while ( cursor.hasNext() )

Modified: directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerTest.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerTest.java (original)
+++ directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/managed/RecordManagerTest.java Sun Oct 27 08:48:07 2013
@@ -35,6 +35,7 @@ import java.util.Set;
 import java.util.UUID;
 
 import org.apache.directory.mavibot.btree.Tuple;
+import org.apache.directory.mavibot.btree.ValueCursor;
 import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
 import org.apache.directory.mavibot.btree.serializer.LongSerializer;
@@ -845,28 +846,13 @@ public class RecordManagerTest
 
         dupsTree = recordManager1.getManagedTree( name );
 
-        //        Cursor<Long, String> cursor1 = dupsTree.browse();
-        //        while( cursor1.hasNext() )
-        //        {
-        //            System.out.println( cursor1.next() );
-        //        }
-        //        cursor1.close();
-
         for ( long i = 0; i < numKeys; i++ )
         {
-            DuplicateKeyVal<String> dupVal = dupsTree.getValues( i );
-            //            Cursor<String, String> cursor = values.browse();
-            //            while( cursor.hasNext() )
-            //            {
-            //                System.out.println( cursor.next() );
-            //            }
-            //            cursor.close();
-
-            BTree<String, String> values = dupVal.getSubTree();
+            ValueCursor<String> values = dupsTree.getValues( i );
 
             for ( int k = 0; k < pageSize + 1; k++ )
             {
-                assertTrue( values.hasKey( String.valueOf( k ) ) );
+                assertTrue( values.next().equals( String.valueOf( k ) ) );
             }
         }
     }

Modified: directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/memory/BTreeBuilderTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/memory/BTreeBuilderTest.java?rev=1536066&r1=1536065&r2=1536066&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/memory/BTreeBuilderTest.java (original)
+++ directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/memory/BTreeBuilderTest.java Sun Oct 27 08:48:07 2013
@@ -27,8 +27,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.directory.mavibot.btree.Cursor;
 import org.apache.directory.mavibot.btree.Tuple;
+import org.apache.directory.mavibot.btree.TupleCursor;
 import org.apache.directory.mavibot.btree.serializer.IntSerializer;
 import org.junit.Test;
 
@@ -62,8 +62,9 @@ public class BTreeBuilderTest
 
         assertEquals( 1, btree.rootPage.findLeftMost().getKey().intValue() );
 
-        Cursor<Integer, Integer> cursor = btree.browse();
+        TupleCursor<Integer, Integer> cursor = btree.browse();
         int i = 0;
+
         while ( cursor.hasNext() )
         {
             Tuple<Integer, Integer> expected = sortedTuple.get( i++ );



Mime
View raw message