You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@labs.apache.org by ka...@apache.org on 2013/04/21 19:58:25 UTC

svn commit: r1470325 [2/3] - in /labs/mavibot/trunk: ./ mavibot/src/main/java/org/apache/mavibot/btree/ mavibot/src/main/java/org/apache/mavibot/btree/comparator/ mavibot/src/main/java/org/apache/mavibot/btree/serializer/ mavibot/src/main/java/org/apac...

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Leaf.java Sun Apr 21 17:58:23 2013
@@ -26,6 +26,7 @@ import java.util.LinkedList;
 
 import org.apache.mavibot.btree.exception.EndOfFileExceededException;
 import org.apache.mavibot.btree.exception.KeyNotFoundException;
+import static org.apache.mavibot.btree.InternalUtil.*;
 
 
 /**
@@ -36,14 +37,16 @@ import org.apache.mavibot.btree.exceptio
  *
  * @author <a href="mailto:labs@labs.apache.org">Mavibot labs Project</a>
  */
-public class Leaf<K, V> extends AbstractPage<K, V>
+/* No qualifier */class Leaf<K, V> extends AbstractPage<K, V>
 {
     /** Values associated with keys */
     protected ElementHolder<V, K, V>[] values;
 
 
     /**
-     * Empty constructor
+     * Constructor used to create a new Leaf when we read it from a file.
+     * 
+     * @param btree The BTree this page belongs to.
      */
     /* No qualifier */Leaf( BTree<K, V> btree )
     {
@@ -53,6 +56,10 @@ public class Leaf<K, V> extends Abstract
 
     /**
      * Internal constructor used to create Page instance used when a page is being copied or overflow
+     * 
+     * @param btree The BTree this page belongs to.
+     * @param revision The page revision
+     * @param nbElems The number of elements this page will contain
      */
     @SuppressWarnings("unchecked")
     // Cannot create an array of generic objects
@@ -60,13 +67,20 @@ public class Leaf<K, V> extends Abstract
     {
         super( btree, revision, nbElems );
 
-        this.values = ( MemoryHolder<K, V>[] ) Array.newInstance( MemoryHolder.class, nbElems );
+        if ( btree.isAllowDuplicates() )
+        {
+            this.values = ( DuplicateKeyMemoryHolder<K, V>[] ) Array.newInstance( DuplicateKeyMemoryHolder.class,
+                nbElems );
+        }
+        else
+        {
+            this.values = ( MemoryHolder<K, V>[] ) Array.newInstance( MemoryHolder.class, nbElems );
+        }
     }
 
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
      */
     public InsertResult<K, V> insert( long revision, K key, V value ) throws IOException
     {
@@ -109,12 +123,10 @@ public class Leaf<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
     @SuppressWarnings("unchecked")
-    public DeleteResult<K, V> delete( long revision, K key, Page<K, V> parent, int parentPos )
-        throws EndOfFileExceededException, IOException
+    public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
+        throws IOException
     {
         // Check that the leaf is not empty
         if ( nbElems == 0 )
@@ -132,17 +144,85 @@ public class Leaf<K, V> extends Abstract
             return NotPresentResult.NOT_PRESENT;
         }
 
+        // Get the removed element
+        Tuple<K, V> removedElement = null;
+
+        // flag to detect if a key was completely removed
+        boolean keyRemoved = false;
+
         int index = -( pos + 1 );
 
+        if ( btree.isAllowDuplicates() )
+        {
+            if ( value == null )
+                ;
+            BTree<V, V> dups = ( BTree<V, V> ) values[index].getValue( btree );
+
+            if ( dups.hasKey( value ) )
+            {
+                dups.delete( value );
+
+                if ( dups.getNbElems() == 0 )
+                {
+                    keyRemoved = true;
+                }
+
+                removedElement = new Tuple<K, V>( keys[index], value ); // we deleted only one value (even if it is from a tree of size 1)
+            }
+            else if ( value == null ) // this is a case to delete entire <K,dupsTree> 
+            {
+                removedElement = new Tuple<K, V>( keys[index], ( V ) dups ); // the entire tree was removed so pass it as the value
+                keyRemoved = true;
+            }
+            else
+            // value is not found
+            {
+                return NotPresentResult.NOT_PRESENT;
+            }
+        }
+        else
+        {
+            V existing = values[index].getValue( btree );
+
+            if ( ( ( existing == null ) && ( value == null ) ) || ( value == null ) )
+            {
+                removedElement = new Tuple<K, V>( keys[index], existing );
+                keyRemoved = true;
+            }
+            else if ( btree.getValueSerializer().compare( value, existing ) == 0 )
+            {
+                removedElement = new Tuple<K, V>( keys[index], value );
+                keyRemoved = true;
+            }
+            else
+            {
+                return NotPresentResult.NOT_PRESENT;
+            }
+        }
+
+        Leaf<K, V> newLeaf = null;
+
+        if ( keyRemoved )
+        {
+            newLeaf = new Leaf<K, V>( btree, revision, nbElems - 1 );
+        }
+        else
+        {
+            newLeaf = new Leaf<K, V>( btree, revision, nbElems );
+        }
+
+        // Create the result
+        DeleteResult<K, V> defaultResult = new RemoveResult<K, V>( newLeaf, removedElement );
+
         // If the parent is null, then this page is the root page.
         if ( parent == null )
         {
             // Just remove the entry if it's present
-            DeleteResult<K, V> result = removeElement( revision, index );
+            copyAfterRemovingElement( keyRemoved, newLeaf, index );
 
-            return result;
+            return defaultResult;
         }
-        else
+        else if ( keyRemoved )
         {
             // The current page is not the root. Check if the leaf has more than N/2
             // elements
@@ -160,7 +240,8 @@ public class Leaf<K, V> extends Abstract
                 if ( sibling.getNbElems() == halfSize )
                 {
                     // We will merge the current page with its sibling
-                    DeleteResult<K, V> result = mergeWithSibling( revision, sibling, ( siblingPos < parentPos ), index );
+                    DeleteResult<K, V> result = mergeWithSibling( removedElement, revision, sibling,
+                        ( siblingPos < parentPos ), index );
 
                     return result;
                 }
@@ -169,14 +250,14 @@ public class Leaf<K, V> extends Abstract
                     // We can borrow the element from the left sibling
                     if ( siblingPos < parentPos )
                     {
-                        DeleteResult<K, V> result = borrowFromLeft( revision, sibling, index );
+                        DeleteResult<K, V> result = borrowFromLeft( removedElement, revision, sibling, index );
 
                         return result;
                     }
                     else
                     {
                         // Borrow from the right sibling
-                        DeleteResult<K, V> result = borrowFromRight( revision, sibling, index );
+                        DeleteResult<K, V> result = borrowFromRight( removedElement, revision, sibling, index );
 
                         return result;
                     }
@@ -188,32 +269,33 @@ public class Leaf<K, V> extends Abstract
                 // We simply remove the element from the page, and if it was the leftmost,
                 // we return the new pivot (it will replace any instance of the removed
                 // key in its parents)
-                DeleteResult<K, V> result = removeElement( revision, index );
+                copyAfterRemovingElement( keyRemoved, newLeaf, index );
 
-                return result;
+                return defaultResult;
             }
         }
+
+        return defaultResult;
     }
 
 
     /**
-     * Merge the sibling with the current leaf, after having removed the element in the page.
+     * Merges the sibling with the current leaf, after having removed the element in the page.
      * 
      * @param revision The new revision
      * @param sibling The sibling we will merge with
      * @param isLeft Tells if the sibling is on the left or on the right
      * @param pos The position of the removed element
      * @return The new created leaf containing the sibling and the old page.
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page
      */
-    private DeleteResult<K, V> mergeWithSibling( long revision, Leaf<K, V> sibling, boolean isLeft, int pos )
+    private DeleteResult<K, V> mergeWithSibling( Tuple<K, V> removedElement, long revision, Leaf<K, V> sibling,
+        boolean isLeft, int pos )
         throws EndOfFileExceededException, IOException
     {
         // Create the new page. It will contain N - 1 elements (the maximum number)
         // as we merge two pages that contain N/2 elements minus the one we remove
         Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, btree.getPageSize() - 1 );
-        Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos], values[pos].getValue( btree ) );
 
         if ( isLeft )
         {
@@ -255,7 +337,7 @@ public class Leaf<K, V> extends Abstract
 
 
     /**
-     * Borrow an element from the left sibling, creating a new sibling with one
+     * Borrows an element from the left sibling, creating a new sibling with one
      * less element and creating a new page where the element to remove has been
      * deleted and the borrowed element added on the left.
      * 
@@ -263,11 +345,10 @@ public class Leaf<K, V> extends Abstract
      * @param sibling The left sibling
      * @param pos The position of the element to remove
      * @return The resulting pages
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page 
      */
-    private DeleteResult<K, V> borrowFromLeft( long revision, Leaf<K, V> sibling, int pos )
-        throws EndOfFileExceededException, IOException
+    private DeleteResult<K, V> borrowFromLeft( Tuple<K, V> removedElement, long revision, Leaf<K, V> sibling, int pos )
+        throws IOException
     {
         // The sibling is on the left, borrow the rightmost element
         K siblingKey = sibling.keys[sibling.getNbElems() - 1];
@@ -292,9 +373,6 @@ public class Leaf<K, V> extends Abstract
         System.arraycopy( keys, pos + 1, newLeaf.keys, pos + 1, keys.length - pos - 1 );
         System.arraycopy( values, pos + 1, newLeaf.values, pos + 1, values.length - pos - 1 );
 
-        // Create the result
-        Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos], values[pos].getValue( btree ) );
-
         DeleteResult<K, V> result = new BorrowedFromLeftResult<K, V>( newLeaf, newSibling, removedElement );
 
         return result;
