You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2013/09/10 18:27:19 UTC

svn commit: r1521540 - in /directory/mavibot/trunk/mavibot/src: main/java/org/apache/directory/mavibot/btree/ test/java/org/apache/directory/mavibot/btree/

Author: elecharny
Date: Tue Sep 10 16:27:18 2013
New Revision: 1521540

URL: http://svn.apache.org/r1521540
Log:
o Replaced the ReferenceHolder by a CacheHolder everywhere we have a managed BTree
o The offsets are now set in the CacheHolder class
o Added a EhCache instance with a default value of 1000 
o Added a configuration element to set the cache size

Added:
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/CacheHolder.java
Modified:
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTree.java
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeConfiguration.java
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/Node.java
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
    directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/LeafTest.java

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTree.java?rev=1521540&r1=1521539&r2=1521540&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTree.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTree.java Tue Sep 10 16:27:18 2013
@@ -35,6 +35,9 @@ import java.util.LinkedList;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.locks.ReentrantLock;
 
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.config.CacheConfiguration;
+
 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
 import org.apache.directory.mavibot.btree.serializer.BufferHandler;
 import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
@@ -126,6 +129,15 @@ public class BTree<K, V> implements Clos
 
     private FileChannel journalChannel = null;
 
+    /** The cache associated with this BTree */
+    private Cache cache;
+
+    /** The cache size, default to 1000 elements */
+    private int cacheSize = DEFAULT_CACHE_SIZE;
+
+    /** The default number of pages to keep in memory */
+    private static final int DEFAULT_CACHE_SIZE = 1000;
+
 
     /**
      * Create a thread that is responsible of cleaning the transactions when
@@ -246,6 +258,7 @@ public class BTree<K, V> implements Clos
         writeBufferSize = configuration.getWriteBufferSize();
         btreeHeader.setAllowDuplicates( configuration.isAllowDuplicates() );
         type = configuration.getType();
+        cacheSize = configuration.getCacheSize();
 
         if ( comparator == null )
         {
@@ -277,7 +290,7 @@ public class BTree<K, V> implements Clos
         boolean allowDuplicates )
         throws IOException
     {
-        this( name, null, keySerializer, valueSerializer, DEFAULT_PAGE_SIZE, allowDuplicates );
+        this( name, null, keySerializer, valueSerializer, DEFAULT_PAGE_SIZE, allowDuplicates, DEFAULT_CACHE_SIZE );
     }
 
 
@@ -321,7 +334,7 @@ public class BTree<K, V> implements Clos
         int pageSize )
         throws IOException
     {
-        this( name, dataDir, keySerializer, valueSerializer, pageSize, false );
+        this( name, dataDir, keySerializer, valueSerializer, pageSize, false, DEFAULT_CACHE_SIZE );
     }
 
 
@@ -330,8 +343,18 @@ public class BTree<K, V> implements Clos
         int pageSize, boolean allowDuplicates )
         throws IOException
     {
+        this( name, dataDir, keySerializer, valueSerializer, pageSize, false, DEFAULT_CACHE_SIZE );
+    }
+
+
+    public BTree( String name, String dataDir, ElementSerializer<K> keySerializer,
+        ElementSerializer<V> valueSerializer,
+        int pageSize, boolean allowDuplicates, int cacheSize )
+        throws IOException
+    {
         btreeHeader = new BTreeHeader();
         btreeHeader.setName( name );
+
         if ( dataDir != null )
         {
             envDir = new File( dataDir );
@@ -340,6 +363,8 @@ public class BTree<K, V> implements Clos
         setPageSize( pageSize );
         writeBufferSize = DEFAULT_WRITE_BUFFER_SIZE;
 
+        this.cacheSize = cacheSize;
+
         this.keySerializer = keySerializer;
 
         btreeHeader.setKeySerializerFQCN( keySerializer.getClass().getName() );
@@ -436,6 +461,18 @@ public class BTree<K, V> implements Clos
             type = BTreeTypeEnum.IN_MEMORY;
         }
 
+        // Initialize the caches
+        CacheConfiguration cacheConfiguration = new CacheConfiguration();
+        cacheConfiguration.setName( "pages" );
+        cacheConfiguration.setEternal( true );
+        cacheConfiguration.setOverflowToDisk( false );
+        cacheConfiguration.setCacheLoaderTimeoutMillis( 0 );
+        cacheConfiguration.setMaxElementsInMemory( cacheSize );
+        cacheConfiguration.setMemoryStoreEvictionPolicy( "LRU" );
+
+        cache = new Cache( cacheConfiguration );
+        cache.initialise();
+
         // Initialize the txnManager thread
         //FIXME we should NOT create a new transaction manager thread for each BTree
         //createTransactionManager();
@@ -443,6 +480,15 @@ public class BTree<K, V> implements Clos
 
 
     /**
+     * Return the cache we use in this BTree
+     */
+    /* No qualifier */Cache getCache()
+    {
+        return cache;
+    }
+
+
+    /**
      * Close the BTree, cleaning up all the data structure
      */
     public void close() throws IOException
