o reinstated the copiedPage BTree (reverted the changes made in revision 1613792)
o updated SpaceReclaimer
diff --git a/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java b/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
index abfa120..d960174 100644
--- a/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
+++ b/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
@@ -48,6 +48,7 @@
import org.apache.directory.mavibot.btree.exception.RecordManagerException;
import org.apache.directory.mavibot.btree.serializer.ElementSerializer;
import org.apache.directory.mavibot.btree.serializer.IntSerializer;
+import org.apache.directory.mavibot.btree.serializer.LongArraySerializer;
import org.apache.directory.mavibot.btree.serializer.LongSerializer;
import org.apache.directory.mavibot.btree.util.Strings;
import org.slf4j.Logger;
@@ -101,13 +102,10 @@
private long endOfFileOffset;
/**
- * A Map used to hold the pages that were copied in a new version.
+ * A B-tree used to manage the page that has been copied in a new version.
* Those pages can be reclaimed when the associated version is dead.
- *
- * Note: the offsets are of AbstractPageS' while freeing the associated
- * PageIOs will be fetched and freed.
**/
- /* no qualifier */Map<RevisionName, long[]> copiedPageMap = null;
+ /* no qualifier */ BTree<RevisionName, long[]> copiedPageBtree;
/** A constant for an offset on a non existing page */
public static final long NO_PAGE = -1L;
@@ -178,6 +176,12 @@
/** The previous B-tree of B-trees header offset */
private long previousBtreeOfBtreesOffset = NO_PAGE;
+ /** The offset on the current copied pages B-tree */
+ /* no qualifier */ long currentCopiedPagesBtreeOffset = NO_PAGE;
+
+ /** The offset on the previous copied pages B-tree */
+ private long previousCopiedPagesBtreeOffset = NO_PAGE;
+
/** A lock to protect the transaction handling */
private ReentrantLock transactionLock = new ReentrantLock();
@@ -285,8 +289,6 @@
}
reclaimer = new SpaceReclaimer( this );
-
- copiedPageMap = reclaimer.readCopiedPageMap( file.getParentFile() );
runReclaimer();
}
catch ( Exception e )
@@ -387,6 +389,9 @@
// First, create the btree of btrees <NameRevision, Long>
createBtreeOfBtrees();
+ // Now, initialize the Copied Page B-tree
+ createCopiedPagesBtree();
+
// Inject these B-trees into the RecordManager. They are internal B-trees.
try
{
@@ -401,6 +406,16 @@
( ( PersistedBTree<NameRevision, Long> ) btreeOfBtrees ).getBtreeHeader() );
newBTreeHeaders.put( BTREE_OF_BTREES_NAME,
( ( PersistedBTree<NameRevision, Long> ) btreeOfBtrees ).getBtreeHeader() );
+
+ // The FreePage B-tree
+ manageSubBtree( copiedPageBtree );
+
+ currentCopiedPagesBtreeOffset = ( ( PersistedBTree<RevisionName, long[]> ) copiedPageBtree ).getBtreeHeader().getBTreeHeaderOffset();
+ updateRecordManagerHeader();
+
+ // Inject the CopiedPagesBTree into the currentBtreeHeaders map
+ currentBTreeHeaders.put( COPIED_PAGE_BTREE_NAME, ( ( PersistedBTree<RevisionName, long[]> ) copiedPageBtree ).getBtreeHeader() );
+ newBTreeHeaders.put( COPIED_PAGE_BTREE_NAME, ( ( PersistedBTree<RevisionName, long[]> ) copiedPageBtree ).getBtreeHeader() );
}
catch ( BTreeAlreadyManagedException btame )
{
@@ -433,6 +448,22 @@
/**
+ * Create the CopiedPagesBtree
+ */
+ private void createCopiedPagesBtree()
+ {
+ PersistedBTreeConfiguration<RevisionName, long[]> configuration = new PersistedBTreeConfiguration<RevisionName, long[]>();
+ configuration.setKeySerializer( RevisionNameSerializer.INSTANCE );
+ configuration.setName( COPIED_PAGE_BTREE_NAME );
+ configuration.setValueSerializer( LongArraySerializer.INSTANCE );
+ configuration.setBtreeType( BTreeTypeEnum.COPIED_PAGES_BTREE );
+ configuration.setCacheSize( PersistedBTree.DEFAULT_CACHE_SIZE );
+
+ copiedPageBtree = BTreeFactory.createPersistedBTree( configuration );
+ }
+
+
+ /**
* Load the BTrees from the disk.
*
* @throws InstantiationException
@@ -489,6 +520,12 @@
// The previous BOB offset
previousBtreeOfBtreesOffset = recordManagerHeader.getLong();
+ // The current Copied Pages B-tree offset
+ currentCopiedPagesBtreeOffset = recordManagerHeader.getLong();
+
+ // The previous Copied Pages B-tree offset
+ previousCopiedPagesBtreeOffset = recordManagerHeader.getLong();
+
// read the B-tree of B-trees
PageIO[] bobHeaderPageIos = readPageIOs( currentBtreeOfBtreesOffset, Long.MAX_VALUE );
@@ -497,6 +534,14 @@
loadBtree( bobHeaderPageIos, btreeOfBtrees );
+ // read the copied page B-tree
+ PageIO[] copiedPagesPageIos = readPageIOs( currentCopiedPagesBtreeOffset, Long.MAX_VALUE );
+
+ copiedPageBtree = BTreeFactory.<RevisionName, long[]> createPersistedBTree( BTreeTypeEnum.COPIED_PAGES_BTREE );
+ //( ( PersistedBTree<RevisionName, long[]> ) copiedPageBtree ).setBtreeHeaderOffset( currentCopiedPagesBtreeOffset );
+
+ loadBtree( copiedPagesPageIos, copiedPageBtree );
+
// Now, read all the B-trees from the btree of btrees
TupleCursor<NameRevision, Long> btreeCursor = btreeOfBtrees.browse();
Map<String, Long> loadedBtrees = new HashMap<String, Long>();
@@ -534,6 +579,7 @@
// TODO : clean up the old revisions...
+
// Now, we can load the real btrees using the offsets
for ( String btreeName : loadedBtrees.keySet() )
{
@@ -1620,7 +1666,9 @@
// Now, if this is a new B-tree, add it to the B-tree of B-trees
// Add the btree into the map of managed B-trees
- if ( ( btree.getType() != BTreeTypeEnum.BTREE_OF_BTREES ) && ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB ) )
+ if ( ( btree.getType() != BTreeTypeEnum.BTREE_OF_BTREES ) &&
+ ( btree.getType() != BTreeTypeEnum.COPIED_PAGES_BTREE ) &&
+ ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB ) )
{
managedBtrees.put( name, ( BTree<Object, Object> ) btree );
}
@@ -1633,7 +1681,9 @@
NameRevision nameRevision = new NameRevision( name, 0L );
// Inject it into the B-tree of B-tree
- if ( ( btree.getType() != BTreeTypeEnum.BTREE_OF_BTREES ) && ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB ) )
+ if ( ( btree.getType() != BTreeTypeEnum.BTREE_OF_BTREES ) &&
+ ( btree.getType() != BTreeTypeEnum.COPIED_PAGES_BTREE ) &&
+ ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB ) )
{
// We can safely increment the number of managed B-trees
nbBtree++;
@@ -1959,6 +2009,12 @@
// The offset of the copied pages B-tree
position = writeData( RECORD_MANAGER_HEADER_BYTES, position, previousBtreeOfBtreesOffset );
+ // The offset of the current B-tree of B-trees
+ position = writeData( RECORD_MANAGER_HEADER_BYTES, position, currentCopiedPagesBtreeOffset );
+
+ // The offset of the copied pages B-tree
+ position = writeData( RECORD_MANAGER_HEADER_BYTES, position, previousCopiedPagesBtreeOffset );
+
// Write the RecordManager header on disk
RECORD_MANAGER_HEADER_BUFFER.put( RECORD_MANAGER_HEADER_BYTES );
RECORD_MANAGER_HEADER_BUFFER.flip();
@@ -1970,10 +2026,10 @@
StringBuilder sb = new StringBuilder();
sb.append( "First free page : 0x" ).append( Long.toHexString( firstFreePage ) ).append( "\n" );
- sb.append( "Current BOB header : 0x" ).append( Long.toHexString( currentBtreeOfBtreesOffset ) )
- .append( "\n" );
- sb.append( "Previous BOB header : 0x" ).append( Long.toHexString( previousBtreeOfBtreesOffset ) )
- .append( "\n" );
+ sb.append( "Current BOB header : 0x" ).append( Long.toHexString( currentBtreeOfBtreesOffset ) ).append( "\n" );
+ sb.append( "Previous BOB header : 0x" ).append( Long.toHexString( previousBtreeOfBtreesOffset ) ).append( "\n" );
+ sb.append( "Current CPB header : 0x" ).append( Long.toHexString( currentCopiedPagesBtreeOffset ) ).append( "\n" );
+ sb.append( "Previous CPB header : 0x" ).append( Long.toHexString( previousCopiedPagesBtreeOffset ) ).append( "\n" );
if ( firstFreePage != NO_PAGE )
{
@@ -2039,6 +2095,7 @@
// Reset the old versions
previousBtreeOfBtreesOffset = -1L;
+ previousCopiedPagesBtreeOffset = -1L;
nbUpdateRMHeader.incrementAndGet();
}
@@ -2072,6 +2129,12 @@
previousBtreeOfBtreesOffset = currentBtreeOfBtreesOffset;
currentBtreeOfBtreesOffset = newBtreeOfBtreesOffset;
}
+
+ if ( newCopiedPageBtreeOffset != -1L )
+ {
+ previousCopiedPagesBtreeOffset = currentCopiedPagesBtreeOffset;
+ currentCopiedPagesBtreeOffset = newCopiedPageBtreeOffset;
+ }
}
@@ -2149,7 +2212,10 @@
pageOffsets[pos++] = ( ( AbstractPage<K, V> ) page ).getOffset();
}
- copiedPageMap.put( revisionName, pageOffsets );
+ copiedPageBtree.insert( revisionName, pageOffsets );
+
+ // Update the CopiedPageBtree offset
+ currentCopiedPagesBtreeOffset = ( ( AbstractBTree<RevisionName, long[]> ) copiedPageBtree ).getBtreeHeader().getBTreeHeaderOffset();
}
@@ -3191,6 +3257,7 @@
}
// Close the management B-trees
+ copiedPageBtree.close();
btreeOfBtrees.close();
managedBtrees.clear();
@@ -3201,8 +3268,6 @@
// And close the channel
fileChannel.close();
- reclaimer.storeCopiedPageMap( file.getParentFile() );
-
commit();
}
@@ -3524,7 +3589,7 @@
{
RevisionName revisionName = new RevisionName( revision, name );
- copiedPageMap.put( revisionName, copiedPages );
+ copiedPageBtree.insert( revisionName, copiedPages );
}
@@ -3542,6 +3607,11 @@
return;
}
+ if ( btree == copiedPageBtree )
+ {
+ return;
+ }
+
NameRevision nameRevision = new NameRevision( btree.getName(), rootPage.getRevision() );
( ( AbstractBTree<NameRevision, Long> ) btreeOfBtrees ).insert( nameRevision,
@@ -3692,7 +3762,10 @@
// Deal with standard B-trees
RevisionName revisionName = new RevisionName( revision, btree.getName() );
- copiedPageMap.put( revisionName, pageOffsets );
+ copiedPageBtree.insert( revisionName, pageOffsets );
+
+ // Update the RecordManager Copiedpage Offset
+ currentCopiedPagesBtreeOffset = ( ( PersistedBTree<RevisionName, long[]> ) copiedPageBtree ).getBtreeOffset();
}
else
{
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 2f29402..e119ecc 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
@@ -63,104 +63,7 @@
public SpaceReclaimer( RecordManager rm )
{
this.rm = rm;
- }
-
-
- /**
- * stores the copied page map, if not empty, in a file under the given directory
- *
- * @param dir the directory where mavibot database file is present
- */
- /* no qualifier */ void storeCopiedPageMap( File dir )
- {
- if ( rm.copiedPageMap.isEmpty() )
- {
- LOG.debug( "Copied page map is empty, nothing to store on disk." );
- return;
- }
-
- File file = new File( dir, COPIED_PAGE_MAP_DATA_FILE );
-
- try
- {
- LOG.debug( "Storing {} RevisionNames of Copied page map", rm.copiedPageMap.size() );
-
- OutputStream fileOut = new FileOutputStream( file );
-
- ObjectOutputStream objOut = new ObjectOutputStream( fileOut );
-
- objOut.writeObject( rm.copiedPageMap );
-
- objOut.close();
-
- LOG.debug( "Successfully stored copied page map in {}", file.getAbsolutePath() );
- }
- catch( Exception e )
- {
- LOG.warn( "Failed to store the copied page map in {}", file.getAbsolutePath() );
- LOG.warn( "", e );
- }
- }
-
-
- /**
- * reads the copied page map from the file named {@link #COPIED_PAGE_MAP_DATA_FILE} if it
- * is present under the given directory
- *
- * @param dir the directory where mavibot database file is present
- *
- * @return
- */
- /* no qualifier */ ConcurrentHashMap<RevisionName, long[]> readCopiedPageMap( File dir )
- {
-
- ConcurrentHashMap<RevisionName, long[]> map = new ConcurrentHashMap<RevisionName, long[]>();
-
- File file = new File( dir, COPIED_PAGE_MAP_DATA_FILE );
-
- if ( !file.exists() )
- {
- LOG.debug( "Copied page map store {} doesn't exist, returning empty map", file.getAbsolutePath() );
- return map;
- }
-
- try
- {
- LOG.debug( "Reading Copied page map data stored in {}", file.getAbsolutePath() );
-
- InputStream fileIn = new FileInputStream( file );
-
- ObjectInputStream objIn = new ObjectInputStream( fileIn );
-
- map = ( ConcurrentHashMap<RevisionName, long[]> ) objIn.readObject();
-
- objIn.close();
-
- LOG.debug( "Successfully read copied page map containing {} RevisionNames", map.size() );
- }
- catch( Exception e )
- {
- LOG.warn( "Failed to read the copied page map from {}", file.getAbsolutePath() );
- LOG.warn( "", e );
- }
- finally
- {
- boolean deleted = file.delete();
-
- // this is dangerous, cause during a subsequent restart the pages
- // will be freed again, but this time they might have been in use
- if( !deleted )
- {
- String warn = "Failed to delete the copied page map store " + file.getAbsolutePath() +
- " Make sure the approapriate permissions are given to delete this file by mavibot process." ;
- LOG.warn( warn );
-
- throw new RuntimeException( warn );
- }
- }
-
- return map;
- }
+ }
/**
@@ -207,7 +110,7 @@
rm.free( offsets );
RevisionName key = new RevisionName( rv, name );
- rm.copiedPageMap.remove( key );
+ rm.copiedPageBtree.delete( key );
}
}
}
@@ -228,21 +131,13 @@
*/
private List<RevisionOffset> getRevisions( String name ) throws Exception
{
- long nbElems = rm.copiedPageMap.size();
- //System.out.println( "Total number of entries in CPB " + nbElems );
-
- if ( nbElems == 0 )
- {
- return Collections.EMPTY_LIST;
- }
-
- Iterator<Map.Entry<RevisionName, long[]>> cursor = rm.copiedPageMap.entrySet().iterator();
+ TupleCursor<RevisionName, long[]> cursor = rm.copiedPageBtree.browse();
List<RevisionOffset> lst = new ArrayList<RevisionOffset>();
while ( cursor.hasNext() )
{
- Map.Entry<RevisionName, long[]> t = cursor.next();
+ Tuple<RevisionName, long[]> t = cursor.next();
RevisionName rn = t.getKey();
if ( name.equals( rn.getName() ) )
{