o added support for replacing value of an existing key
o fixed an issue in InMemoryBTree when a key already exists
o fixed an NPE in findLeftMost() findRightMost() of PersistedLeaf of a persisted sub-BTree
o made RevisionName serializable
o added and updated tests

diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractValueHolder.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractValueHolder.java
index 053d3e1..3038fbc 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractValueHolder.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractValueHolder.java
@@ -375,4 +375,25 @@
             addInBtree( value );
         }
     }
+    
+    
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public V replaceValueArray( V newValue )
+    {
+        if( isSubBtree() )
+        {
+            throw new IllegalStateException( "method is not applicable for the duplicate B-Trees" );
+        }
+        
+        V tmp = valueArray[0];
+        
+        nbArrayElems = 1;
+        valueArray[0] = newValue;
+        
+        return tmp;
+    }
+
 }
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java
index fb09eac..920afcc 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryBTree.java
@@ -389,6 +389,11 @@
         // a Node or a Leaf
         InsertResult<K, V> result = newBtreeHeader.getRootPage().insert( key, value, revision );
 
+        if ( result instanceof ExistsResult )
+        {
+            return result;
+        }
+
         if ( result instanceof ModifyResult )
         {
             ModifyResult<K, V> modifyResult = ( ( ModifyResult<K, V> ) result );
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java
index ba5e10f..83c18ab 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/InMemoryLeaf.java
@@ -748,12 +748,6 @@
 
         boolean valueExists = valueHolder.contains( value );
 
-        // Check we can add a new value
-        if ( !valueExists && !btree.isAllowDuplicates() )
-        {
-            throw new DuplicateValueNotAllowedException( "Duplicate values are not allowed" );
-        }
-
         if ( this.revision != revision )
         {
             // The page hasn't been modified yet, we need to copy it first
@@ -764,12 +758,12 @@
         valueHolder = newLeaf.values[pos];
         V replacedValue = null;
 
-        if ( !valueExists )
+        if ( !valueExists && btree.isAllowDuplicates() )
         {
             valueHolder.add( value );
             newLeaf.values[pos] = valueHolder;
         }
-        else
+        else if ( valueExists && btree.isAllowDuplicates() )
         {
             // As strange as it sounds, we need to remove the value to reinject it.
             // There are cases where the value retrieval just use one part of the
@@ -777,6 +771,10 @@
             replacedValue = valueHolder.remove( value );
             valueHolder.add( value );
         }
+        else if ( !btree.isAllowDuplicates() )
+        {
+            replacedValue = valueHolder.replaceValueArray( value );
+        }
 
         // Create the result
         InsertResult<K, V> result = new ModifyResult<K, V>( newLeaf, replacedValue );
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java
index b1d08db..97f5bb3 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java
@@ -844,26 +844,29 @@
         // Copy the keys and the values
         System.arraycopy( keys, 0, newLeaf.keys, 0, nbElems );
 
-        // It' not enough to copy the ValueHolder, we have to clone them
-        // as ValueHolders are mutable
-        int pos = 0;
-
-        for ( ValueHolder<V> valueHolder : values )
+        if ( values != null )
         {
-            try
+            // It' not enough to copy the ValueHolder, we have to clone them
+            // as ValueHolders are mutable
+            int pos = 0;
+            
+            for ( ValueHolder<V> valueHolder : values )
             {
-                newLeaf.values[pos++] = valueHolder.clone();
-            }
-            catch ( CloneNotSupportedException e )
-            {
-                // TODO Auto-generated catch block
-                e.printStackTrace();
-            }
-
-            // Stop when we have copied nbElems values
-            if ( pos == nbElems )
-            {
-                break;
+                try
+                {
+                    newLeaf.values[pos++] = valueHolder.clone();
+                }
+                catch ( CloneNotSupportedException e )
+                {
+                    // TODO Auto-generated catch block
+                    e.printStackTrace();
+                }
+                
+                // Stop when we have copied nbElems values
+                if ( pos == nbElems )
+                {
+                    break;
+                }
             }
         }
 
@@ -891,17 +894,6 @@
 
         boolean valueExists = valueHolder.contains( value );
 
-        // Check we can add a new value
-        if ( !valueExists && !btree.isAllowDuplicates() )
-        {
-            throw new DuplicateValueNotAllowedException( "Duplicate values are not allowed" );
-        }
-
-        if ( valueExists )
-        {
-            return ExistsResult.EXISTS;
-        }
-        
         if ( this.revision != revision )
         {
             // The page hasn't been modified yet, we need to copy it first
@@ -912,21 +904,24 @@
         valueHolder = newLeaf.values[pos];
         V replacedValue = null;
 
-        if ( !valueExists )
+        if ( !valueExists && btree.isAllowDuplicates() )
         {
             valueHolder.add( value );
             newLeaf.values[pos] = valueHolder;
         }
-        else
+        else if ( valueExists && btree.isAllowDuplicates() )
         {
-            // this block should be deleted after fixing MAVIBOT-39
             // As strange as it sounds, we need to remove the value to reinject it.
             // There are cases where the value retrieval just use one part of the
             // value only (typically for LDAP Entries, where we use the DN)
-            //replacedValue = valueHolder.remove( value );
-            //valueHolder.add( value );
+            replacedValue = valueHolder.remove( value );
+            valueHolder.add( value );
         }
-
+        else if ( !btree.isAllowDuplicates() )
+        {
+            replacedValue = valueHolder.replaceValueArray( value );
+        }
+        
         // Create the result
         InsertResult<K, V> result = new ModifyResult<K, V>( newLeaf, replacedValue );
         result.addCopiedPage( this );
@@ -1096,6 +1091,15 @@
      */
     public Tuple<K, V> findLeftMost() throws IOException
     {
+        K key = keys[0].getKey();
+        
+        boolean isSubTree = ( btree.getType() == PERSISTED_SUB );
+        
+        if ( isSubTree )
+        {
+            return new Tuple<K, V>( key, null );
+        }
+        
         ValueCursor<V> cursor = values[0].getCursor();
 
         try
@@ -1103,12 +1107,12 @@
             cursor.beforeFirst();
             if ( cursor.hasNext() )
             {
-                return new Tuple<K, V>( keys[0].getKey(), cursor.next() );
+                return new Tuple<K, V>( key, cursor.next() );
             }
             else
             {
                 // Null value
-                return new Tuple<K, V>( keys[0].getKey(), null );
+                return new Tuple<K, V>( key, null );
             }
         }
         finally
@@ -1123,6 +1127,16 @@
      */
     public Tuple<K, V> findRightMost() throws EndOfFileExceededException, IOException
     {
+        
+        K key = keys[nbElems - 1].getKey();
+        
+        boolean isSubTree = ( btree.getType() == PERSISTED_SUB );
+        
+        if ( isSubTree )
+        {
+            return new Tuple<K, V>( key, null );
+        }
+
         ValueCursor<V> cursor = values[nbElems - 1].getCursor();
 
         try
@@ -1131,12 +1145,12 @@
 
             if ( cursor.hasPrev() )
             {
-                return new Tuple<K, V>( keys[nbElems - 1].getKey(), cursor.prev() );
+                return new Tuple<K, V>( key, cursor.prev() );
             }
             else
             {
                 // Null value
-                return new Tuple<K, V>( keys[nbElems - 1].getKey(), null );
+                return new Tuple<K, V>( key, null );
             }
         }
         finally
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java
index ba6b3e0..3e9dea5 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java
@@ -410,6 +410,8 @@
                         }
                     }
 
+                    cursor.close();
+                    
                     return returnedValue;
                 }
                 else