@@ -767,12 +813,12 @@ public class BTree<K, V> implements Clos
                         revision );
 
                     // Store the offset on disk in the page in memory
-                    ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
+                    ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( CacheHolder<Page<K, V>, K, V> ) holder )
                         .getOffset() );
 
                     // Store the last offset on disk in the page in memory
                     ( ( AbstractPage<K, V> ) modifiedPage )
-                        .setLastOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
+                        .setLastOffset( ( ( CacheHolder<Page<K, V>, K, V> ) holder )
                             .getLastOffset() );
                 }
 
@@ -1068,14 +1114,6 @@ public class BTree<K, V> implements Clos
                 // remain in memory.
                 ElementHolder<Page<K, V>, K, V> holder = recordManager.writePage( this, modifiedPage,
                     revision );
-
-                // Store the offset on disk in the page in memory
-                ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
-                    .getOffset() );
-
-                // Store the last offset on disk in the page in memory
-                ( ( AbstractPage<K, V> ) modifiedPage ).setLastOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
-                    .getLastOffset() );
             }
 
             // The root has just been modified, we haven't split it
@@ -1102,25 +1140,9 @@ public class BTree<K, V> implements Clos
                 ElementHolder<Page<K, V>, K, V> holderLeft = recordManager.writePage( this,
                     leftPage, revision );
 
-                // Store the offset on disk in the page
-                ( ( AbstractPage<K, V> ) splitResult.getLeftPage() )
-                    .setOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holderLeft ).getOffset() );
-
-                // Store the last offset on disk in the page
-                ( ( AbstractPage<K, V> ) splitResult.getLeftPage() )
-                    .setLastOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holderLeft ).getLastOffset() );
-
                 ElementHolder<Page<K, V>, K, V> holderRight = recordManager.writePage( this,
                     rightPage, revision );
 
-                // Store the offset on disk in the page
-                ( ( AbstractPage<K, V> ) splitResult.getRightPage() )
-                    .setOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holderRight ).getOffset() );
-
-                // Store the last offset on disk in the page
-                ( ( AbstractPage<K, V> ) splitResult.getRightPage() )
-                    .setLastOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holderRight ).getLastOffset() );
-
                 // Create the new rootPage
                 newRootPage = new Node<K, V>( this, revision, pivot, holderLeft, holderRight );
             }
@@ -1136,14 +1158,6 @@ public class BTree<K, V> implements Clos
             {
                 ElementHolder<Page<K, V>, K, V> holder = recordManager
                     .writePage( this, newRootPage, revision );
-
-                // Store the offset on disk in the page
-                ( ( AbstractPage<K, V> ) newRootPage ).setOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
-                    .getOffset() );
-
-                // Store the last offset on disk in the page
-                ( ( AbstractPage<K, V> ) newRootPage ).setLastOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
-                    .getLastOffset() );
             }
 
             rootPage = newRootPage;