@@ -302,7 +380,7 @@ public class Leaf<K, V> extends Abstract
 
 
     /**
-     * Borrow an element from the right sibling, creating a new sibling with one
+     * Borrows an element from the right sibling, creating a new sibling with one
      * less element and creating a new page where the element to remove has been
      * deleted and the borrowed element added on the right.
      * 
@@ -310,11 +388,10 @@ public class Leaf<K, V> extends Abstract
      * @param sibling The right sibling
      * @param pos The position of the element to remove
      * @return The resulting pages
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page 
      */
-    private DeleteResult<K, V> borrowFromRight( long revision, Leaf<K, V> sibling, int pos )
-        throws EndOfFileExceededException, IOException
+    private DeleteResult<K, V> borrowFromRight( Tuple<K, V> removedElement, long revision, Leaf<K, V> sibling, int pos )
+        throws IOException
     {
         // The sibling is on the left, borrow the rightmost element
         K siblingKey = sibling.keys[0];
@@ -343,9 +420,6 @@ public class Leaf<K, V> extends Abstract
         System.arraycopy( keys, pos + 1, newLeaf.keys, pos, keys.length - pos - 1 );
         System.arraycopy( values, pos + 1, newLeaf.values, pos, values.length - pos - 1 );
 
-        // Create the result
-        Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos], values[pos].getValue( btree ) );
-
         DeleteResult<K, V> result = new BorrowedFromRightResult<K, V>( newLeaf, newSibling, removedElement );
 
         return result;
@@ -353,26 +427,24 @@ public class Leaf<K, V> extends Abstract
 
 
     /**
-     * Remove the element at a given position.
-     * 
-     * @param revision The revision of the modified page
+     * Copies the elements of the current page to a new page
+     *
+     * @param keyRemoved a flag stating if the key was removed
+     * @param newLeaf The new page into which the remaining keys and values will be copied
      * @param pos The position into the page of the element to remove
-     * @return The modified page with the <K,V> element added
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page
      */
-    private DeleteResult<K, V> removeElement( long revision, int pos ) throws EndOfFileExceededException, IOException
+    private void copyAfterRemovingElement( boolean keyRemoved, Leaf<K, V> newLeaf, int pos ) throws IOException
     {
-        // First copy the current page, but remove one element in the copied page
-        Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems - 1 );
-
-        // Get the removed element
-        Tuple<K, V> removedElement = new Tuple<K, V>( keys[pos], values[pos].getValue( btree ) );
-
-        // Deal with the special case of an page with only one element by skipping
-        // the copy, as we won't have any remaining  element in the page
-        if ( nbElems > 1 )
+        if ( keyRemoved )
         {
+            // Deal with the special case of a page with only one element by skipping
+            // the copy, as we won't have any remaining  element in the page
+            if ( nbElems == 1 )
+            {
+                return;
+            }
+
             // Copy the keys and the values up to the insertion position
             System.arraycopy( keys, 0, newLeaf.keys, 0, pos );
             System.arraycopy( values, 0, newLeaf.values, 0, pos );
@@ -381,48 +453,107 @@ public class Leaf<K, V> extends Abstract
             System.arraycopy( keys, pos + 1, newLeaf.keys, pos, keys.length - pos - 1 );
             System.arraycopy( values, pos + 1, newLeaf.values, pos, values.length - pos - 1 );
         }
+        else
+        // one of the many values of the same key was removed, no change in the number of keys
+        {
+            System.arraycopy( keys, 0, newLeaf.keys, 0, nbElems );
+            System.arraycopy( values, 0, newLeaf.values, 0, nbElems );
+        }
+    }
 
-        // Create the result
-        DeleteResult<K, V> result = new RemoveResult<K, V>( newLeaf, removedElement );
 
-        return result;
+    /**
+     * {@inheritDoc}
+     */
+    public V get( K key ) throws KeyNotFoundException, IOException
+    {
+        int pos = findPos( key );
+
+        if ( pos < 0 )
+        {
+            V v = values[-( pos + 1 )].getValue( btree );
+
+            if ( btree.isAllowDuplicates() )
+            {
+                // always return the first value for get(key) when duplicates are allowed
+                BTree<V, V> dupTree = ( ( BTree<V, V> ) v );
+                return dupTree.rootPage.getLeftMostKey();
+            }
+
+            return v;
+        }
+        else
+        {
+            throw new KeyNotFoundException( "Cannot find an entry for key " + key );
+        }
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public boolean exist( K key )
+    @Override
+    public BTree<V, V> getValues( K key ) throws KeyNotFoundException, IOException, IllegalArgumentException
     {
+        if( !btree.isAllowDuplicates() )
+        {
+            throw new IllegalArgumentException( "Duplicates are not allowed in this tree" );
+        }
+        
         int pos = findPos( key );
 
         if ( pos < 0 )
         {
-            return true;
+            V v = values[-( pos + 1 )].getValue( btree );
+
+            return ( ( BTree<V, V> ) v );
         }
         else
         {
-            return false;
+            throw new KeyNotFoundException( "Cannot find an entry for key " + key );
         }
     }
 
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
-    public V get( K key ) throws KeyNotFoundException, EndOfFileExceededException, IOException
+    public boolean hasKey( K key )
     {
         int pos = findPos( key );
 
         if ( pos < 0 )
         {
-            return values[-( pos + 1 )].getValue( btree );
+            return true;
+        }
+
+        return false;
+    }
+
+
+    @Override
+    public boolean contains( K key, V value ) throws IOException
+    {
+        int pos = findPos( key );
+
+        if ( pos < 0 )
+        {
+            V v = values[-( pos + 1 )].getValue( btree );
+
+            if ( btree.isAllowDuplicates() )
+            {
+                // always return the first value for get(key) when duplicates are allowed
+                BTree<V, V> dupTree = ( ( BTree<V, V> ) v );
+                return dupTree.hasKey( value );
+            }
+            else
+            {
+                return ( btree.getValueSerializer().compare( value, v ) == 0 );
+            }
         }
         else
         {
-            throw new KeyNotFoundException( "Cannot find an entry for key " + key );
+            return false;
         }
     }
 
@@ -444,7 +575,7 @@ public class Leaf<K, V> extends Abstract
 
 
     /**
-     * Set the value at a give position
+     * Sets the value at a give position
      * @param pos The position in the values array
      * @param value the value to inject
      */
@@ -467,7 +598,9 @@ public class Leaf<K, V> extends Abstract
             int index = -( pos + 1 );
 
             // The first element has been found. Create the cursor
-            stack.push( new ParentPos<K, V>( this, index ) );
+            ParentPos<K, V> parentPos = new ParentPos<K, V>( this, index );
+            setDupsContainer( parentPos, btree );
+            stack.push( parentPos );
 
             cursor = new Cursor<K, V>( btree, transaction, stack );
         }