@@ -636,6 +638,17 @@
     }
 
 
+    @Override
+    public V replaceValueArray( V newValue )
+    {
+        V val = super.replaceValueArray( newValue );
+        // The raw value is not anymore up to date with the content
+        isRawUpToDate = false;
+        
+        return val;
+    }
+
+
     /**
      * Deserialize the values stored in an array
      */
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/RevisionName.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/RevisionName.java
index 4d2445b..ae7a24f 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/RevisionName.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/RevisionName.java
@@ -19,6 +19,8 @@
  */
 package org.apache.directory.mavibot.btree;
 
+import java.io.Serializable;
+
 
 /**
  * A data structure that stores a revision associated to a BTree name. We use
@@ -26,7 +28,7 @@
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-/* no qualifier*/class RevisionName extends Tuple<Long, String>
+/* no qualifier*/class RevisionName extends Tuple<Long, String> implements Serializable
 {
     /**
      * A constructor for the RevisionName class
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/SpaceReclaimer.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/SpaceReclaimer.java
index b04a7d1..33747cb 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/SpaceReclaimer.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/SpaceReclaimer.java
@@ -83,7 +83,7 @@
 
         try
         {
-            LOG.debug( "Storing {} RevisionName of Copied page map", rm.copiedPageMap.size() );
+            LOG.debug( "Storing {} RevisionNames of Copied page map", rm.copiedPageMap.size() );
             
             OutputStream fileOut = new FileOutputStream( file );
             
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java
index 5f56511..6215d99 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java
@@ -69,6 +69,18 @@
      */
     V remove( V removedValue );
 
+    
+    /**
+     * Replaces the single value present in the array.
+     * 
+     * This is only applicable for B-Trees that don't
+     * support duplicate values.
+     *
+     * @param newValue the new value
+     * @return the value that was replaced
+     */
+    V replaceValueArray( V newValue );
+    
 
     /**
      * Create a clone of this instance
diff --git a/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeDuplicateKeyTest.java b/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeDuplicateKeyTest.java
index 68b7a88..1721992 100644
--- a/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeDuplicateKeyTest.java
+++ b/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeDuplicateKeyTest.java
@@ -37,6 +37,7 @@
 import org.apache.directory.mavibot.btree.serializer.IntSerializer;
 import org.apache.directory.mavibot.btree.serializer.LongSerializer;
 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.junit.Ignore;
 import org.junit.Test;
 
 
@@ -743,6 +744,7 @@
      * Test that a BTree which forbid duplicate values does not accept them
      */
     @Test(expected = DuplicateValueNotAllowedException.class)
+    @Ignore("this condition is removed")
     public void testBTreeForbidDups() throws IOException, BTreeAlreadyManagedException
     {
         BTree<Long, String> singleValueBtree = BTreeFactory.createInMemoryBTree( "test2", LongSerializer.INSTANCE,
diff --git a/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeTest.java b/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeTest.java
index f32cebf..751a257 100644
--- a/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeTest.java
+++ b/mavibot/src/test/java/org/apache/directory/mavibot/btree/InMemoryBTreeTest.java
@@ -1982,4 +1982,29 @@
 
         btree.close();
     }
+
+    
+    /**
+     * Test the overwriting of elements
+     */
+    @Test
+    public void testOverwrite() throws Exception
+    {
+        BTree<Integer, Integer> btree = BTreeFactory.createInMemoryBTree( "test", IntSerializer.INSTANCE,
+            IntSerializer.INSTANCE );
+
+        // Adding an element with a null value
+        btree.insert( 1, 1 );
+
+        assertTrue( btree.hasKey( 1 ) );
+
+        assertEquals( Integer.valueOf( 1 ), btree.get( 1 ) );
+        
+        btree.insert( 1, 10 );
+
+        assertTrue( btree.hasKey( 1 ) );
+        assertEquals( Integer.valueOf( 10 ), btree.get( 1 ) );
+
+        btree.close();
+    }
 }
diff --git a/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeBrowseTest.java b/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeBrowseTest.java
index 612479b..8346bde 100644
--- a/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeBrowseTest.java
+++ b/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeBrowseTest.java
@@ -36,6 +36,7 @@
 import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
 import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
+import org.apache.directory.mavibot.btree.serializer.IntSerializer;
 import org.apache.directory.mavibot.btree.serializer.LongSerializer;
 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
 import org.junit.After;
@@ -1107,6 +1108,30 @@
     }
     
     