@@ -1667,7 +1681,7 @@ public class BTree<K, V> implements Clos
     {
         if ( type == BTreeTypeEnum.MANAGED )
         {
-            return new ReferenceHolder<Page<K, V>, K, V>( this, value,
+            return new CacheHolder<Page<K, V>, K, V>( this, value,
                 value.getOffset(), value.getLastOffset() );
         }
         else

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeConfiguration.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeConfiguration.java?rev=1521540&r1=1521539&r2=1521540&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeConfiguration.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/BTreeConfiguration.java Tue Sep 10 16:27:18 2013
@@ -87,6 +87,9 @@ public class BTreeConfiguration<K, V>
     /** the type of BTree */
     private BTreeTypeEnum type;
 
+    /** The cache size */
+    private int cacheSize;
+
 
     /**
      * @return the pageSize
@@ -320,4 +323,21 @@ public class BTreeConfiguration<K, V>
         this.type = type;
     }
 
+
+    /**
+     * @return the cacheSize
+     */
+    public int getCacheSize()
+    {
+        return cacheSize;
+    }
+
+
+    /**
+     * @param cacheSize the cacheSize to set
+     */
+    public void setCacheSize( int cacheSize )
+    {
+        this.cacheSize = cacheSize;
+    }
 }

Added: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/CacheHolder.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/CacheHolder.java?rev=1521540&view=auto
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/CacheHolder.java (added)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/CacheHolder.java Tue Sep 10 16:27:18 2013
@@ -0,0 +1,183 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ *
+ */
+package org.apache.directory.mavibot.btree;
+
+
+import java.io.IOException;
+
+import net.sf.ehcache.Element;
+
+import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
+
+
+/**
+ * A Value holder. As we may not store all the values in memory (except for an in-memory
+ * BTree), we will use a SoftReference to keep a reference to a Value, and if it's null,
+ * then we will load the Value from the underlying physical support, using the offset. 
+ * 
+ * @param <E> The type for the stored element (either a value or a page)
+ * @param <K> The type of the BTree key
+ * @param <V> The type of the BTree value
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CacheHolder<E, K, V> implements ElementHolder<E, K, V>
+{
+    /** The BTree */
+    private BTree<K, V> btree;
+
+    /** The offset of the first {@link PageIO} storing the page on disk */
+    private long offset;
+
+    /** The offset of the last {@link PageIO} storing the page on disk */
+    private long lastOffset;
+
+
+    /**
+     * Create a new holder storing an offset and a SoftReference containing the element.
+     * 
+     * @param offset The offset in disk for this value
+     * @param element The element to store into a SoftReference
+     */
+    public CacheHolder( BTree<K, V> btree, Page<K, V> element, long offset, long lastOffset )
+    {
+        this.btree = btree;
+        this.offset = offset;
+        this.lastOffset = lastOffset;
+
+        if ( element instanceof Page<?, ?> )
+        {
+            ( ( AbstractPage<K, V> ) element ).setOffset( offset );
+            ( ( AbstractPage<K, V> ) element ).setLastOffset( lastOffset );
+        }
+
+        btree.getCache().put( new Element( offset, element ) );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     * @throws IOException 
+     * @throws EndOfFileExceededException 
+     */
+    @Override
+    public E getValue( BTree<K, V> btree ) throws EndOfFileExceededException, IOException
+    {
+        Element element = btree.getCache().get( offset );
+
+        if ( element == null )
+        {
+            // We haven't found the element in the cache, reload it
+            // We have to fetch the element from disk, using the offset now
+            Page<K, V> page = fetchElement( btree );
+
+            btree.getCache().put( new Element( offset, page ) );
+
+            return ( E ) page;
+        }
+
+        V value = ( V ) element.getObjectValue();
+
+        if ( value == null )
+        {
+            // We have to fetch the element from disk, using the offset now
+            Page<K, V> page = fetchElement( btree );
+
+            if ( page instanceof Page<?, ?> )
+            {
+                ( ( AbstractPage<K, V> ) page ).setOffset( offset );
+                ( ( AbstractPage<K, V> ) page ).setLastOffset( lastOffset );
+            }
+
+            btree.getCache().put( new Element( offset, page ) );
+
+            element = btree.getCache().get( offset );
+
+            return ( E ) page;
+        }
+        else
+        {
+            return ( E ) value;
+        }
+    }
+
+
+    /**
+     * Retrieve the value from the disk, using the BTree and offset
+     * @return The deserialized element (
+     * @throws IOException 
+     * @throws EndOfFileExceededException 
+     */
+    private Page<K, V> fetchElement( BTree<K, V> btree ) throws EndOfFileExceededException, IOException
+    {
+        Page<K, V> element = btree.getRecordManager().deserialize( btree, offset );
+
+        return element;
+    }
+
+
+    /**
+     * @return The offset of the first {@link PageIO} storing the data on disk
+     */
+    /* No qualifier */long getOffset()
+    {
+        return offset;
+    }
+
+
+    /**
+     * @return The offset of the last {@link PageIO} storing the data on disk
+     */
+    /* No qualifier */long getLastOffset()
+    {
+        return lastOffset;
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        try
+        {
+            E element = getValue( btree );
+
+            if ( element != null )
+            {
+                sb.append( btree.getName() ).append( "[" ).append( offset ).append( ", " ).append( lastOffset )
+                    .append( "]:" ).append( element );
+            }
+            else
+            {
+                sb.append( btree.getName() ).append( "[" ).append( offset ).append( ", " ).append( lastOffset )
+                    .append( "]" );
+            }
+        }
+        catch ( IOException ioe )
+        {
+            // Nothing we can do...
+        }
+
+        return sb.toString();
+    }
+}

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/Node.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/Node.java?rev=1521540&r1=1521539&r2=1521540&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/Node.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/Node.java Tue Sep 10 16:27:18 2013
@@ -82,7 +82,7 @@ import org.apache.directory.mavibot.btre
         // Create the children array, and store the left and right children
         if ( btree.isManaged() )
         {
-            children = ( ReferenceHolder<Page<K, V>, K, V>[] ) Array.newInstance( ReferenceHolder.class,
+            children = ( CacheHolder<Page<K, V>, K, V>[] ) Array.newInstance( CacheHolder.class,
                 btree.getPageSize() + 1 );
         }
         else
@@ -122,7 +122,7 @@ import org.apache.directory.mavibot.btre
         super( btree, revision, 1 );
 
         // Create the children array, and store the left and right children
-        children = ( ReferenceHolder<Page<K, V>, K, V>[] ) Array.newInstance( ReferenceHolder.class,
+        children = ( CacheHolder<Page<K, V>, K, V>[] ) Array.newInstance( CacheHolder.class,
             btree.getPageSize() + 1 );
 
         children[0] = leftPage;
@@ -1027,12 +1027,6 @@ import org.apache.directory.mavibot.btre
                 page,
                 revision );
 
-            // Store the offsets on disk in the page in memory
-            ( ( AbstractPage<K, V> ) page ).setOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
-                .getOffset() );
-            ( ( AbstractPage<K, V> ) page ).setLastOffset( ( ( ReferenceHolder<Page<K, V>, K, V> ) holder )
-                .getLastOffset() );
-
             return holder;
         }
         else

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java?rev=1521540&r1=1521539&r2=1521540&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java Tue Sep 10 16:27:18 2013
@@ -552,6 +552,9 @@ public class RecordManager
 
         Page<K, V> page = readPage( btree, rootPageIos );
 