@@ -476,14 +609,16 @@ public class Leaf<K, V> extends Abstract
             // The key has not been found. Select the value just above, if we have one
             if ( pos < nbElems )
             {
-                stack.push( new ParentPos<K, V>( this, pos ) );
+                ParentPos<K, V> parentPos = new ParentPos<K, V>( this, pos );
+                setDupsContainer( parentPos, btree );
+                stack.push( parentPos );
 
                 cursor = new Cursor<K, V>( btree, transaction, stack );
             }
             else
             {
                 // Not found : return a null cursor
-                stack.push( new ParentPos<K, V>( this, -1 ) );
+                stack.push( new ParentPos<K, V>( null, -1 ) );
 
                 return new Cursor<K, V>( btree, transaction, stack );
             }
@@ -511,7 +646,11 @@ public class Leaf<K, V> extends Abstract
         else
         {
             // Start at the beginning of the page
-            stack.push( new ParentPos<K, V>( this, pos ) );
+            ParentPos<K, V> parentPos = new ParentPos<K, V>( this, pos );
+
+            setDupsContainer( parentPos, btree );
+
+            stack.push( parentPos );
 
             cursor = new Cursor<K, V>( btree, transaction, stack );
         }
@@ -547,11 +686,10 @@ public class Leaf<K, V> extends Abstract
      * @param value the new value
      * @param pos The position of the key in the page
      * @return The copied page
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private InsertResult<K, V> replaceElement( long revision, K key, V value, int pos )
-        throws EndOfFileExceededException, IOException
+        throws IOException
     {
         Leaf<K, V> newLeaf = this;
 
@@ -561,10 +699,27 @@ public class Leaf<K, V> extends Abstract
             newLeaf = ( Leaf<K, V> ) copy( revision, nbElems );
         }
 
-        // Now we can inject the value
-        V oldValue = newLeaf.values[pos].getValue( btree );
+        V oldValue = null;
 
-        newLeaf.values[pos] = btree.createHolder( value );
+        if ( btree.isAllowDuplicates() )
+        {
+            BTree<V, V> dupValues = ( BTree<V, V> ) newLeaf.values[pos].getValue( btree );
+            // return value will always be null  here 
+            if ( !dupValues.hasKey( value ) )
+            {
+                dupValues.insert( value, null, 0 );
+            }
+            else
+            {
+                oldValue = value;
+            }
+        }
+        else
+        {
+            // Now we can inject the value
+            oldValue = newLeaf.values[pos].getValue( btree );
+            newLeaf.values[pos] = btree.createHolder( value );
+        }
 
         // Create the result
         InsertResult<K, V> result = new ModifyResult<K, V>( newLeaf, oldValue );
@@ -574,7 +729,7 @@ public class Leaf<K, V> extends Abstract
 
 
     /**
-     * Add a new <K, V> into a copy of the current page at a given position. We return the
+     * Adds a new <K, V> into a copy of the current page at a given position. We return the
      * modified page. The new page will have one more element than the current page.
      * 
      * @param revision The revision of the modified page
@@ -588,8 +743,19 @@ public class Leaf<K, V> extends Abstract
         // First copy the current page, but add one element in the copied page
         Leaf<K, V> newLeaf = new Leaf<K, V>( btree, revision, nbElems + 1 );
 
-        // Atm, store the value in memory 
-        MemoryHolder<K, V> valueHolder = new MemoryHolder<K, V>( btree, value );
+        // Atm, store the value in memory
+
+        ElementHolder valueHolder = null;
+
+        if ( btree.isAllowDuplicates() )
+        {
+            valueHolder = new DuplicateKeyMemoryHolder<K, V>( btree, value );
+        }
+        else
+        {
+            valueHolder = new MemoryHolder<K, V>( btree, value );
+        }
+
         //ValueHolder<K, V> valueHolder = btree.createHolder( value );
 
         // Deal with the special case of an empty page
@@ -713,23 +879,52 @@ public class Leaf<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
-    public Tuple<K, V> findLeftMost() throws EndOfFileExceededException, IOException
+    public K getRightMostKey()
+    {
+        return keys[nbElems - 1];
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Tuple<K, V> findLeftMost() throws IOException
     {
-        return new Tuple<K, V>( keys[0], values[0].getValue( btree ) );
+        V val = null;
+
+        if ( btree.isAllowDuplicates() )
+        {
+            BTree<V, V> dupTree = ( BTree<V, V> ) values[0].getValue( btree );
+            val = dupTree.rootPage.getLeftMostKey();
+        }
+        else
+        {
+            val = values[0].getValue( btree );
+        }
+
+        return new Tuple<K, V>( keys[0], val );
     }
 
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
     public Tuple<K, V> findRightMost() throws EndOfFileExceededException, IOException
     {
-        return new Tuple<K, V>( keys[nbElems - 1], values[nbElems - 1].getValue( btree ) );
+        V val = null;
+
+        if ( btree.isAllowDuplicates() )
+        {
+            BTree<V, V> dupTree = ( BTree<V, V> ) values[nbElems - 1].getValue( btree );
+            val = dupTree.rootPage.getRightMostKey();
+        }
+        else
+        {
+            val = values[nbElems - 1].getValue( btree );
+        }
+
+        return new Tuple<K, V>( keys[nbElems - 1], val );
     }
 
 

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Node.java Sun Apr 21 17:58:23 2013
@@ -37,14 +37,14 @@ import org.apache.mavibot.btree.exceptio
  *
  * @author <a href="mailto:labs@labs.apache.org">Mavibot labs Project</a>
  */