+    /**
+     * Test the overwriting of elements
+     */
+    @Test
+    public void testOverwrite() throws Exception
+    {
+        btree.setAllowDuplicates( false );
+        
+        // Adding an element with a null value
+        btree.insert( 1L, "1" );
+
+        assertTrue( btree.hasKey( 1L ) );
+
+        assertEquals( "1", btree.get( 1L ) );
+        
+        btree.insert( 1L, "10" );
+
+        assertTrue( btree.hasKey( 1L ) );
+        assertEquals( "10", btree.get( 1L ) );
+
+        btree.close();
+    }
+
+    
     @Ignore("test used for debugging")
     @Test
     public void testAdd20Random() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException
diff --git a/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeDuplicateKeyTest.java b/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeDuplicateKeyTest.java
index c428797..8dfd94c 100644
--- a/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeDuplicateKeyTest.java
+++ b/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeDuplicateKeyTest.java
@@ -41,6 +41,7 @@
 import org.apache.directory.mavibot.btree.serializer.StringSerializer;
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -792,11 +793,40 @@
         cursor.close();
     }
 
+    
+    @Test
+    public void testFindLeftAndRightMosetInSubBTree() throws Exception
+    {
+        PersistedBTreeConfiguration<Integer, Integer> config = new PersistedBTreeConfiguration<Integer, Integer>();
+
+        config.setName( "test" );
+        config.setKeySerializer( IntSerializer.INSTANCE );
+        config.setValueSerializer( IntSerializer.INSTANCE );
+        config.setAllowDuplicates( false );
+        config.setBtreeType( BTreeTypeEnum.PERSISTED_SUB );
+
+        PersistedBTree<Integer, Integer> subBtree = new PersistedBTree<Integer, Integer>( config );
+        
+        subBtree.setRecordManager( recordManager1 );
+        
+        subBtree.insert( 1, 1 ); // the values will be discarded in this BTree type
+        subBtree.insert( 2, 2 );
+        subBtree.insert( 3, 3 );
+        subBtree.insert( 4, 4 );
+        subBtree.insert( 5, 5 );
+        
+        Tuple<Integer, Integer> t = subBtree.getRootPage().findLeftMost();
+        assertEquals( Integer.valueOf( 1 ), t.getKey() );
+        
+        t = subBtree.getRootPage().findRightMost();
+        assertEquals( Integer.valueOf( 5 ), t.getKey() );
+    }
 
     /**
      * Test that a BTree which forbid duplicate values does not accept them
      */
     @Test(expected = DuplicateValueNotAllowedException.class)
+    @Ignore("this condition is removed")
     public void testBTreeForbidDups() throws IOException, BTreeAlreadyManagedException
     {
         BTree<Long, String> singleValueBtree = recordManager1.addBTree( "test2", LongSerializer.INSTANCE,