+        ( ( AbstractPage<K, V> ) page ).setOffset( rootPageIos[0].getOffset() );
+        ( ( AbstractPage<K, V> ) page ).setLastOffset( rootPageIos[rootPageIos.length - 1].getOffset() );
+
         return page;
     }
 
@@ -646,7 +649,7 @@ public class RecordManager
                 long offset = OFFSET_SERIALIZER.deserialize( byteBuffer );
                 long lastOffset = OFFSET_SERIALIZER.deserialize( byteBuffer );
 
-                ElementHolder valueHolder = new ReferenceHolder( btree, null, offset, lastOffset );
+                ElementHolder valueHolder = new CacheHolder( btree, null, offset, lastOffset );
                 ( ( Node<K, V> ) page ).setValue( i, valueHolder );
 
                 K key = btree.getKeySerializer().deserialize( byteBuffer );
@@ -657,7 +660,7 @@ public class RecordManager
             long offset = OFFSET_SERIALIZER.deserialize( byteBuffer );
             long lastOffset = OFFSET_SERIALIZER.deserialize( byteBuffer );
 
-            ElementHolder valueHolder = new ReferenceHolder( btree, null, offset, lastOffset );
+            ElementHolder valueHolder = new CacheHolder( btree, null, offset, lastOffset );
             ( ( Node<K, V> ) page ).setValue( nodeNbElems, valueHolder );
         }
 