-public class Node<K, V> extends AbstractPage<K, V>
+/* No qualifier */class Node<K, V> extends AbstractPage<K, V>
 {
     /** Children pages associated with keys. */
     protected ElementHolder<Page<K, V>, K, V>[] children;
 
 
     /**
-     * Create a new Node which will contain only one key, with references to
+     * Creates a new Node which will contain only one key, with references to
      * a left and right page. This is a specific constructor used by the btree
      * when the root was full when we added a new value.
      * 
@@ -63,7 +63,7 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Create a new Node which will contain only one key, with references to
+     * Creates a new Node which will contain only one key, with references to
      * a left and right page. This is a specific constructor used by the btree
      * when the root was full when we added a new value.
      * 
@@ -104,7 +104,7 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Create a new Node which will contain only one key, with references to
+     * Creates a new Node which will contain only one key, with references to
      * a left and right page. This is a specific constructor used by the btree
      * when the root was full when we added a new value.
      * 
@@ -194,9 +194,15 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Modify the current node after a remove has been done in one of its children.
+     * Modifies the current node after a remove has been done in one of its children.
      * The node won't be merged with another node.
-     * @throws IOException 
+     * 
+     * @param removeResult The result of a remove operation
+     * @param index the position of the key, not transformed
+     * @param pos The position of the key, as a positive value
+     * @param found If the key has been found in the page
+     * @return The new result
+     * @throws IOException If we have an error while trying to access the page
      */
     private RemoveResult<K, V> handleRemoveResult( RemoveResult<K, V> removeResult, int index, int pos, boolean found )
         throws IOException
@@ -230,14 +236,14 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Handle the removal of an element from the root page, when two of its children
+     * Handles the removal of an element from the root page, when two of its children
      * have been merged.
      * 
      * @param mergedResult The merge result
      * @param pos The position in the current root
      * @param found Tells if the removed key is present in the root page
      * @return The resulting root page
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private RemoveResult<K, V> handleRootRemove( MergedWithSiblingResult<K, V> mergedResult, int pos, boolean found )
         throws IOException
@@ -262,7 +268,7 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Borrow an element from the right sibling, creating a new sibling with one
+     * Borrows an element from the right sibling, creating a new sibling with one
      * less element and creating a new page where the element to remove has been
      * deleted and the borrowed element added on the right.
      * 
@@ -270,7 +276,7 @@ public class Node<K, V> extends Abstract
      * @param sibling The right sibling
      * @param pos The position of the element to remove
      * @return The resulting pages
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private DeleteResult<K, V> borrowFromRight( long revision, MergedWithSiblingResult<K, V> mergedResult,
         Node<K, V> sibling, int pos ) throws IOException
@@ -344,7 +350,7 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Borrow an element from the left sibling, creating a new sibling with one
+     * Borrows an element from the left sibling, creating a new sibling with one
      * less element and creating a new page where the element to remove has been
      * deleted and the borrowed element added on the left.
      * 
@@ -352,7 +358,7 @@ public class Node<K, V> extends Abstract
      * @param sibling The left sibling
      * @param pos The position of the element to remove
      * @return The resulting pages
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private DeleteResult<K, V> borrowFromLeft( long revision, MergedWithSiblingResult<K, V> mergedResult,
         Node<K, V> sibling, int pos ) throws IOException
@@ -428,13 +434,15 @@ public class Node<K, V> extends Abstract
      * We have to merge the node with its sibling, both have N/2 elements before the element
      * removal.
      * 
-     * @param revision
-     * @param mergedResult
-     * @param pos
-     * @return
-     * @throws IOException 
+     * @param revision The revision
+     * @param mergedResult The result of the merge
+     * @param sibling The Page we will merge the current page with
+     * @param isLeft Tells if the sibling is on the left
+     * @param pos The position of the key that has been removed
+     * @return The page resulting of the merge
+     * @throws IOException If we have an error while trying to access the page
      */
-    public DeleteResult<K, V> mergeWithSibling( long revision, MergedWithSiblingResult<K, V> mergedResult,
+    private DeleteResult<K, V> mergeWithSibling( long revision, MergedWithSiblingResult<K, V> mergedResult,
         Node<K, V> sibling, boolean isLeft, int pos ) throws IOException
     {
         // Create the new node. It will contain N - 1 elements (the maximum number)
@@ -551,9 +559,9 @@ public class Node<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
      */
-    public DeleteResult<K, V> delete( long revision, K key, Page<K, V> parent, int parentPos ) throws IOException
+    public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
+        throws IOException
     {
         // We first try to delete the element from the child it belongs to
         // Find the key in the page
@@ -567,12 +575,12 @@ public class Node<K, V> extends Abstract
         {
             index = -( pos + 1 );
             child = children[-pos].getValue( btree );
-            deleteResult = child.delete( revision, key, this, -pos );
+            deleteResult = child.delete( revision, key, value, this, -pos );
         }
         else
         {
             child = children[pos].getValue( btree );
-            deleteResult = child.delete( revision, key, this, pos );
+            deleteResult = child.delete( revision, key, value, this, pos );
         }
 
         // If the key is not present in the tree, we simply return
@@ -677,7 +685,7 @@ public class Node<K, V> extends Abstract
      * @param borrowedResult The result of the deletion from the children
      * @param pos The position the key was found in the current node
      * @return The result
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private RemoveResult<K, V> handleBorrowedResult( BorrowedFromSiblingResult<K, V> borrowedResult, int pos )
         throws IOException
@@ -744,10 +752,11 @@ public class Node<K, V> extends Abstract
     /**
      * Remove the key at a given position.
      * 
+     * @param mergedResult The page we will remove a key from
      * @param revision The revision of the modified page
      * @param pos The position into the page of the element to remove
      * @return The modified page with the <K,V> element added
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private RemoveResult<K, V> removeKey( MergedWithSiblingResult<K, V> mergedResult, long revision, int pos )
         throws IOException
@@ -801,9 +810,9 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * {@inheritDoc} 
+     * {@inheritDoc}
      */
-    public boolean exist( K key ) throws IOException
+    public V get( K key ) throws IOException, KeyNotFoundException
     {
         int pos = findPos( key );
 
@@ -811,22 +820,20 @@ public class Node<K, V> extends Abstract
         {
             // Here, if we have found the key in the node, then we must go down into
             // the right child, not the left one
-            return children[-pos].getValue( btree ).exist( key );
+            return children[-pos].getValue( btree ).get( key );
         }
         else
         {
-            return children[pos].getValue( btree ).exist( key );
+            return children[pos].getValue( btree ).get( key );
         }
     }
 
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws KeyNotFoundException 
-     * @throws EndOfFileExceededException 
      */
-    public V get( K key ) throws IOException, KeyNotFoundException
+    @Override
+    public BTree<V, V> getValues( K key ) throws KeyNotFoundException, IOException, IllegalArgumentException
     {
         int pos = findPos( key );
 
@@ -834,17 +841,60 @@ public class Node<K, V> extends Abstract
         {
             // Here, if we have found the key in the node, then we must go down into
             // the right child, not the left one
-            return children[-pos].getValue( btree ).get( key );
+            return children[-pos].getValue( btree ).getValues( key );
         }
         else
         {
-            return children[pos].getValue( btree ).get( key );
+            return children[pos].getValue( btree ).getValues( key );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean hasKey( K key ) throws IOException
+    {
+        int pos = findPos( key );
+
+        if ( pos < 0 )
+        {
+            // Here, if we have found the key in the node, then we must go down into
+            // the right child, not the left one
+            return children[-pos].getValue( btree ).hasKey( key );
+        }
+        else
+        {
+            return children[pos].getValue( btree ).hasKey( key );
+        }
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean contains( K key, V value ) throws IOException
+    {
+        int pos = findPos( key );
+
+        if ( pos < 0 )
+        {
+            // Here, if we have found the key in the node, then we must go down into
+            // the right child, not the left one
+            return children[-pos].getValue( btree ).contains( key, value );
+        }
+        else
+        {
+            return children[pos].getValue( btree ).contains( key, value );
         }
     }
 
 
     /**
      * Set the value at a give position
+     * 
      * @param pos The position in the values array
      * @param value the value to inject
      */
@@ -856,10 +906,8 @@ public class Node<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
-    public Page<K, V> getReference( int pos ) throws EndOfFileExceededException, IOException
+    public Page<K, V> getReference( int pos ) throws IOException
     {
         if ( pos < nbElems + 1 )
         {
@@ -874,11 +922,9 @@ public class Node<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
     public Cursor<K, V> browse( K key, Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
-        throws EndOfFileExceededException, IOException
+        throws IOException
     {
         int pos = findPos( key );
 
@@ -896,11 +942,9 @@ public class Node<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
     public Cursor<K, V> browse( Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
-        throws EndOfFileExceededException, IOException
+        throws IOException
     {
         stack.push( new ParentPos<K, V>( this, 0 ) );
 
@@ -917,7 +961,7 @@ public class Node<K, V> extends Abstract
      * @param result The modified page
      * @param pos The position of the found key
      * @return A modified page
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private InsertResult<K, V> replaceChild( long revision, ModifyResult<K, V> result, int pos ) throws IOException
     {
@@ -938,11 +982,18 @@ public class Node<K, V> extends Abstract
     }
 
 
+    /**
+     * Creates a new holder contaning a reference to a Page
+     * 
+     * @param page The page we will refer to
+     * @return A holder contaning a reference to the child page
+     * @throws IOException If we have an error while trying to access the page
+     */
     private ElementHolder<Page<K, V>, K, V> createHolder( Page<K, V> page ) throws IOException
     {
         if ( btree.isManaged() )
         {
-            ElementHolder<Page<K, V>, K, V> holder = btree.getRecordManager().writePage( btree, this,
+            ElementHolder<Page<K, V>, K, V> holder = btree.getRecordManager().writePage( btree,
                 page,
                 revision );
 
@@ -960,7 +1011,7 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Add a new key into a copy of the current page at a given position. We return the
+     * Adds a new key into a copy of the current page at a given position. We return the
      * modified page. The new page will have one more key than the current page.
      * 
      * @param revision The revision of the modified page
@@ -969,7 +1020,7 @@ public class Node<K, V> extends Abstract
      * @param rightPage The right child
      * @param pos The position into the page
      * @return The modified page with the <K,V> element added
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private InsertResult<K, V> insertChild( long revision, K key, Page<K, V> leftPage, Page<K, V> rightPage, int pos )
         throws IOException
@@ -1007,7 +1058,7 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Split a full page into two new pages, a left, a right and a pivot element. The new pages will
+     * Splits a full page into two new pages, a left, a right and a pivot element. The new pages will
      * each contains half of the original elements. <br/>
      * The pivot will be computed, depending on the place
      * we will inject the newly added element. <br/>
@@ -1016,12 +1067,12 @@ public class Node<K, V> extends Abstract
      * on the left, or the first element in the right page if it's added on the right.
      * 
      * @param revision The new revision for all the created pages
-     * @param key The key to add
+     * @param pivot The key that will be move up after the split
      * @param leftPage The left child
      * @param rightPage The right child
      * @param pos The position of the insertion of the new element
      * @return An OverflowPage containing the pivot, and the new left and right pages
-     * @throws IOException 
+     * @throws IOException If we have an error while trying to access the page
      */
     private InsertResult<K, V> addAndSplit( long revision, K pivot, Page<K, V> leftPage, Page<K, V> rightPage, int pos )
         throws IOException
@@ -1106,7 +1157,7 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * Copy the current page and all its keys, with a new revision.
+     * Copies the current page and all its keys, with a new revision.
      * 
      * @param revision The new revision
      * @return The copied page
@@ -1127,8 +1178,6 @@ public class Node<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
     public K getLeftMostKey() throws EndOfFileExceededException, IOException
     {
@@ -1138,8 +1187,15 @@ public class Node<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     */
+    public K getRightMostKey() throws EndOfFileExceededException, IOException
+    {
+        return children[nbElems - 1].getValue( btree ).getRightMostKey();
+    }
+
+
+    /**
+     * {@inheritDoc}
      */
     public Tuple<K, V> findLeftMost() throws EndOfFileExceededException, IOException
     {
@@ -1149,8 +1205,6 @@ public class Node<K, V> extends Abstract
 
     /**
      * {@inheritDoc}
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      */
     public Tuple<K, V> findRightMost() throws EndOfFileExceededException, IOException
     {
@@ -1159,8 +1213,6 @@ public class Node<K, V> extends Abstract
 
 
     /**
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
      * @see Object#toString()
      */
     public String toString()

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/Page.java Sun Apr 21 17:58:23 2013
@@ -28,14 +28,15 @@ import org.apache.mavibot.btree.exceptio
 
 
 /**
- * A MVCC Page interface.
+ * A MVCC Page interface. A Page can be either a Leaf (containing keys and values) or a Node
+ * (containing keys and references to child pages).
  * 
  * @param <K> The type for the Key
  * @param <V> The type for the stored value
  *
  * @author <a href="mailto:labs@labs.apache.org">Mavibot labs Project</a>
  */
-public interface Page<K, V>
+/* No qualifier */interface Page<K, V>
 {
     /**
      * @return The number of keys present in this page
@@ -44,7 +45,7 @@ public interface Page<K, V>
 
 
     /**
-     * Insert the given key and value into this page. We first find the place were to
+     * Inserts the given key and value into this page. We first find the place were to
      * inject the <K,V> into the tree, by recursively browsing the pages :<br/>
      * <ul>
      * <li>If the index is below zero, the key is present in the Page : we modify the
@@ -59,68 +60,88 @@ public interface Page<K, V>
      * @param key Inserted key
      * @param value Inserted value
      * @return Either a modified Page or an Overflow element if the Page was full
+     * @throws IOException If we have an error while trying to access the page
      */
     InsertResult<K, V> insert( long revision, K key, V value ) throws IOException;
 
 
     /**
-     * delete an entry with the given key from this page. We first find the place were to
-     * remove the <K,V> into the tree, by recursively browsing the pages :<br/>
-     * <p>
+     * Deletes the value from an entry associated with the given key in this page. We first find 
+     * the place were to remove the <K,V> into the tree, by recursively browsing the pages.
+     * If the value is present, it will be deleted first, later if there are no other values associated with 
+     * this key(which can happen when duplicates are enabled), we will remove the key from the tree.
      * 
      * @param revision The new revision for the modified pages
      * @param key The key to delete
+     * @param value The value to delete (can be null)
      * @param parent The parent page
-     * @param parentPos he position of the current page in it's parent
-     * @return
+     * @param parentPos The position of the current page in it's parent
+     * @return Either a modified Page if the key has been removed from the page, or a NotPresentResult.
+     * @throws IOException If we have an error while trying to access the page
      */
-    DeleteResult<K, V> delete( long revision, K key, Page<K, V> parent, int parentPos ) throws IOException;
+    DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos ) throws IOException;
 
 
     /**
-     * Check if there is an element associated with the given key.
+     * Gets the value associated with the given key, if any. If we don't have 
+     * one, this method will throw a KeyNotFoundException.<br/>
+     * Note that we may get back null if a null value has been associated 
+     * with the key.
      * 
-     * @param key The key we are looking at
-     * @return true if the Key exists in the BTree 
+     * @param key The key we are looking for
+     * @return The associated value, which can be null
+     * @throws KeyNotFoundException If no entry with the given key can be found
      * @throws IOException If we have an error while trying to access the page
      */
-    boolean exist( K key ) throws IOException;
-
+    V get( K key ) throws KeyNotFoundException, IOException;
 
+    
     /**
-     * Get the value associated with the given key, if any. If we don't have 
-     * one, this method will throw a KeyNotFoundException.<br/>
+     * Gets the values associated with the given key, if any. If we don't have 
+     * the key, this method will throw a KeyNotFoundException.<br/>
      * Note that we may get back null if a null value has been associated 
      * with the key.
      * 
      * @param key The key we are looking for
+     * @return The associated value, which can be null
      * @throws KeyNotFoundException If no entry with the given key can be found
-     * @return The associated value, or null if there is none
+     * @throws IOException If we have an error while trying to access the page
+     * @throws IllegalArgumentException If duplicates are not enabled 
      */
-    V get( K key ) throws KeyNotFoundException, IOException;
+    BTree<V,V> getValues( K key ) throws KeyNotFoundException, IOException, IllegalArgumentException;
+
+    
+    /**
+     * Checks if the page contains the given key with the given value.
+     * 
+     * @param key The key we are looking for
+     * @param value The value associated with the given key
+     * @return true if the key and value are associated with each other, false otherwise
+     */
+    boolean contains( K key, V value ) throws IOException;
 
 
     /**
-     * browse the tree, looking for the given key, and create a Cursor on top
+     * Browses the tree, looking for the given key, and creates a Cursor on top
      * of the found result.
      * 
      * @param key The key we are looking for.
      * @param transaction The started transaction for this operation
      * @param stack The stack of parents we go through to get to this page
      * @return A Cursor to browse the next elements
+     * @throws IOException If we have an error while trying to access the page
      */
     Cursor<K, V> browse( K key, Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
-        throws EndOfFileExceededException, IOException;
+        throws IOException;
 
 
     /**
-     * browse the whole tree, and create a Cursor on top of it.
+     * Browses the whole tree, and creates a Cursor on top of it.
      * 
      * @param transaction The started transaction for this operation
      * @param stack The stack of parents we go through to get to this page
      * @return A Cursor to browse the next elements
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page
      */
     Cursor<K, V> browse( Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack )
         throws EndOfFileExceededException, IOException;
@@ -133,7 +154,8 @@ public interface Page<K, V>
 
 
     /**
-     * Return the key at a given position
+     * Returns the key at a given position
+     * 
      * @param pos The position of the key we want to retrieve
      * @return The key found at the given position
      */
@@ -141,42 +163,104 @@ public interface Page<K, V>
 
 
     /**
-     * Find the leftmost key in this page. If the page is a node, it will go
+     * Finds the leftmost key in this page. If the page is a node, it will go
      * down in the leftmost children to recursively find the leftmost key.
      * 
      * @return The leftmost key in the tree
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page
+     */
+    K getLeftMostKey() throws IOException;
+
+
+    /**
+     * Finds the rightmost key in this page. If the page is a node, it will go
+     * down in the rightmost children to recursively find the rightmost key.
+     * 
+     * @return The rightmost key in the tree
+     * @throws IOException If we have an error while trying to access the page
      */
-    K getLeftMostKey() throws EndOfFileExceededException, IOException;
+    K getRightMostKey() throws IOException;
 
 
     /**
-     * Find the leftmost element in this page. If the page is a node, it will go
+     * Finds the leftmost element in this page. If the page is a node, it will go
      * down in the leftmost children to recursively find the leftmost element.
      * 
      * @return The leftmost element in the tree
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page
      */
-    Tuple<K, V> findLeftMost() throws EndOfFileExceededException, IOException;
+    Tuple<K, V> findLeftMost() throws IOException;
 
 
     /**
-     * Find the rightmost element in this page. If the page is a node, it will go
+     * Finds the rightmost element in this page. If the page is a node, it will go
      * down in the rightmost children to recursively find the rightmost element.
      * 
      * @return The rightmost element in the tree
-     * @throws IOException 
-     * @throws EndOfFileExceededException 
+     * @throws IOException If we have an error while trying to access the page
      */
     Tuple<K, V> findRightMost() throws EndOfFileExceededException, IOException;
 
 
     /**
-     * Pretty-print the tree with tabs
+     * Pretty-prints the tree with tabs
      * @param tabs The tabs to add in front of each node
      * @return A pretty-print dump of the tree
      */
     String dumpPage( String tabs );
+
+
+    /**
+     * Find the position of the given key in the page. If we have found the key,
+     * we will return its position as a negative value.
+     * <p/>
+     * Assuming that the array is zero-indexed, the returned value will be : <br/>
+     *   position = - ( position + 1)
+     * <br/>
+     * So for the following table of keys : <br/>
+     * <pre>
+     * +---+---+---+---+
+     * | b | d | f | h |
+     * +---+---+---+---+
+     *   0   1   2   3
+     * </pre>
+     * looking for 'b' will return -1 (-(0+1)) and looking for 'f' will return -3 (-(2+1)).<br/>
+     * Computing the real position is just a matter to get -(position++).
+     * <p/>
+     * If we don't find the key in the table, we will return the position of the key
+     * immediately above the key we are looking for. <br/>
+     * For instance, looking for :
+     * <ul>
+     * <li>'a' will return 0</li>
+     * <li>'b' will return -1</li>
+     * <li>'c' will return 1</li>
+     * <li>'d' will return -2</li>
+     * <li>'e' will return 2</li>
+     * <li>'f' will return -3</li>
+     * <li>'g' will return 3</li>
+     * <li>'h' will return -4</li>
+     * <li>'i' will return 4</li>
+     * </ul>
+     * 
+     * 
+     * @param key The key to find
+     * @return The position in the page.
+     */
+    int findPos( K key );
+
+
+    /**
+     * Checks if the given key exists.
+     *  
+     * @param key The key we are looking at
+     * @return true if the key is present, false otherwise
+     * @throws IOException If we have an error while trying to access the page
+     */
+    boolean hasKey( K key ) throws IOException;
+
+
+    /**
+     * @return the offset
+     */
+    long getOffset();
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ParentPos.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ParentPos.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ParentPos.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ParentPos.java Sun Apr 21 17:58:23 2013
@@ -37,7 +37,12 @@ package org.apache.mavibot.btree;
     /** The current position in the page */
     /* No qualifier*/int pos;
 
+    /** The current position of the duplicate container in the page */
+    /* No qualifier*/int dupPos;
 
+    /** the container of duplicate key's values. The tuples will be stored as <V,null>*/
+    /* No qualifier*/BTree<V, V> dupsContainer;
+    
     /**
      * Creates a new instance of ParentPos
      * @param page The current Page

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/BooleanComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/BooleanComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/BooleanComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/BooleanComparator.java Sun Apr 21 17:58:23 2013
@@ -46,12 +46,12 @@ public class BooleanComparator implement
 
         if ( boolean1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
+            return -1;
         }
 
         if ( boolean2 == null )
         {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
+            return 1;
         }
 
         return boolean1.compareTo( boolean2 );

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteArrayComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteArrayComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteArrayComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteArrayComparator.java Sun Apr 21 17:58:23 2013
@@ -24,7 +24,7 @@ import java.util.Comparator;
 
 
 /**
- * Compares byte arrays
+ * Compares byte arrays.
  * 
  * @author <a href="mailto:labs@labs.apache.org">Mavibot labs Project</a>
  */
@@ -46,49 +46,79 @@ public class ByteArrayComparator impleme
 
         if ( byteArray1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
-        }
-
-        if ( byteArray2 == null )
-        {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
-        }
-
-        if ( byteArray1.length < byteArray2.length )
-        {
-            return -1;
-        }
-
-        if ( byteArray1.length > byteArray2.length )
-        {
-            return 1;
-        }
-
-        for ( int pos = 0; pos < byteArray1.length; pos++ )
-        {
-            int comp = compare( byteArray1[pos], byteArray2[pos] );
-
-            if ( comp != 0 )
+            if ( byteArray2 == null )
             {
-                return comp;
+                return 0;
+            }
+            else
+            {
+                return -1;
             }
         }
-
-        return 0;
-    }
-
-
-    private int compare( byte byte1, byte byte2 )
-    {
-        if ( byte1 < byte2 )
-        {
-            return -1;
-        }
-        if ( byte1 > byte2 )
+        else
         {
-            return 1;
+            if ( byteArray2 == null )
+            {
+                return 1;
+            }
+            else
+            {
+                if ( byteArray1.length < byteArray2.length )
+                {
+                    int pos = 0;
+
+                    for ( byte b1 : byteArray1 )
+                    {
+                        byte b2 = byteArray2[pos];
+
+                        if ( b1 == b2 )
+                        {
+                            pos++;
+                        }
+                        else if ( b1 < b2 )
+                        {
+                            return -1;
+                        }
+                        else
+                        {
+                            return 1;
+                        }
+                    }
+
+                    return -1;
+                }
+                else
+                {
+                    int pos = 0;
+
+                    for ( byte b2 : byteArray2 )
+                    {
+                        byte b1 = byteArray1[pos];
+
+                        if ( b1 == b2 )
+                        {
+                            pos++;
+                        }
+                        else if ( b1 < b2 )
+                        {
+                            return -1;
+                        }
+                        else
+                        {
+                            return 1;
+                        }
+                    }
+
+                    if ( pos < byteArray1.length )
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return 0;
+                    }
+                }
+            }
         }
-
-        return 0;
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ByteComparator.java Sun Apr 21 17:58:23 2013
@@ -46,14 +46,25 @@ public class ByteComparator implements C
 
         if ( byte1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
+            return -1;
         }
 
         if ( byte2 == null )
         {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
+            return 1;
         }
 
-        return byte1.compareTo( byte2 );
+        if ( byte1 < byte2 )
+        {
+            return -1;
+        }
+        else if ( byte1 > byte2 )
+        {
+            return 1;
+        }
+        else
+        {
+            return 0;
+        }
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/CharComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/CharComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/CharComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/CharComparator.java Sun Apr 21 17:58:23 2013
@@ -46,14 +46,36 @@ public class CharComparator implements C
 
         if ( char1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
+            if ( char2 == null )
+            {
+                return 0;
+            }
+            else
+            {
+                return -1;
+            }
         }
-
-        if ( char2 == null )
+        else
         {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
+            if ( char2 == null )
+            {
+                return 1;
+            }
+            else
+            {
+                if ( char1 < char2 )
+                {
+                    return -1;
+                }
+                else if ( char1 > char2 )
+                {
+                    return 1;
+                }
+                else
+                {
+                    return 0;
+                }
+            }
         }
-
-        return char1.compareTo( char2 );
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/IntComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/IntComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/IntComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/IntComparator.java Sun Apr 21 17:58:23 2013
@@ -46,14 +46,25 @@ public class IntComparator implements Co
 
         if ( integer1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
+            if ( integer2 == null )
+            {
+                return 0;
+            }
+            else
+            {
+                return -1;
+            }
         }
-
-        if ( integer2 == null )
+        else
         {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
+            if ( integer2 == null )
+            {
+                return 1;
+            }
+            else
+            {
+                return integer1.compareTo( integer2 );
+            }
         }
-
-        return integer1.compareTo( integer2 );
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongArrayComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongArrayComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongArrayComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongArrayComparator.java Sun Apr 21 17:58:23 2013
@@ -33,8 +33,8 @@ public class LongArrayComparator impleme
     /**
      * Compare two long arrays.
      * 
-     * @param longArray1 First longArray
-     * @param longArray2 Second longArray
+     * @param longArray1 First long array
+     * @param longArray2 Second long array
      * @return 1 if longArray1 > longArray2, 0 if longArray1 == longArray2, -1 if longArray1 < longArray2
      */
     public int compare( long[] longArray1, long[] longArray2 )
@@ -46,49 +46,79 @@ public class LongArrayComparator impleme
 
         if ( longArray1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
-        }
-
-        if ( longArray2 == null )
-        {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
-        }
-
-        if ( longArray1.length < longArray2.length )
-        {
-            return -1;
-        }
-
-        if ( longArray1.length > longArray2.length )
-        {
-            return 1;
-        }
-
-        for ( int pos = 0; pos < longArray1.length; pos++ )
-        {
-            int comp = compare( longArray1[pos], longArray2[pos] );
-
-            if ( comp != 0 )
+            if ( longArray2 == null )
             {
-                return comp;
+                return 0;
+            }
+            else
+            {
+                return -1;
             }
         }
-
-        return 0;
-    }
-
-
-    private int compare( long long1, long long2 )
-    {
-        if ( long1 < long2 )
-        {
-            return -1;
-        }
-        if ( long1 > long2 )
+        else
         {
-            return 1;
+            if ( longArray2 == null )
+            {
+                return 1;
+            }
+            else
+            {
+                if ( longArray1.length < longArray2.length )
+                {
+                    int pos = 0;
+
+                    for ( long long1 : longArray1 )
+                    {
+                        long long2 = longArray2[pos];
+
+                        if ( long1 == long2 )
+                        {
+                            pos++;
+                        }
+                        else if ( long1 < long2 )
+                        {
+                            return -1;
+                        }
+                        else
+                        {
+                            return 1;
+                        }
+                    }
+
+                    return -1;
+                }
+                else
+                {
+                    int pos = 0;
+
+                    for ( long long2 : longArray2 )
+                    {
+                        long long1 = longArray1[pos];
+
+                        if ( long1 == long2 )
+                        {
+                            pos++;
+                        }
+                        else if ( long1 < long2 )
+                        {
+                            return -1;
+                        }
+                        else
+                        {
+                            return 1;
+                        }
+                    }
+
+                    if ( pos < longArray1.length )
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return 0;
+                    }
+                }
+            }
         }
-
-        return 0;
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/LongComparator.java Sun Apr 21 17:58:23 2013
@@ -46,14 +46,36 @@ public class LongComparator implements C
 
         if ( long1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
+            if ( long2 == null )
+            {
+                return 0;
+            }
+            else
+            {
+                return -1;
+            }
         }
-
-        if ( long2 == null )
+        else
         {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
+            if ( long2 == null )
+            {
+                return 1;
+            }
+            else
+            {
+                if ( long1 < long2 )
+                {
+                    return -1;
+                }
+                else if ( long1 > long2 )
+                {
+                    return 1;
+                }
+                else
+                {
+                    return 0;
+                }
+            }
         }
-
-        return long1.compareTo( long2 );
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ShortComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ShortComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ShortComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/ShortComparator.java Sun Apr 21 17:58:23 2013
@@ -46,14 +46,36 @@ public class ShortComparator implements 
 
         if ( short1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
+            if ( short2 == null )
+            {
+                return 0;
+            }
+            else
+            {
+                return -1;
+            }
         }
-
-        if ( short2 == null )
+        else
         {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
+            if ( short2 == null )
+            {
+                return 1;
+            }
+            else
+            {
+                if ( short1 < short2 )
+                {
+                    return -1;
+                }
+                else if ( short1 > short2 )
+                {
+                    return 1;
+                }
+                else
+                {
+                    return 0;
+                }
+            }
         }
-
-        return short1.compareTo( short2 );
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/StringComparator.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/StringComparator.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/StringComparator.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/comparator/StringComparator.java Sun Apr 21 17:58:23 2013
@@ -37,23 +37,35 @@ public class StringComparator implements
      * @param string2 Second String
      * @return 1 if string1 > String2, 0 if string1 == String2, -1 if string1 < String2
      */
-    public int compare( String string1, String String2 )
+    public int compare( String string1, String string2 )
     {
-        if ( string1 == String2 )
+        if ( string1 == string2 )
         {
             return 0;
         }
 
         if ( string1 == null )
         {
-            throw new IllegalArgumentException( "The first object to compare must not be null" );
+            return -1;
         }
-
-        if ( String2 == null )
+        else if ( string2 == null )
         {
-            throw new IllegalArgumentException( "The second object to compare must not be null" );
+            return 1;
         }
 
-        return string1.compareTo( String2 );
+        int result = string1.compareTo( string2 );
+
+        if ( result < 0 )
+        {
+            return -1;
+        }
+        else if ( result > 0 )
+        {
+            return 1;
+        }
+        else
+        {
+            return 0;
+        }
     }
 }

Propchange: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Sun Apr 21 17:58:23 2013
@@ -0,0 +1 @@
+BooleanArraySerializer.java

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/BooleanSerializer.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/BooleanSerializer.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/BooleanSerializer.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/BooleanSerializer.java Sun Apr 21 17:58:23 2013
@@ -22,7 +22,6 @@ package org.apache.mavibot.btree.seriali
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.Comparator;
 
 import org.apache.mavibot.btree.comparator.BooleanComparator;
 
@@ -32,18 +31,14 @@ import org.apache.mavibot.btree.comparat
  * 
  * @author <a href="mailto:labs@labs.apache.org">Mavibot labs Project</a>
  */
-public class BooleanSerializer implements ElementSerializer<Boolean>
+public class BooleanSerializer extends AbstractElementSerializer<Boolean>
 {
-    /** The associated comparator */
-    private final Comparator<Boolean> comparator;
-
-
     /**
      * Create a new instance of BooleanSerializer
      */
     public BooleanSerializer()
     {
-        comparator = new BooleanComparator();
+        super( new BooleanComparator() );
     }
 
 
@@ -53,82 +48,77 @@ public class BooleanSerializer implement
     public byte[] serialize( Boolean element )
     {
         byte[] bytes = new byte[1];
-        bytes[0] = element.booleanValue() ? ( byte ) 0x01 : ( byte ) 0x00;
 
-        return bytes;
+        return serialize( bytes, 0, element );
     }
 
 
     /**
-     * A static method used to deserialize a Boolean from a byte array.
-     * @param in The byte array containing the boolean
-     * @return A boolean
+     * Serialize a boolean
+     * 
+     * @param value the value to serialize
+     * @return The byte[] containing the serialized boolean
      */
-    public static Boolean deserialize( byte[] in )
+    public static byte[] serialize( boolean element )
     {
-        if ( ( in == null ) || ( in.length < 1 ) )
-        {
-            throw new RuntimeException( "Cannot extract a Boolean from a buffer with not enough bytes" );
-        }
+        byte[] bytes = new byte[1];
 
-        return in[0] == 0x01;
+        return serialize( bytes, 0, element );
     }
 
 
     /**
-     * {@inheritDoc}
+     * Serialize a boolean
+     * 
+     * @param buffer the Buffer that will contain the serialized value
+     * @param start the position in the buffer we will store the serialized boolean
+     * @param value the value to serialize
+     * @return The byte[] containing the serialized boolean
      */
-    public Boolean deserialize( ByteBuffer buffer ) throws IOException
+    public static byte[] serialize( byte[] buffer, int start, boolean element )
     {
-        return buffer.get() == 0x01;
+        buffer[start] = element ? ( byte ) 0x01 : ( byte ) 0x00;
+
+        return buffer;
     }
 
 
     /**
-     * {@inheritDoc}
+     * A static method used to deserialize a Boolean from a byte array.
+     * 
+     * @param in The byte array containing the boolean
+     * @return A boolean
      */
-    @Override
-    public Boolean deserialize( BufferHandler bufferHandler ) throws IOException
+    public static Boolean deserialize( byte[] in )
     {
-        byte[] in = bufferHandler.read( 1 );
-
-        return deserialize( in );
+        return deserialize( in, 0 );
     }
 
 
     /**
-     * {@inheritDoc}
+     * A static 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
      */
-    @Override
-    public int compare( Boolean type1, Boolean type2 )
+    public static Boolean deserialize( byte[] in, int start )
     {
-        if ( type1 == type2 )
+        if ( ( in == null ) || ( in.length < 1 + start ) )
         {
-            return 0;
+            throw new RuntimeException( "Cannot extract a Boolean from a buffer with not enough bytes" );
         }
 
-        if ( type1 == null )
-        {
-            if ( type2 == null )
-            {
-                return 0;
-            }
-            else
-            {
-                return -1;
-            }
-        }
-        else
-        {
-            if ( type2 == null )
-            {
-                return 1;
-            }
-            else
-            {
-                return type1.compareTo( type2 );
-            }
-        }
+        return in[start] == 0x01;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Boolean deserialize( ByteBuffer buffer ) throws IOException
+    {
+        return buffer.get() != 0x00;
     }
 
 
@@ -136,8 +126,10 @@ public class BooleanSerializer implement
      * {@inheritDoc}
      */
     @Override
-    public Comparator<Boolean> getComparator()
+    public Boolean deserialize( BufferHandler bufferHandler ) throws IOException
     {
-        return comparator;
+        byte[] in = bufferHandler.read( 1 );
+
+        return deserialize( in );
     }
 }

Modified: labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/ByteArraySerializer.java
URL: http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/ByteArraySerializer.java?rev=1470325&r1=1470324&r2=1470325&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/ByteArraySerializer.java (original)
+++ labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/ByteArraySerializer.java Sun Apr 21 17:58:23 2013
@@ -22,7 +22,6 @@ package org.apache.mavibot.btree.seriali
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.util.Comparator;
 
 import org.apache.mavibot.btree.comparator.ByteArrayComparator;
 
@@ -32,18 +31,14 @@ import org.apache.mavibot.btree.comparat
  * 
  * @author <a href="mailto:labs@labs.apache.org">Mavibot labs Project</a>
  */
-public class ByteArraySerializer implements ElementSerializer<byte[]>
+public class ByteArraySerializer extends AbstractElementSerializer<byte[]>
 {
-    /** The associated comparator */
-    private final Comparator<byte[]> comparator;
-
-
     /**
      * Create a new instance of ByteArraySerializer
      */
     public ByteArraySerializer()
     {
-        comparator = new ByteArrayComparator();
+        super( new ByteArrayComparator() );
     }
 
 
@@ -99,11 +94,67 @@ public class ByteArraySerializer impleme
 
 
     /**
-     * {@inheritDoc}
+     * Serialize a byte[]
+     * 
+     * @param buffer the Buffer that will contain the serialized value
+     * @param start the position in the buffer we will store the serialized byte[]
+     * @param value the value to serialize
+     * @return The byte[] containing the serialized byte[]
      */
-    public byte[] deserialize( BufferHandler bufferHandler ) throws IOException
+    public static byte[] serialize( byte[] buffer, int start, byte[] element )
     {
-        byte[] in = bufferHandler.read( 4 );
+        int len = -1;
+
+        if ( element != null )
+        {
+            len = element.length;
+        }
+
+        switch ( len )
+        {
+            case 0:
+                buffer[start] = 0x00;
+                buffer[start + 1] = 0x00;
+                buffer[start + 2] = 0x00;
+                buffer[start + 3] = 0x00;
+
+                break;
+
+            case -1:
+                buffer[start] = ( byte ) 0xFF;
+                buffer[start + 1] = ( byte ) 0xFF;
+                buffer[start + 2] = ( byte ) 0xFF;
+                buffer[start + 3] = ( byte ) 0xFF;
+
+                break;
+
+            default:
+
+                buffer[start] = ( byte ) ( len >>> 24 );
+                buffer[start + 1] = ( byte ) ( len >>> 16 );
+                buffer[start + 2] = ( byte ) ( len >>> 8 );
+                buffer[start + 3] = ( byte ) ( len );
+
+                System.arraycopy( element, 0, buffer, 4 + start, len );
+        }
+
+        return buffer;
+
+    }
+
+
+    /**
+     * A static method used to deserialize a byte array from a byte array.
+     * 
+     * @param in The byte array containing the byte array
+     * @return A byte[]
+     */
+    public static byte[] deserialize( 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 );
 
@@ -117,19 +168,29 @@ public class ByteArraySerializer impleme
                 return null;
 
             default:
-                in = bufferHandler.read( len );
+                byte[] result = new byte[len];
+                System.arraycopy( in, 4, result, 0, len );
 
-                return in;
+                return result;
         }
     }
 
 
     /**
-     * {@inheritDoc}
+     * A static 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[] deserialize( ByteBuffer buffer ) throws IOException
+    public static byte[] deserialize( byte[] in, int start )
     {
-        int len = buffer.getInt();
+        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 )
         {
@@ -141,11 +202,10 @@ public class ByteArraySerializer impleme
                 return null;
 
             default:
-                byte[] bytes = new byte[len];
+                byte[] result = new byte[len];
+                System.arraycopy( in, 4 + start, result, 0, len );
 
-                buffer.get( bytes );
-
-                return bytes;
+                return result;
         }
     }
 
@@ -153,82 +213,25 @@ public class ByteArraySerializer impleme
     /**
      * {@inheritDoc}
      */
-    @Override
-    public int compare( byte[] type1, byte[] type2 )
+    public byte[] deserialize( BufferHandler bufferHandler ) throws IOException
     {
-        if ( type1 == type2 )
+        byte[] in = bufferHandler.read( 4 );
+
+        int len = IntSerializer.deserialize( in );
+
+        switch ( len )
         {
-            return 0;
-        }
+            case 0:
+                return new byte[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                in = bufferHandler.read( len );
 
-        if ( type1 == null )
-        {
-            if ( type2 == null )
-            {
-                return 0;
-            }
-            else
-            {
-                return -1;
-            }
-        }
-        else
-        {
-            if ( type2 == null )
-            {
-                return 1;
-            }
-            else
-            {
-                if ( type1.length < type2.length )
-                {
-                    int pos = 0;
-
-                    for ( byte b1 : type1 )
-                    {
-                        byte b2 = type2[pos];
-
-                        if ( b1 == b2 )
-                        {
-                            pos++;
-                        }
-                        else if ( b1 < b2 )
-                        {
-                            return -1;
-                        }
-                        else
-                        {
-                            return 1;
-                        }
-                    }
-
-                    return 1;
-                }
-                else
-                {
-                    int pos = 0;
-
-                    for ( byte b2 : type2 )
-                    {
-                        byte b1 = type1[pos];
-
-                        if ( b1 == b2 )
-                        {
-                            pos++;
-                        }
-                        else if ( b1 < b2 )
-                        {
-                            return -1;
-                        }
-                        else
-                        {
-                            return 1;
-                        }
-                    }
-
-                    return -11;
-                }
-            }
+                return in;
         }
     }
 
@@ -236,9 +239,25 @@ public class ByteArraySerializer impleme
     /**
      * {@inheritDoc}
      */
-    @Override
-    public Comparator<byte[]> getComparator()
+    public byte[] deserialize( ByteBuffer buffer ) throws IOException
     {
-        return comparator;
+        int len = buffer.getInt();
+
+        switch ( len )
+        {
+            case 0:
+                return new byte[]
+                    {};
+
+            case -1:
+                return null;
+
+            default:
+                byte[] bytes = new byte[len];
+
+                buffer.get( bytes );
+
+                return bytes;
+        }
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@labs.apache.org
For additional commands, e-mail: commits-help@labs.apache.org