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 2014/05/17 15:31:25 UTC
svn commit: r1595477 [4/8] - in /directory/mavibot/trunk: ./ mavibot/img/
mavibot/src/main/java/org/apache/directory/mavibot/btree/
mavibot/src/main/java/org/apache/directory/mavibot/btree/comparator/
mavibot/src/main/java/org/apache/directory/mavibot/...
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PageIO.java Sat May 17 13:31:23 2014
@@ -34,25 +34,25 @@ import org.apache.directory.mavibot.btre
* Here is the logical structure of a PageIO :
* <pre>
* For a first page :
- *
+ *
* +----------+------+----------------------+
* | nextPage | size | XXXXXXXXXXXXXXXXXXXX |
* +----------+------+----------------------+
- *
+ *
* for any page but the first :
- *
+ *
* +----------+-----------------------------+
* | nextPage | XXXXXXXXXXXXXXXXXXXXXXXXXXX |
* +----------+-----------------------------+
- *
+ *
* for the last page :
* +----------+-----------------------------+
* | -1 | XXXXXXXXXXXXXXXXXXXXXXXXXXX |
* +----------+-----------------------------+
- *
+ *
* In any case, the page length is always PageSize.
* </pre>
- *
+ *
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
/* No qualifier*/class PageIO
@@ -70,7 +70,7 @@ import org.apache.directory.mavibot.btre
private long offset;
- /**
+ /**
* A default constructor for a PageIO
*/
/* no qualifier */PageIO()
@@ -81,7 +81,7 @@ import org.apache.directory.mavibot.btre
}
- /**
+ /**
* A constructor for a PageIO when we know the offset of this page on disk
*/
/* no qualifier */PageIO( long offset )
@@ -179,6 +179,45 @@ import org.apache.directory.mavibot.btre
}
+ /* no qualifier */PageIO copy( PageIO copy )
+ {
+ // The data
+ if ( data.isDirect() )
+ {
+ copy.data = ByteBuffer.allocateDirect( data.capacity() );
+ }
+ else
+ {
+ copy.data = ByteBuffer.allocate( data.capacity() );
+ }
+
+ // Save the original buffer position and limit
+ int start = data.position();
+ int limit = data.limit();
+
+ // The data is extended to get all the bytes in it
+ data.position( 0 );
+ data.limit( data.capacity() );
+
+ // Copy the data
+ copy.data.put( data );
+
+ // Restore the original buffer to the initial position and limit
+ data.position( start );
+ data.limit( limit );
+
+ // Set those position and limit in the copied buffer
+ copy.data.position( start );
+ copy.data.limit( limit );
+
+ // The size
+ copy.size = size;
+
+ // The offset and next page pointers are not copied.
+ return copy;
+ }
+
+
/**
* @see Object#toString()
*/
@@ -186,7 +225,7 @@ import org.apache.directory.mavibot.btre
{
StringBuilder sb = new StringBuilder();
- sb.append( "PageIO[offset:" ).append( offset );
+ sb.append( "PageIO[offset:0x" ).append( Long.toHexString( offset ) );
if ( size != -1 )
{
@@ -195,7 +234,7 @@ import org.apache.directory.mavibot.btre
if ( nextPage != -1L )
{
- sb.append( ", next:" ).append( nextPage );
+ sb.append( ", next:0x" ).append( Long.toHexString( nextPage ) );
}
sb.append( "]" );
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java Sat May 17 13:31:23 2014
@@ -24,9 +24,7 @@ import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
-import java.util.Map;
import java.util.concurrent.ConcurrentLinkedQueue;
-import java.util.concurrent.locks.ReentrantLock;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Status;
@@ -50,47 +48,44 @@ public class PersistedBTree<K, V> extend
/** The LoggerFactory used by this class */
protected static final Logger LOG = LoggerFactory.getLogger( PersistedBTree.class );
- /** The RecordManager if the BTree is managed */
- private RecordManager recordManager;
+ protected static final Logger LOG_PAGES = LoggerFactory.getLogger( "LOG_PAGES" );
- /** The cache associated with this BTree */
+ /** The cache associated with this B-tree */
protected Cache cache;
/** The default number of pages to keep in memory */
- static final int DEFAULT_CACHE_SIZE = 1000;
+ public static final int DEFAULT_CACHE_SIZE = 1000;
/** The cache size, default to 1000 elements */
protected int cacheSize = DEFAULT_CACHE_SIZE;
- /** A flag indicating if this BTree is a Sub BTree */
- private boolean isSubBtree = false;
-
- /** The number of stored Values before we switch to a BTree */
+ /** The number of stored Values before we switch to a B-tree */
private static final int DEFAULT_VALUE_THRESHOLD_UP = 8;
/** The number of stored Values before we switch back to an array */
private static final int DEFAULT_VALUE_THRESHOLD_LOW = 1;
- /** The configuration for the array <-> BTree switch */
+ /** The configuration for the array <-> B-tree switch */
/*No qualifier*/static int valueThresholdUp = DEFAULT_VALUE_THRESHOLD_UP;
/*No qualifier*/static int valueThresholdLow = DEFAULT_VALUE_THRESHOLD_LOW;
- /** A lock to protect the creation of the transaction */
- protected ReentrantLock createTransaction = new ReentrantLock();
-
+ /** The BtreeInfo offset */
+ private long btreeInfoOffset;
+
+ /** The internal recordManager */
+ private RecordManager recordManager;
/**
* Creates a new BTree, with no initialization.
*/
/* no qualifier */PersistedBTree()
{
- btreeHeader = new BTreeHeader();
setType( BTreeTypeEnum.PERSISTED );
}
/**
- * Creates a new persisted BTree using the BTreeConfiguration to initialize the
+ * Creates a new persisted B-tree using the BTreeConfiguration to initialize the
* BTree
*
* @param configuration The configuration to use
@@ -105,22 +100,16 @@ public class PersistedBTree<K, V> extend
throw new IllegalArgumentException( "BTree name cannot be null" );
}
- btreeHeader = new BTreeHeader();
- btreeHeader.setName( name );
- btreeHeader.setPageSize( configuration.getPageSize() );
- isSubBtree = configuration.isSubBtree();
-
- keySerializer = configuration.getKeySerializer();
- btreeHeader.setKeySerializerFQCN( keySerializer.getClass().getName() );
-
- valueSerializer = configuration.getValueSerializer();
- btreeHeader.setValueSerializerFQCN( valueSerializer.getClass().getName() );
+ setName( name );
+ setPageSize( configuration.getPageSize() );
+ setKeySerializer( configuration.getKeySerializer() );
+ setValueSerializer( configuration.getValueSerializer() );
+ setAllowDuplicates( configuration.isAllowDuplicates() );
+ setType( configuration.getBtreeType() );
readTimeOut = configuration.getReadTimeOut();
writeBufferSize = configuration.getWriteBufferSize();
- btreeHeader.setAllowDuplicates( configuration.isAllowDuplicates() );
cacheSize = configuration.getCacheSize();
- setType( BTreeTypeEnum.PERSISTED );
if ( keySerializer.getComparator() == null )
{
@@ -129,18 +118,35 @@ public class PersistedBTree<K, V> extend
// Create the first root page, with revision 0L. It will be empty
// and increment the revision at the same time
- rootPage = new PersistedLeaf<K, V>( this );
+ Page<K, V> rootPage = new PersistedLeaf<K, V>( this );
- if ( isSubBtree )
- {
- // The subBTree inherit its cache from its parent BTree
- this.cache = ( ( PersistedBTree<K, V> ) configuration.getParentBTree() ).getCache();
- this.writeLock = ( ( PersistedBTree<K, V> ) configuration.getParentBTree() ).getWriteLock();
- readTransactions = new ConcurrentLinkedQueue<ReadTransaction<K, V>>();
+ // Create a B-tree header, and initialize it
+ BTreeHeader<K, V> btreeHeader = new BTreeHeader<K, V>();
+ btreeHeader.setRootPage( rootPage );
+ btreeHeader.setBtree( this );
+
+ switch ( btreeType )
+ {
+ case BTREE_OF_BTREES :
+ case COPIED_PAGES_BTREE :
+ // We will create a new cache and a new readTransactions map
+ init( null );
+ currentBtreeHeader = btreeHeader;
+ break;
+
+ case PERSISTED_SUB :
+ init( ( PersistedBTree<K, V> ) configuration.getParentBTree() );
+ btreeRevisions.put( 0L, btreeHeader );
+ currentBtreeHeader = btreeHeader;
+ break;
+
+ default :
+ // We will create a new cache and a new readTransactions map
+ init( null );
+ btreeRevisions.put( 0L, btreeHeader );
+ currentBtreeHeader = btreeHeader;
+ break;
}
-
- // Now, initialize the BTree
- init();
}
@@ -149,17 +155,15 @@ public class PersistedBTree<K, V> extend
*
* @throws IOException If we get some exception while initializing the BTree
*/
- public void init()
+ public void init( BTree<K, V> parentBTree )
{
- if ( !isSubBtree )
+ if ( parentBTree == null )
{
// This is not a subBtree, we have to initialize the cache
// Create the queue containing the pending read transactions
readTransactions = new ConcurrentLinkedQueue<ReadTransaction<K, V>>();
- writeLock = new ReentrantLock();
-
// Initialize the caches
CacheConfiguration cacheConfiguration = new CacheConfiguration();
cacheConfiguration.setName( "pages" );
@@ -172,6 +176,11 @@ public class PersistedBTree<K, V> extend
cache = new Cache( cacheConfiguration );
cache.initialise();
}
+ else
+ {
+ this.cache = ((PersistedBTree<K, V>)parentBTree).getCache();
+ this.readTransactions = ((PersistedBTree<K, V>)parentBTree).getReadTransactions();
+ }
// Initialize the txnManager thread
//FIXME we should NOT create a new transaction manager thread for each BTree
@@ -191,15 +200,6 @@ public class PersistedBTree<K, V> extend
/**
* Return the cache we use in this BTree
*/
- /* No qualifier */ReentrantLock getWriteLock()
- {
- return writeLock;
- }
-
-
- /**
- * Return the cache we use in this BTree
- */
/* No qualifier */ConcurrentLinkedQueue<ReadTransaction<K, V>> getReadTransactions()
{
return readTransactions;
@@ -222,8 +222,6 @@ public class PersistedBTree<K, V> extend
}
cache.dispose();
-
- rootPage = null;
}
@@ -232,16 +230,16 @@ public class PersistedBTree<K, V> extend
*/
/* No qualifier*/long getBtreeOffset()
{
- return btreeHeader.getBTreeOffset();
+ return getBTreeHeader( getName() ).getBTreeHeaderOffset();
}
/**
- * @param btreeOffset the btreeOffset to set
+ * @param btreeOffset the B-tree header Offset to set
*/
- /* No qualifier*/void setBtreeOffset( long btreeOffset )
+ /* No qualifier*/void setBtreeHeaderOffset( long btreeHeaderOffset )
{
- btreeHeader.setBTreeOffset( btreeOffset );
+ getBTreeHeader( getName() ).setBTreeHeaderOffset( btreeHeaderOffset );
}
@@ -250,41 +248,14 @@ public class PersistedBTree<K, V> extend
*/
/* No qualifier*/long getRootPageOffset()
{
- return btreeHeader.getRootPageOffset();
- }
-
-
- /**
- * @param rootPageOffset the rootPageOffset to set
- */
- /* No qualifier*/void setRootPageOffset( long rootPageOffset )
- {
- btreeHeader.setRootPageOffset( rootPageOffset );
- }
-
-
- /**
- * @return the nextBTreeOffset
- */
- /* No qualifier*/long getNextBTreeOffset()
- {
- return btreeHeader.getNextBTreeOffset();
- }
-
-
- /**
- * @param nextBTreeOffset the nextBTreeOffset to set
- */
- /* No qualifier*/void setNextBTreeOffset( long nextBTreeOffset )
- {
- btreeHeader.setNextBTreeOffset( nextBTreeOffset );
+ return getBTreeHeader( getName() ).getRootPageOffset();
}
/**
* Gets the RecordManager for a managed BTree
*
- * @return The recordManager if the BTree is managed
+ * @return The recordManager if the B-tree is managed
*/
/* No qualifier */RecordManager getRecordManager()
{
@@ -299,6 +270,8 @@ public class PersistedBTree<K, V> extend
*/
/* No qualifier */void setRecordManager( RecordManager recordManager )
{
+ // The RecordManager is also the TransactionManager
+ transactionManager = recordManager;
this.recordManager = recordManager;
}
@@ -315,81 +288,158 @@ public class PersistedBTree<K, V> extend
* @return
* @throws IOException
*/
- protected Tuple<K, V> delete( K key, V value, long revision ) throws IOException
+ /* no qualifier */ Tuple<K, V> delete( K key, V value, long revision ) throws IOException
{
- writeLock.lock();
+ // We have to start a new transaction, which will be committed or rollbacked
+ // locally. This will duplicate the current BtreeHeader during this phase.
+ if ( revision == -1L )
+ {
+ revision = currentRevision.get() + 1;
+ }
try
{
- // If the key exists, the existing value will be replaced. We store it
- // to return it to the caller.
- Tuple<K, V> tuple = null;
-
// Try to delete the entry starting from the root page. Here, the root
// page may be either a Node or a Leaf
- DeleteResult<K, V> result = rootPage.delete( revision, key, value, null, -1 );
+ DeleteResult<K, V> result = processDelete( key, value, revision );
+ // Check that we have found the element to delete
if ( result instanceof NotPresentResult )
{
- // Key not found.
+ // We haven't found the element in the B-tree, just get out
+ // without updating the recordManager
+
return null;
}
- // Keep the oldRootPage so that we can later access it
- Page<K, V> oldRootPage = rootPage;
+ // The element was found, and removed
+ AbstractDeleteResult<K, V> deleteResult = ( AbstractDeleteResult<K, V> ) result;
- if ( result instanceof RemoveResult )
- {
- // The element was found, and removed
- RemoveResult<K, V> removeResult = ( RemoveResult<K, V> ) result;
+ Tuple<K, V> tuple = deleteResult.getRemovedElement();
- Page<K, V> modifiedPage = removeResult.getModifiedPage();
+ // If the B-tree is managed, we have to update the rootPage on disk
+ // Update the RecordManager header
- // Write the modified page on disk
- // Note that we don't use the holder, the new root page will
- // remain in memory.
- PageHolder<K, V> holder = writePage( modifiedPage, revision );
-
- // Store the offset on disk in the page in memory
- ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( PersistedPageHolder<K, V> ) holder )
- .getOffset() );
-
- // Store the last offset on disk in the page in memory
- ( ( AbstractPage<K, V> ) modifiedPage )
- .setLastOffset( ( ( PersistedPageHolder<K, V> ) holder )
- .getLastOffset() );
-
- // This is a new root
- rootPage = modifiedPage;
- tuple = removeResult.getRemovedElement();
- }
+ // Return the value we have found if it was modified
+ return tuple;
+ }
+ catch ( IOException ioe )
+ {
+ // if we've got an error, we have to rollback
+ throw ioe;
+ }
+ }
- // Decrease the number of elements in the current tree if the deletion is successful
- if ( tuple != null )
- {
- btreeHeader.decrementNbElems();
- // We have to update the rootPage on disk
- // Update the BTree header now
- recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) rootPage ).getOffset() );
- }
+ /**
+ * Insert the tuple into the B-tree rootPage, get back the new rootPage
+ */
+ private DeleteResult<K, V> processDelete( K key, V value, long revision ) throws IOException
+ {
+ // Get the current B-tree header, and delete the value from it
+ BTreeHeader<K, V> btreeHeader = getBTreeHeader( getName() );
- recordManager.addFreePages( this, result.getCopiedPages() );
+ // Try to delete the entry starting from the root page. Here, the root
+ // page may be either a Node or a Leaf
+ DeleteResult<K, V> result = btreeHeader.getRootPage().delete( key, value, revision);
- // Update the RecordManager header
- recordManager.updateRecordManagerHeader();
+ if ( result instanceof NotPresentResult )
+ {
+ // Key not found.
+ return result;
+ }
- // Store the created rootPage into the revision BTree, this will be stored in RecordManager only if revisions are set to keep
- recordManager.storeRootPage( this, rootPage );
+ // Create a new BTreeHeader
+ BTreeHeader<K, V> newBtreeHeader = btreeHeader.copy();
- // Return the value we have found if it was modified
- return tuple;
+ // Inject the old B-tree header into the pages to be freed
+ // if we are deleting an element from a management BTree
+ if ( ( btreeType == BTreeTypeEnum.BTREE_OF_BTREES ) || ( btreeType == BTreeTypeEnum.COPIED_PAGES_BTREE ) )
+ {
+ PageIO[] pageIos = recordManager.readPageIOs( btreeHeader.getBTreeHeaderOffset(), -1L );
+
+ for ( PageIO pageIo : pageIos )
+ {
+ recordManager.freedPages.add( pageIo );
+ }
}
- finally
+
+ // The element was found, and removed
+ AbstractDeleteResult<K, V> removeResult = ( AbstractDeleteResult<K, V> ) result;
+
+ // This is a new root
+ Page<K, V> newRootPage = removeResult.getModifiedPage();
+
+ // Write the modified page on disk
+ // Note that we don't use the holder, the new root page will
+ // remain in memory.
+ PageHolder<K, V> holder = writePage( newRootPage, revision );
+
+ // Decrease the number of elements in the current tree
+ newBtreeHeader.decrementNbElems();
+ newBtreeHeader.setRootPage( newRootPage );
+ newBtreeHeader.setRevision( revision );
+
+ // Write down the data on disk
+ long newBtreeHeaderOffset = recordManager.writeBtreeHeader( this, newBtreeHeader );
+
+
+ // Update the B-tree of B-trees with this new offset, if we are not already doing so
+ switch ( btreeType )
{
- // See above
- writeLock.unlock();
+ case PERSISTED :
+ // We have a new B-tree header to inject into the B-tree of btrees
+ recordManager.addInBtreeOfBtrees( getName(), revision, newBtreeHeaderOffset );
+
+ recordManager.addInCopiedPagesBtree( getName(), revision, result.getCopiedPages() );
+
+ // Store the new revision
+ storeRevision( newBtreeHeader, recordManager.isKeepRevisions() );
+
+ break;
+
+ case PERSISTED_SUB :
+ // Sub-B-trees are only updating the CopiedPage B-tree
+ recordManager.addInCopiedPagesBtree( getName(), revision, result.getCopiedPages() );
+
+ //btreeRevisions.put( revision, newBtreeHeader );
+
+ currentRevision.set( revision );
+
+
+ break;
+
+ case BTREE_OF_BTREES :
+ // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+ recordManager.updateRecordManagerHeader( newBtreeHeaderOffset, -1L );
+
+ // We can free the copied pages
+ recordManager.freePages( this, revision, result.getCopiedPages() );
+
+ // Store the new revision
+ storeRevision( newBtreeHeader, recordManager.isKeepRevisions() );
+
+ break;
+
+ case COPIED_PAGES_BTREE :
+ // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+ recordManager.updateRecordManagerHeader( -1L, newBtreeHeaderOffset );
+
+ // We can free the copied pages
+ recordManager.freePages( this, revision, result.getCopiedPages() );
+
+ // Store the new revision
+ storeRevision( newBtreeHeader, recordManager.isKeepRevisions() );
+
+ break;
+
+ default:
+ // Nothing to do for sub-btrees
+ break;
}
+
+ // Return the value we have found if it was modified
+ return result;
}
@@ -408,36 +458,79 @@ public class PersistedBTree<K, V> extend
*/
/* no qualifier */InsertResult<K, V> insert( K key, V value, long revision ) throws IOException
{
- if ( key == null )
+ // We have to start a new transaction, which will be committed or rollbacked
+ // locally. This will duplicate the current BtreeHeader during this phase.
+ if ( revision == -1L )
+ {
+ revision = currentRevision.get() + 1;
+ }
+
+ try
+ {
+ // Try to insert the new value in the tree at the right place,
+ // starting from the root page. Here, the root page may be either
+ // a Node or a Leaf
+ InsertResult<K, V> result = processInsert( key, value, revision );
+
+ // Return the value we have found if it was modified
+ return result;
+ }
+ catch ( IOException ioe )
{
- throw new IllegalArgumentException( "Key must not be null" );
+ throw ioe;
}
+ }
- // If the key exists, the existing value will be replaced. We store it
- // to return it to the caller.
- V modifiedValue = null;
+
+ private BTreeHeader<K, V> getBTreeHeader( String name )
+ {
+ if ( btreeType == BTreeTypeEnum.PERSISTED_SUB )
+ {
+ return getBtreeHeader();
+ }
+
+ BTreeHeader<K, V> btreeHeader = recordManager.getBTreeHeader( getName() );
- // Try to insert the new value in the tree at the right place,
- // starting from the root page. Here, the root page may be either
- // a Node or a Leaf
- InsertResult<K, V> result = rootPage.insert( revision, key, value );
+ return btreeHeader;
+ }
+
+ /**
+ * Insert the tuple into the B-tree rootPage, get back the new rootPage
+ */
+ private InsertResult<K, V> processInsert( K key, V value, long revision ) throws IOException
+ {
+ // Get the current B-tree header, and insert the value into it
+ BTreeHeader<K, V> btreeHeader = getBTreeHeader( getName() );
+ InsertResult<K, V> result = btreeHeader.getRootPage().insert( key, value, revision );
+
+ // Create a new BTreeHeader
+ BTreeHeader<K, V> newBtreeHeader = btreeHeader.copy();
+
+ // Inject the old B-tree header into the pages to be freed
+ // if we are inserting an element in a management BTree
+ if ( ( btreeType == BTreeTypeEnum.BTREE_OF_BTREES ) || ( btreeType == BTreeTypeEnum.COPIED_PAGES_BTREE ) )
+ {
+ PageIO[] pageIos = recordManager.readPageIOs( btreeHeader.getBTreeHeaderOffset(), -1L );
+
+ for ( PageIO pageIo : pageIos )
+ {
+ recordManager.freedPages.add( pageIo );
+ }
+ }
+
+ Page<K, V> newRootPage;
if ( result instanceof ModifyResult )
{
ModifyResult<K, V> modifyResult = ( ( ModifyResult<K, V> ) result );
- Page<K, V> modifiedPage = modifyResult.getModifiedPage();
+ newRootPage = modifyResult.getModifiedPage();
- // Write the modified page on disk
- // Note that we don't use the holder, the new root page will
- // remain in memory.
- writePage( modifiedPage, revision );
-
- // The root has just been modified, we haven't split it
- // Get it and make it the current root page
- rootPage = modifiedPage;
-
- modifiedValue = modifyResult.getModifiedValue();
+ // Increment the counter if we have inserted a new value
+ if ( modifyResult.getModifiedValue() == null )
+ {
+ newBtreeHeader.incrementNbElems();
+ }
}
else
{
@@ -448,9 +541,8 @@ public class PersistedBTree<K, V> extend
K pivot = splitResult.getPivot();
Page<K, V> leftPage = splitResult.getLeftPage();
Page<K, V> rightPage = splitResult.getRightPage();
- Page<K, V> newRootPage = null;
- // If the BTree is managed, we have to write the two pages that were created
+ // If the B-tree is managed, we have to write the two pages that were created
// and to keep a track of the two offsets for the upper node
PageHolder<K, V> holderLeft = writePage( leftPage, revision );
@@ -459,41 +551,81 @@ public class PersistedBTree<K, V> extend
// Create the new rootPage
newRootPage = new PersistedNode<K, V>( this, revision, pivot, holderLeft, holderRight );
- // If the BTree is managed, we now have to write the page on disk
- // and to add this page to the list of modified pages
- PageHolder<K, V> holder = writePage( newRootPage, revision );
-
- rootPage = newRootPage;
+ // Always increment the counter : we have added a new value
+ newBtreeHeader.incrementNbElems();
}
- // Increase the number of element in the current tree if the insertion is successful
- // and does not replace an element
- if ( modifiedValue == null )
- {
- btreeHeader.incrementNbElems();
- }
+ // Write the new root page on disk
+ LOG_PAGES.debug( "Writing the new rootPage revision {} for {}", revision, name );
+ writePage( newRootPage, revision );
+
+ // Update the new B-tree header
+ newBtreeHeader.setRootPage( newRootPage );
+ newBtreeHeader.setRevision( revision );
- // If the BTree is managed, we have to update the rootPage on disk
- // Update the RecordManager header
- if ( ( writeTransaction == null ) || !writeTransaction.isStarted() )
+ // Write down the data on disk
+ long newBtreeHeaderOffset = recordManager.writeBtreeHeader( this, newBtreeHeader );
+
+ // Update the B-tree of B-trees with this new offset, if we are not already doing so
+ switch ( btreeType )
{
- recordManager.updateRecordManagerHeader();
+ case PERSISTED :
+ // We have a new B-tree header to inject into the B-tree of btrees
+ recordManager.addInBtreeOfBtrees( getName(), revision, newBtreeHeaderOffset );
+
+ recordManager.addInCopiedPagesBtree( getName(), revision, result.getCopiedPages() );
+
+ // Store the new revision
+ storeRevision( newBtreeHeader, recordManager.isKeepRevisions() );
+
+ break;
+
+ case PERSISTED_SUB :
+ // Sub-B-trees are only updating the CopiedPage B-tree
+ recordManager.addInCopiedPagesBtree( getName(), revision, result.getCopiedPages() );
+
+ //btreeRevisions.put( revision, newBtreeHeader );
- // Update the BTree header now
- recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) rootPage ).getOffset() );
+ // Store the new revision
+ storeRevision( newBtreeHeader, recordManager.isKeepRevisions() );
- // Moved the free pages into the list of free pages
- recordManager.addFreePages( this, result.getCopiedPages() );
+ currentRevision.set( revision );
- // Store the created rootPage into the revision BTree, this will be stored in RecordManager only if revisions are set to keep
- recordManager.storeRootPage( this, rootPage );
+ break;
+
+ case BTREE_OF_BTREES :
+ // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+ recordManager.updateRecordManagerHeader( newBtreeHeaderOffset, -1L );
+
+ // We can free the copied pages
+ recordManager.freePages( this, revision, result.getCopiedPages() );
+
+ // Store the new revision
+ storeRevision( newBtreeHeader, recordManager.isKeepRevisions() );
+
+ break;
+
+ case COPIED_PAGES_BTREE :
+ // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+ recordManager.updateRecordManagerHeader( -1L, newBtreeHeaderOffset );
+
+ // We can free the copied pages
+ recordManager.freePages( this, revision, result.getCopiedPages() );
+
+ // Store the new revision
+ storeRevision( newBtreeHeader, recordManager.isKeepRevisions() );
+
+ break;
+
+ default:
+ // Nothing to do for sub-btrees
+ break;
}
- // Return the value we have found if it was modified
+ // Get the new root page and make it the current root page
return result;
}
-
/**
* Write the data in the ByteBuffer, and eventually on disk if needed.
*
@@ -541,21 +673,9 @@ public class PersistedBTree<K, V> extend
*/
private PageHolder<K, V> writePage( Page<K, V> modifiedPage, long revision ) throws IOException
{
- if ( ( writeTransaction != null ) && writeTransaction.isStarted() )
- {
- Map<Page<?, ?>, BTree<?, ?>> pendingPages = recordManager.getPendingPages();
- pendingPages.put( modifiedPage, this );
-
- PageHolder<K, V> pageHolder = new PageHolder<K, V>( this, modifiedPage );
-
- return pageHolder;
- }
- else
- {
- PageHolder<K, V> pageHolder = recordManager.writePage( this, modifiedPage, revision );
+ PageHolder<K, V> pageHolder = recordManager.writePage( this, modifiedPage, revision );
- return pageHolder;
- }
+ return pageHolder;
}
/**
@@ -573,60 +693,76 @@ public class PersistedBTree<K, V> extend
/**
- * Starts a transaction
+ * Get the current rootPage
+ *
+ * @return The rootPage
*/
- public void beginTransaction()
+ public Page<K, V> getRootPage()
{
- createTransaction.lock();
-
- if ( writeTransaction == null )
- {
- writeTransaction = new WriteTransaction( recordManager );
- }
+ return getBTreeHeader( getName() ).getRootPage();
+ }
- createTransaction.unlock();
- writeTransaction.start();
+ /* no qualifier */void setRootPage( Page<K, V> root )
+ {
+ getBTreeHeader( getName() ).setRootPage( root );
}
/**
- * Commits a transaction
+ * @return the btreeInfoOffset
*/
- public void commit()
+ public long getBtreeInfoOffset()
{
- createTransaction.lock();
-
- if ( writeTransaction == null )
- {
- writeTransaction = new WriteTransaction( recordManager );
- }
+ return btreeInfoOffset;
+ }
- createTransaction.unlock();
- writeTransaction.commit();
+ /**
+ * @param btreeInfoOffset the btreeInfoOffset to set
+ */
+ public void setBtreeInfoOffset( long btreeInfoOffset )
+ {
+ this.btreeInfoOffset = btreeInfoOffset;
}
/**
- * Rollback a transaction
+ * {@inheritDoc}
*/
- public void rollback()
+ protected ReadTransaction<K, V> beginReadTransaction()
{
- createTransaction.lock();
+ BTreeHeader<K, V> btreeHeader = getBTreeHeader( getName() );
- if ( writeTransaction == null )
- {
- writeTransaction = new WriteTransaction( recordManager );
- }
+ ReadTransaction<K, V> readTransaction = new ReadTransaction<K, V>( recordManager, btreeHeader, readTransactions );
- createTransaction.unlock();
+ readTransactions.add( readTransaction );
- writeTransaction.rollback();
+ return readTransaction;
}
+
+
+ /**
+ * {@inheritDoc}
+ */
+ protected ReadTransaction<K, V> beginReadTransaction( long revision )
+ {
+ BTreeHeader<K, V> btreeHeader = getBtreeHeader( revision );
+ if ( btreeHeader != null )
+ {
+ ReadTransaction<K, V> readTransaction = new ReadTransaction<K, V>( recordManager, btreeHeader, readTransactions );
+ readTransactions.add( readTransaction );
+ return readTransaction;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
/**
* @see Object#toString()
@@ -636,12 +772,12 @@ public class PersistedBTree<K, V> extend
StringBuilder sb = new StringBuilder();
sb.append( "Managed BTree" );
- sb.append( "[" ).append( btreeHeader.getName() ).append( "]" );
- sb.append( "( pageSize:" ).append( btreeHeader.getPageSize() );
+ sb.append( "[" ).append( getName() ).append( "]" );
+ sb.append( "( pageSize:" ).append( getPageSize() );
- if ( rootPage != null )
+ if ( getBTreeHeader( getName() ).getRootPage() != null )
{
- sb.append( ", nbEntries:" ).append( btreeHeader.getNbElems() );
+ sb.append( ", nbEntries:" ).append( getBTreeHeader( getName() ).getNbElems() );
}
else
{
@@ -659,10 +795,10 @@ public class PersistedBTree<K, V> extend
sb.append( keySerializer.getComparator().getClass().getSimpleName() );
}
- sb.append( ", DuplicatesAllowed: " ).append( btreeHeader.isAllowDuplicates() );
+ sb.append( ", DuplicatesAllowed: " ).append( isAllowDuplicates() );
sb.append( ") : \n" );
- sb.append( rootPage.dumpPage( "" ) );
+ sb.append( getBTreeHeader( getName() ).getRootPage().dumpPage( "" ) );
return sb.toString();
}
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeBuilder.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeBuilder.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeBuilder.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeBuilder.java Sat May 17 13:31:23 2014
@@ -32,7 +32,7 @@ import org.apache.directory.mavibot.btre
/**
- * A BTree builder that builds a tree from the bottom.
+ * A B-tree builder that builds a tree from the bottom.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@@ -138,7 +138,7 @@ public class PersistedBTreeBuilder<K, V>
rm.updateBtreeHeader( btree, ( ( AbstractPage<K, V> ) rootPage ).getOffset() );
- rm.addFreePages( btree, Arrays.asList( btree.getRootPage() ) );
+ rm.freePages( btree, btree.getRootPage().getRevision(), Arrays.asList( btree.getRootPage() ) );
( ( AbstractBTree<K, V> ) btree ).setRootPage( rootPage );
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeConfiguration.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeConfiguration.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeConfiguration.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTreeConfiguration.java Sat May 17 13:31:23 2014
@@ -25,11 +25,11 @@ import org.apache.directory.mavibot.btre
/**
* The B+Tree Configuration. This class can be used to store all the configurable
- * parameters used by the BTree class
- *
+ * parameters used by the B-tree class
+ *
* @param <K> The type for the keys
* @param <V> The type for the stored values
- *
+ *
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class PersistedBTreeConfiguration<K, V>
@@ -40,23 +40,23 @@ public class PersistedBTreeConfiguration
/** The size of the buffer used to write data in disk */
private int writeBufferSize = BTree.DEFAULT_WRITE_BUFFER_SIZE;
- /** The Key and Value serializer used for this tree. If none is provided,
- * the BTree will deduce the serializer to use from the generic type, and
+ /** The Key and Value serializer used for this tree. If none is provided,
+ * the B-tree will deduce the serializer to use from the generic type, and
* use the default Java serialization */
private ElementSerializer<K> keySerializer;
private ElementSerializer<V> valueSerializer;
- /** The BTree name */
+ /** The B-tree name */
private String name;
- /** The path where the BTree file will be stored. Default to the local
+ /** The path where the B-tree file will be stored. Default to the local
* temporary directory.
*/
private String filePath;
- /**
+ /**
* The maximum delay to wait before a revision is considered as unused.
- * This delay is necessary so that a read that does not ends does not
+ * This delay is necessary so that a read that does not ends does not
* hold a revision in memory forever.
* The default value is 10000 (10 seconds). If the value is 0 or below,
* the delay is considered as infinite
@@ -66,13 +66,13 @@ public class PersistedBTreeConfiguration
/** Flag to enable duplicate key support */
private boolean allowDuplicates;
- /** A flag set when the BTree is a sub btree */
- private boolean isSubBtree = false;
+ /** The B-tree type */
+ private BTreeTypeEnum btreeType = BTreeTypeEnum.PERSISTED;
/** The cache size, if it's <= 0, we don't have cache */
private int cacheSize;
- /** The inherited BTree if we create a sub BTree */
+ /** The inherited B-tree if we create a sub B-tree */
private BTree<?, V> parentBTree;
@@ -224,10 +224,10 @@ public class PersistedBTreeConfiguration
/**
* enable duplicate key support
- *
+ *
* @param allowDuplicates
- * @throws IllegalStateException if the btree was already initialized or when tried to turn off duplicate suport on
- * an existing btree containing duplicate keys
+ * @throws IllegalStateException if the B-tree was already initialized or when tried to turn off duplicate suport on
+ * an existing B-tree containing duplicate keys
*/
public void setAllowDuplicates( boolean allowDuplicates )
{
@@ -272,19 +272,19 @@ public class PersistedBTreeConfiguration
/**
- * @return True if this is a sub btree, false otherwise
+ * @return The BtreeType for this Btree
*/
- public boolean isSubBtree()
+ public BTreeTypeEnum getBtreeType()
{
- return isSubBtree;
+ return btreeType;
}
/**
- * @param isSubBtree True if the BTree will be a sub btree, false otherwise
+ * @param btreeType The BtreeType
*/
- public void setSubBtree( boolean isSubBtree )
+ public void setBtreeType( BTreeTypeEnum btreeType )
{
- this.isSubBtree = isSubBtree;
+ this.btreeType = btreeType;
}
}
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedLeaf.java Sat May 17 13:31:23 2014
@@ -71,7 +71,7 @@ import org.apache.directory.mavibot.btre
/**
* {@inheritDoc}
*/
- public InsertResult<K, V> insert( long revision, K key, V value ) throws IOException
+ public InsertResult<K, V> insert( K key, V value, long revision ) throws IOException
{
// Find the key into this leaf
int pos = findPos( key );
@@ -116,7 +116,7 @@ import org.apache.directory.mavibot.btre
* {@inheritDoc}
*/
@SuppressWarnings("unchecked")
- public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
+ /* no qualifier */ DeleteResult<K, V> delete( K key, V value, long revision, Page<K, V> parent, int parentPos )
throws IOException
{
// Check that the leaf is not empty
@@ -519,7 +519,7 @@ import org.apache.directory.mavibot.btre
}
else
{
- throw KEY_NOT_FOUND_EXCEPTION;
+ throw KeyNotFoundException.INSTANCE;
}
}
@@ -561,7 +561,7 @@ import org.apache.directory.mavibot.btre
}
else
{
- throw KEY_NOT_FOUND_EXCEPTION;
+ throw KeyNotFoundException.INSTANCE;
}
}
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java Sat May 17 13:31:23 2014
@@ -120,7 +120,7 @@ import java.util.List;
/**
* {@inheritDoc}
*/
- public InsertResult<K, V> insert( long revision, K key, V value ) throws IOException
+ public InsertResult<K, V> insert( K key, V value, long revision ) throws IOException
{
// Find the key into this leaf
int pos = findPos( key );
@@ -136,7 +136,7 @@ import java.util.List;
Page<K, V> child = children[pos].getValue();
// and insert the <K, V> into this child
- InsertResult<K, V> result = child.insert( revision, key, value );
+ InsertResult<K, V> result = child.insert( key, value, revision );
// Ok, now, we have injected the <K, V> tuple down the tree. Let's check
// the result to see if we have to split the current page
@@ -567,7 +567,7 @@ import java.util.List;
/**
* {@inheritDoc}
*/
- public DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos )
+ /* no qualifier */ DeleteResult<K, V> delete( K key, V value, long revision, Page<K, V> parent, int parentPos )
throws IOException
{
// We first try to delete the element from the child it belongs to
@@ -582,12 +582,12 @@ import java.util.List;
{
index = -( pos + 1 );
child = children[-pos].getValue();
- deleteResult = child.delete( revision, key, value, this, -pos );
+ deleteResult = ((AbstractPage<K, V>)child).delete( key, value, revision, this, -pos );
}
else
{
child = children[pos].getValue();
- deleteResult = child.delete( revision, key, value, this, pos );
+ deleteResult = ((AbstractPage<K, V>)child).delete( key, value, revision, this, pos );
}
// If the key is not present in the tree, we simply return
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedValueHolder.java Sat May 17 13:31:23 2014
@@ -28,6 +28,7 @@ import java.util.UUID;
import org.apache.directory.mavibot.btree.exception.BTreeAlreadyCreatedException;
import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
import org.apache.directory.mavibot.btree.exception.BTreeCreationException;
+import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
import org.apache.directory.mavibot.btree.serializer.IntSerializer;
import org.apache.directory.mavibot.btree.serializer.LongSerializer;
@@ -82,7 +83,7 @@ import org.apache.directory.mavibot.btre
/**
* Creates a new instance of a ValueHolder, containing Values. This constructor is called
- * whe we need to create a new ValueHolder with deserialized values.
+ * when we need to create a new ValueHolder with deserialized values.
*
* @param parentBtree The parent BTree
* @param values The Values stored in the ValueHolder
@@ -248,12 +249,13 @@ import org.apache.directory.mavibot.btre
configuration.setName( UUID.randomUUID().toString() );
configuration.setValueSerializer( valueSerializer );
configuration.setParentBTree( parentBtree );
- configuration.setSubBtree( true );
+ configuration.setBtreeType( BTreeTypeEnum.PERSISTED_SUB );
valueBtree = BTreeFactory.createPersistedBTree( configuration );
try
{
+ // The sub-btree will not be added into the BOB.
parentBtree.getRecordManager().manage( valueBtree, RecordManager.INTERNAL_BTREE );
raw = null;
}
@@ -419,6 +421,12 @@ import org.apache.directory.mavibot.btre
e.printStackTrace();
return null;
}
+ catch ( KeyNotFoundException knfe )
+ {
+ // TODO Auto-generated catch block
+ knfe.printStackTrace();
+ return null;
+ }
}
else
{
@@ -655,7 +663,7 @@ import org.apache.directory.mavibot.btre
long offset = LongSerializer.deserialize( raw );
// and reload the sub btree
- valueBtree = parentBtree.getRecordManager().loadDupsBTree( offset );
+ valueBtree = parentBtree.getRecordManager().loadDupsBtree( offset, parentBtree );
}
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/ReadTransaction.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/ReadTransaction.java?rev=1595477&r1=1595476&r2=1595477&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/ReadTransaction.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/ReadTransaction.java Sat May 17 13:31:23 2014
@@ -21,6 +21,7 @@ package org.apache.directory.mavibot.btr
import java.util.Date;
+import java.util.concurrent.ConcurrentLinkedQueue;
/**
@@ -35,7 +36,7 @@ import java.util.Date;
* A Transaction can be hold for quite a long time, for instance while doing
* a browse against a big BTree. At some point, transactions which are pending
* for too long will be closed by the transaction manager.
- *
+ *
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*
* @param <K> The type for the Key
@@ -49,26 +50,54 @@ public class ReadTransaction<K, V>
/** The date of creation */
private long creationDate;
- /** The revision on which we are having a transaction */
- private volatile Page<K, V> root;
+ /** The associated B-tree header */
+ private BTreeHeader<K, V> btreeHeader;
/** A flag used to tell if a transaction is closed or not */
private volatile boolean closed;
-
-
+
+ /** The list of read transactions being executed */
+ private ConcurrentLinkedQueue<ReadTransaction<K, V>> readTransactions;
+
+ /** The reference to the recordManager, if any */
+ private RecordManager recordManager;
+
+ /**
+ * Creates a new transaction instance
+ *
+ * @param btreeHeader The BtreeHeader we will use for this read transaction
+ */
+ public ReadTransaction( RecordManager recordManager, BTreeHeader<K, V> btreeHeader, ConcurrentLinkedQueue<ReadTransaction<K, V>> readTransactions )
+ {
+ if ( btreeHeader != null )
+ {
+ this.revision = btreeHeader.getRevision();
+ this.creationDate = System.currentTimeMillis();
+ this.btreeHeader = btreeHeader;
+ this.recordManager = recordManager;
+ closed = false;
+ }
+
+ this.readTransactions = readTransactions;
+ }
+
+
/**
* Creates a new transaction instance
- *
- * @param root The associated root
- * @param revision The revision this transaction is using
- * @param creationDate The creation date for this transaction
- */
- public ReadTransaction( Page<K, V> root, long revision, long creationDate )
- {
- this.revision = revision;
- this.creationDate = creationDate;
- this.root = root;
- closed = false;
+ *
+ * @param btreeHeader The BtreeHeader we will use for this read transaction
+ */
+ public ReadTransaction( BTreeHeader<K, V> btreeHeader, ConcurrentLinkedQueue<ReadTransaction<K, V>> readTransactions )
+ {
+ if ( btreeHeader != null )
+ {
+ this.revision = btreeHeader.getRevision();
+ this.creationDate = System.currentTimeMillis();
+ this.btreeHeader = btreeHeader;
+ closed = false;
+ }
+
+ this.readTransactions = readTransactions;
}
@@ -82,20 +111,20 @@ public class ReadTransaction<K, V>
/**
- * @return the associated root
+ * @return the creationDate
*/
- public Page<K, V> getRoot()
+ public long getCreationDate()
{
- return root;
+ return creationDate;
}
/**
- * @return the creationDate
+ * @return the btreeHeader
*/
- public long getCreationDate()
+ public BTreeHeader<K, V> getBtreeHeader()
{
- return creationDate;
+ return btreeHeader;
}
@@ -104,8 +133,18 @@ public class ReadTransaction<K, V>
*/
public void close()
{
- root = null;
closed = true;
+
+ // Remove the transaction from the list of opened transactions
+ readTransactions.remove( this );
+
+ // and push the
+ if ( recordManager != null )
+ {
+ recordManager.releaseTransaction( this );
+ }
+
+ // Now, get back the copied pages
}