@@ -1728,7 +1731,7 @@ public class RecordManager
         // Build the resulting reference
         long offset = pageIos[0].getOffset();
         long lastOffset = pageIos[pageIos.length - 1].getOffset();
-        ElementHolder<Page<K, V>, K, V> valueHolder = new ReferenceHolder<Page<K, V>, K, V>( btree, newPage, offset,
+        ElementHolder<Page<K, V>, K, V> valueHolder = new CacheHolder<Page<K, V>, K, V>( btree, newPage, offset,
             lastOffset );
 
         if ( LOG_CHECK.isDebugEnabled() )

Modified: directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/LeafTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/LeafTest.java?rev=1521540&r1=1521539&r2=1521540&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/LeafTest.java (original)
+++ directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/LeafTest.java Tue Sep 10 16:27:18 2013
@@ -206,7 +206,11 @@ public class LeafTest
 
     /**
      * Check that deleting an element from a leaf with N/2 element works when we borrow
-     * an element in a left page with more than N/2 elements
+     * an element in a left page with more than N/2 elements.
+     * The BTree contains :
+     *            +--[1, 2, 3, 4, 5]
+     * [6, 10]-+--[6, 7, 8, 9]
+     *            +--[10, 11, 12, 13]
      * @throws IOException 
      */
     @Test
@@ -236,12 +240,9 @@ public class LeafTest
         right = insert( right, 12L, "v12" );
         right = insert( right, 13L, "v13" );
 
-        parent.children[0] = new ReferenceHolder<Page<Long, String>, Long, String>( null, left,
-            left.getOffset(), left.getLastOffset() );
-        parent.children[1] = new ReferenceHolder<Page<Long, String>, Long, String>( null, target,
-            target.getOffset(), target.getLastOffset() );
-        parent.children[2] = new ReferenceHolder<Page<Long, String>, Long, String>( null, right,
-            right.getOffset(), right.getLastOffset() );
+        parent.children[0] = new MemoryHolder( btree, left );
+        parent.children[1] = new MemoryHolder( btree, target );
+        parent.children[2] = new MemoryHolder( btree, right );
 
         // Update the parent
         parent.keys[0] = 6L;
@@ -309,12 +310,9 @@ public class LeafTest
         right = insert( right, 13L, "v13" );
         right = insert( right, 14L, "v14" );
 
-        parent.children[0] = new ReferenceHolder<Page<Long, String>, Long, String>( null, left,
-            left.getOffset(), left.getLastOffset() );
-        parent.children[1] = new ReferenceHolder<Page<Long, String>, Long, String>( null, target,
-            target.getOffset(), target.getLastOffset() );
-        parent.children[2] = new ReferenceHolder<Page<Long, String>, Long, String>( null, right,
-            right.getOffset(), right.getLastOffset() );
+        parent.children[0] = new MemoryHolder( null, left );
+        parent.children[1] = new MemoryHolder( null, target );
+        parent.children[2] = new MemoryHolder( null, right );
 
         // Update the parent
         parent.keys[0] = 6L;
@@ -382,12 +380,9 @@ public class LeafTest
         right = insert( right, 11L, "v11" );
         right = insert( right, 12L, "v12" );
 
-        parent.children[0] = new ReferenceHolder<Page<Long, String>, Long, String>( null, left,
-            left.getOffset(), left.getLastOffset() );
-        parent.children[1] = new ReferenceHolder<Page<Long, String>, Long, String>( null, target,
-            target.getOffset(), target.getLastOffset() );;
-        parent.children[2] = new ReferenceHolder<Page<Long, String>, Long, String>( null, right,
-            right.getOffset(), right.getLastOffset() );
+        parent.children[0] = new MemoryHolder( null, left );
+        parent.children[1] = new MemoryHolder( null, target );
+        parent.children[2] = new MemoryHolder( null, right );
 
         // Update the parent
         parent.keys[0] = 5L;