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 2015/11/02 00:01:01 UTC
svn commit: r1711861 [3/4] - in
/directory/mavibot/branches/single-value/mavibot/src:
main/java/org/apache/directory/mavibot/btree/
main/java/org/apache/directory/mavibot/btree/exception/
test/java/org/apache/directory/mavibot/btree/
Modified: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java?rev=1711861&r1=1711860&r2=1711861&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java Sun Nov 1 23:01:00 2015
@@ -26,6 +26,7 @@ import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -41,6 +42,7 @@ import java.util.concurrent.locks.Reentr
import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
import org.apache.directory.mavibot.btree.exception.BTreeCreationException;
+import org.apache.directory.mavibot.btree.exception.CursorException;
import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
import org.apache.directory.mavibot.btree.exception.FileException;
import org.apache.directory.mavibot.btree.exception.InvalidOffsetException;
@@ -98,9 +100,6 @@ public class RecordManager extends Abstr
public AtomicLong nbUpdateBtreeHeader = new AtomicLong( 0 );
public AtomicLong nbUpdatePageIOs = new AtomicLong( 0 );
- /** The offset of the end of the file */
- private long endOfFileOffset;
-
/**
* 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.
@@ -224,6 +223,9 @@ public class RecordManager extends Abstr
private boolean disableReclaimer = false;
public Map<Long, Integer> writeCounter = new HashMap<Long, Integer>();
+
+ /** The transaction context */
+ private TransactionContext context;
/**
@@ -281,9 +283,6 @@ public class RecordManager extends Abstr
RandomAccessFile randomFile = new RandomAccessFile( file, "rw" );
fileChannel = randomFile.getChannel();
- // get the current end of file offset
- endOfFileOffset = fileChannel.size();
-
if ( isNewFile )
{
initRecordManager();
@@ -322,6 +321,7 @@ public class RecordManager extends Abstr
reclaimer.reclaim();
// must update the headers after reclaim operation
updateRecordManagerHeader();
+ writeRecordManagerHeader();
}
catch ( Exception e )
{
@@ -395,9 +395,7 @@ public class RecordManager extends Abstr
currentBtreeOfBtreesOffset = NO_PAGE;
updateRecordManagerHeader();
-
- // Set the offset of the end of the file
- endOfFileOffset = fileChannel.size();
+ writeRecordManagerHeader();
// First, create the btree of btrees <NameRevision, Long>
createBtreeOfBtrees();
@@ -408,11 +406,11 @@ public class RecordManager extends Abstr
// Inject these B-trees into the RecordManager. They are internal B-trees.
try
{
- manageSubBtree( btreeOfBtrees );
+ beginTransaction();
+ writeManagementTree( btreeOfBtrees );
currentBtreeOfBtreesOffset = ( ( PersistedBTree<NameRevision, Long> ) btreeOfBtrees ).getBtreeHeader()
.getBTreeHeaderOffset();
- updateRecordManagerHeader();
// Inject the BtreeOfBtrees into the currentBtreeHeaders map
currentBTreeHeaders.put( BTREE_OF_BTREES_NAME,
@@ -420,18 +418,20 @@ public class RecordManager extends Abstr
newBTreeHeaders.put( BTREE_OF_BTREES_NAME,
( ( PersistedBTree<NameRevision, Long> ) btreeOfBtrees ).getBtreeHeader() );
- // The FreePage B-tree
- manageSubBtree( copiedPageBtree );
+ // The Copied Pages B-tree
+ writeManagementTree( 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() );
+
+ // And finally, commit the transaction
+ commit();
}
catch ( BTreeAlreadyManagedException btame )
{
@@ -488,9 +488,10 @@ public class RecordManager extends Abstr
* @throws NoSuchFieldException
* @throws SecurityException
* @throws IllegalArgumentException
+ * @throws CursorException
*/
private void loadRecordManager() throws IOException, ClassNotFoundException, IllegalAccessException,
- InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException, KeyNotFoundException
+ InstantiationException, IllegalArgumentException, SecurityException, NoSuchFieldException, KeyNotFoundException, CursorException
{
if ( fileChannel.size() != 0 )
{
@@ -608,9 +609,6 @@ public class RecordManager extends Abstr
// Add the btree into the map of managed B-trees
managedBtrees.put( btreeName, ( BTree<Object, Object> ) btree );
}
-
- // We are done ! Let's finish with the last initialization parts
- endOfFileOffset = fileChannel.size();
}
}
@@ -637,6 +635,19 @@ public class RecordManager extends Abstr
TXN_LOG.debug( "..o The current thread already holds the lock" );
}
+ // Create the context
+ try
+ {
+ context = new TransactionContext( fileChannel.size() );
+ }
+ catch ( IOException ioe )
+ {
+ String name = Thread.currentThread().getName();
+ String err = "This thread, '" + name + "' cannot get the file size ";
+ TXN_LOG.error( err );
+ throw new RecordManagerException( err );
+ }
+
// Now, check the TLS state
incrementTxnLevel();
}
@@ -688,9 +699,22 @@ public class RecordManager extends Abstr
return;
case 1:
+ // First, write all the pageIos that are present in the context
+ Collection<WALObject> walObjects = context.getPages();
+
+ try
+ {
+ flushObjects( walObjects );
+ }
+ catch ( IOException ioe )
+ {
+
+ }
+
// We are done with the transaction, we can update the RMHeader and swap the BTreeHeaders
// First update the RMHeader to be sure that we have a way to restore from a crash
updateRecordManagerHeader();
+ writeRecordManagerHeader();
// Swap the BtreeHeaders maps
swapCurrentBtreeHeaders();
@@ -715,6 +739,7 @@ public class RecordManager extends Abstr
// And update the RMHeader again, removing the old references to BOB and CPB b-tree headers
// here, we have to erase the old references to keep only the new ones.
updateRecordManagerHeader();
+ writeRecordManagerHeader();
commitCount++;
@@ -961,7 +986,7 @@ public class RecordManager extends Abstr
*/
/* no qualifier */void checkOffset( long offset )
{
- if ( ( offset < 0 ) || ( offset > endOfFileOffset ) || ( ( offset % pageSize ) != 0 ) )
+ if ( ( offset < 0 ) || ( offset > context.getLastOffset() ) || ( ( offset % pageSize ) != 0 ) )
{
throw new InvalidOffsetException( "Bad Offset : " + offset );
}
@@ -1077,10 +1102,6 @@ public class RecordManager extends Abstr
BTreeFactory.setValueSerializer( btree, valueSerializerFqcn );
// The B-tree allowDuplicates flag
- int allowDuplicates = readInt( infoPageIos, dataPos );
- ( ( PersistedBTree<K, V> ) btree ).setAllowDuplicates( allowDuplicates != 0 );
- dataPos += INT_SIZE;
-
// Set the recordManager in the btree
( ( PersistedBTree<K, V> ) btree ).setRecordManager( this );
@@ -1193,43 +1214,23 @@ public class RecordManager extends Abstr
leaf.setLastOffset( pageIos[pageIos.length - 1].getOffset() );
int[] keyLengths = new int[nbElems];
- int[] valueLengths = new int[nbElems];
-
- boolean isNotSubTree = ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB );
+ int valueLength = 0;
// Read each key and value
for ( int i = 0; i < nbElems; i++ )
{
- if ( isNotSubTree )
- {
- // Read the number of values
- int nbValues = byteBuffer.getInt();
- PersistedValueHolder<V> valueHolder = null;
+ // Read the number of values
+ PersistedValueHolder<V> valueHolder = null;
- if ( nbValues < 0 )
- {
- // This is a sub-btree
- byte[] btreeOffsetBytes = new byte[LONG_SIZE];
- byteBuffer.get( btreeOffsetBytes );
+ // Read the value's length
+ valueLength = byteBuffer.getInt();
- // Create the valueHolder. As the number of values is negative, we have to switch
- // to a positive value but as we start at -1 for 0 value, add 1.
- valueHolder = new PersistedValueHolder<V>( btree, 1 - nbValues, btreeOffsetBytes );
- }
- else
- {
- // This is an array
- // Read the value's array length
- valueLengths[i] = byteBuffer.getInt();
+ // This is a value, read the byte[] associated with it
+ byte[] valuBytes = new byte[valueLength];
+ byteBuffer.get( valuBytes );
+ valueHolder = new PersistedValueHolder<V>( btree, valuBytes );
- // This is an Array of values, read the byte[] associated with it
- byte[] arrayBytes = new byte[valueLengths[i]];
- byteBuffer.get( arrayBytes );
- valueHolder = new PersistedValueHolder<V>( btree, nbValues, arrayBytes );
- }
-
- BTreeFactory.setValue( btree, leaf, i, valueHolder );
- }
+ BTreeFactory.setValue( btree, leaf, i, valueHolder );
keyLengths[i] = byteBuffer.getInt();
byte[] data = new byte[keyLengths[i]];
@@ -1548,6 +1549,20 @@ public class RecordManager extends Abstr
return value;
}
+
+ private <K, V> BTreeInfo<K, V> createBtreeInfo( BTree<K, V> btree )
+ {
+ BTreeInfo<K,V> btreeInfo = new BTreeInfo<K, V>();
+
+ btreeInfo.setBtree( btree );
+ btreeInfo.setPageSize( btree.getPageSize() );
+ btreeInfo.setBtreeName( btree.getName() );
+ btreeInfo.setKeySerializer( btree.getKeySerializerFQCN() );
+ btreeInfo.setValueSerializer( btree.getValueSerializerFQCN() );
+
+ return btreeInfo;
+ }
+
/**
* Manage a B-tree. The btree will be added and managed by this RecordManager. We will create a
@@ -1582,29 +1597,27 @@ public class RecordManager extends Abstr
throw new BTreeAlreadyManagedException( name );
}
- // Now, write the B-tree informations
- long btreeInfoOffset = writeBtreeInfo( btree );
+ // Get the B-tree header offset
+ PageIO[] btreeHeaderPageIos = getFreePageIOs( 0 );
+ long btreeHeaderOffset = btreeHeaderPageIos[0].getOffset();
BTreeHeader<K, V> btreeHeader = ( ( AbstractBTree<K, V> ) btree ).getBtreeHeader();
+ ( ( PersistedBTree<K, V> ) btree ).setBtreeHeaderOffset( btreeHeaderOffset );
+ context.addPage( btreeHeaderOffset, btreeHeader );
+
+ // Get the B-tree info offset
+ BTreeInfo<K, V> btreeInfo = createBtreeInfo( btree );
+ PageIO[] btreeInfoPageIos = getFreePageIOs( 0 );
+ long btreeInfoOffset = btreeInfoPageIos[0].getOffset();
( ( PersistedBTree<K, V> ) btree ).setBtreeInfoOffset( btreeInfoOffset );
+ context.addPage( btreeInfoOffset, btreeInfo );
- // Serialize the B-tree root page
+ // Get the B-tree root page offset
Page<K, V> rootPage = btreeHeader.getRootPage();
-
- PageIO[] rootPageIos = serializePage( btree, btreeHeader.getRevision(), rootPage );
-
- // Get the reference on the first page
+ PageIO[] rootPageIos = getFreePageIOs( 0 );
long rootPageOffset = rootPageIos[0].getOffset();
-
- // Store the rootPageOffset into the Btree header and into the rootPage
btreeHeader.setRootPageOffset( rootPageOffset );
( ( PersistedLeaf<K, V> ) rootPage ).setOffset( rootPageOffset );
- LOG.debug( "Flushing the newly managed '{}' btree rootpage", btree.getName() );
- flushPages( rootPageIos );
-
- // And the B-tree header
- long btreeHeaderOffset = writeBtreeHeader( btree, btreeHeader );
-
// 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
managedBtrees.put( name, ( BTree<Object, Object> ) btree );
@@ -1620,7 +1633,8 @@ public class RecordManager extends Abstr
NameRevision nameRevision = new NameRevision( name, 0L );
// Inject it into the B-tree of B-tree
- btreeOfBtrees.insert( nameRevision, btreeHeaderOffset );
+ btreeOfBtrees.insert( nameRevision, btreeHeader.getId() );
+
commit();
}
catch ( IOException ioe )
@@ -1632,9 +1646,81 @@ public class RecordManager extends Abstr
/**
- * Managing a btree is a matter of storing an reference to the managed B-tree in the B-tree Of B-trees.
- * We store a tuple of NameRevision (where revision is 0L) and a offset to the B-tree header.
- * At the same time, we keep a track of the managed B-trees in a Map.
+ * Write the B-tree informations on disk. We will write the following informations :
+ * <pre>
+ * +------------+
+ * | pageSize | The B-tree page size (ie, the number of elements per page max)
+ * +------------+
+ * | nameSize | The B-tree name size
+ * +------------+
+ * | name | The B-tree name
+ * +------------+
+ * | keySerSize | The keySerializer FQCN size
+ * +------------+
+ * | keySerFQCN | The keySerializer FQCN
+ * +------------+
+ * | valSerSize | The Value serializer FQCN size
+ * +------------+
+ * | valSerKQCN | The valueSerializer FQCN
+ * +------------+
+ * </pre>
+ * @param btree The B-tree which header has to be written
+ * @return The B-tree header offset
+ * @throws IOException If we weren't able to write the B-tree header
+ */
+ private <K, V> long writeBtreeInfo( BTree<K, V> btree ) throws IOException
+ {
+ // We will add the newly managed B-tree at the end of the header.
+ byte[] btreeNameBytes = Strings.getBytesUtf8( btree.getName() );
+ byte[] keySerializerBytes = Strings.getBytesUtf8( btree.getKeySerializerFQCN() );
+ byte[] valueSerializerBytes = Strings.getBytesUtf8( btree.getValueSerializerFQCN() );
+
+ int bufferSize =
+ INT_SIZE + // The page size
+ INT_SIZE + // The name size
+ btreeNameBytes.length + // The name
+ INT_SIZE + // The keySerializerBytes size
+ keySerializerBytes.length + // The keySerializerBytes
+ INT_SIZE + // The valueSerializerBytes size
+ valueSerializerBytes.length; // The valueSerializerBytes
+
+ // Get the pageIOs we need to store the data. We may need more than one.
+ PageIO[] btreeHeaderPageIos = getFreePageIOs( bufferSize );
+
+ // Keep the B-tree header Offset into the B-tree
+ long btreeInfoOffset = btreeHeaderPageIos[0].getOffset();
+
+ // Now store the B-tree information data in the pages :
+ // - the B-tree page size
+ // - the B-tree name
+ // - the keySerializer FQCN
+ // - the valueSerializer FQCN
+ // Starts at 0
+ long position = 0L;
+
+ // The B-tree page size
+ position = store( position, btree.getPageSize(), btreeHeaderPageIos );
+
+ // The tree name
+ position = store( position, btreeNameBytes, btreeHeaderPageIos );
+
+ // The keySerializer FQCN
+ position = store( position, keySerializerBytes, btreeHeaderPageIos );
+
+ // The valueSerialier FQCN
+ position = store( position, valueSerializerBytes, btreeHeaderPageIos );
+
+ // And flush the pages to disk now
+ LOG.debug( "Flushing the newly managed '{}' btree header", btree.getName() );
+ flushPages( btreeHeaderPageIos );
+
+ return btreeInfoOffset;
+ }
+
+
+ /**
+ * Write the management BTrees (BOB and CPB). There are special BTrees, we can write them on disk immediately
+ * (this is done only once anyway : when we create the RecordManager).
*
* @param btree The new B-tree to manage.
* @param treeType flag indicating if this is an internal tree
@@ -1642,7 +1728,7 @@ public class RecordManager extends Abstr
* @throws BTreeAlreadyManagedException If the B-tree is already managed
* @throws IOException
*/
- public synchronized <K, V> void manageSubBtree( BTree<K, V> btree )
+ private synchronized <K, V> void writeManagementTree( BTree<K, V> btree )
throws BTreeAlreadyManagedException, IOException
{
LOG.debug( "Managing the sub-btree {}", btree.getName() );
@@ -1650,13 +1736,6 @@ public class RecordManager extends Abstr
String name = btree.getName();
- if ( managedBtrees.containsKey( name ) )
- {
- // There is already a subB-tree with this name in the recordManager...
- LOG.error( "There is already a sub-B-tree named '{}' managed by this recordManager", name );
- throw new BTreeAlreadyManagedException( name );
- }
-
// Now, write the subB-tree informations
long btreeInfoOffset = writeBtreeInfo( btree );
BTreeHeader<K, V> btreeHeader = ( ( AbstractBTree<K, V> ) btree ).getBtreeHeader();
@@ -1666,7 +1745,7 @@ public class RecordManager extends Abstr
Page<K, V> rootPage = btreeHeader.getRootPage();
PageIO[] rootPageIos = serializePage( btree, btreeHeader.getRevision(), rootPage );
-
+
// Get the reference on the first page
long rootPageOffset = rootPageIos[0].getOffset();
@@ -1678,37 +1757,9 @@ public class RecordManager extends Abstr
LOG.debug( "Flushing the newly managed '{}' btree rootpage", btree.getName() );
flushPages( rootPageIos );
- // And the B-tree header
- long btreeHeaderOffset = writeBtreeHeader( btree, btreeHeader );
-
- // 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.COPIED_PAGES_BTREE ) &&
- ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB ) )
- {
- managedBtrees.put( name, ( BTree<Object, Object> ) btree );
- }
-
- // And in the Map of currentBtreeHeaders and newBtreeHeaders
+ // Now, if this is a new B-tree, add it t // And in the Map of currentBtreeHeaders and newBtreeHeaders
currentBTreeHeaders.put( name, btreeHeader );
newBTreeHeaders.put( name, btreeHeader );
-
- // Create the new NameRevision
- 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.COPIED_PAGES_BTREE ) &&
- ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB ) )
- {
- // We can safely increment the number of managed B-trees
- nbBtree++;
-
- btreeOfBtrees.insert( nameRevision, btreeHeaderOffset );
- }
-
- updateRecordManagerHeader();
}
@@ -1734,8 +1785,6 @@ public class RecordManager extends Abstr
{
int nbElems = page.getNbElems();
- boolean isNotSubTree = ( btree.getType() != BTreeTypeEnum.PERSISTED_SUB );
-
if ( nbElems == 0 )
{
return serializeRootPage( revision );
@@ -1787,11 +1836,7 @@ public class RecordManager extends Abstr
}
else
{
- if ( isNotSubTree )
- {
- dataSize += serializeLeafValue( ( PersistedLeaf<K, V> ) page, pos, serializedData );
- }
-
+ dataSize += serializeLeafValue( ( PersistedLeaf<K, V> ) page, pos, serializedData );
dataSize += serializeLeafKey( ( PersistedLeaf<K, V> ) page, pos, serializedData );
}
}
@@ -1905,54 +1950,22 @@ public class RecordManager extends Abstr
private <K, V> int serializeLeafValue( PersistedLeaf<K, V> leaf, int pos, List<byte[]> serializedData )
throws IOException
{
- // The value can be an Array or a sub-btree, but we don't care
- // we just iterate on all the values
ValueHolder<V> valueHolder = leaf.getValue( pos );
int dataSize = 0;
- int nbValues = valueHolder.size();
- if ( nbValues == 0 )
- {
- // No value.
- byte[] buffer = IntSerializer.serialize( nbValues );
- serializedData.add( buffer );
+ // We have a serialized value. Just flush it
+ byte[] data = ( ( PersistedValueHolder<V> ) valueHolder ).getRaw();
+ dataSize += data.length;
- return buffer.length;
- }
-
- if ( !valueHolder.isSubBtree() )
- {
- // Write the nb elements first
- byte[] buffer = IntSerializer.serialize( nbValues );
- serializedData.add( buffer );
- dataSize = INT_SIZE;
-
- // We have a serialized value. Just flush it
- byte[] data = ( ( PersistedValueHolder<V> ) valueHolder ).getRaw();
- dataSize += data.length;
-
- // Store the data size
- buffer = IntSerializer.serialize( data.length );
- serializedData.add( buffer );
- dataSize += INT_SIZE;
+ // Store the data size
+ byte[] buffer = IntSerializer.serialize( data.length );
+ serializedData.add( buffer );
+ dataSize += INT_SIZE;
- // and add the data if it's not 0
- if ( data.length > 0 )
- {
- serializedData.add( data );
- }
- }
- else
+ // and add the data if it's not 0
+ if ( data.length > 0 )
{
- // Store the nbVlues as a negative number. We add 1 so that 0 is not confused with an Array value
- byte[] buffer = IntSerializer.serialize( -( nbValues + 1 ) );
- serializedData.add( buffer );
- dataSize += buffer.length;
-
- // the B-tree offset
- buffer = LongSerializer.serialize( ( ( PersistedValueHolder<V> ) valueHolder ).getOffset() );
- serializedData.add( buffer );
- dataSize += buffer.length;
+ serializedData.add( data );
}
return dataSize;
@@ -2009,7 +2022,7 @@ public class RecordManager extends Abstr
* +---------------------+
* </pre>
*/
- public void updateRecordManagerHeader()
+ public ByteBuffer updateRecordManagerHeader()
{
// The page size
int position = writeData( RECORD_MANAGER_HEADER_BYTES, 0, pageSize );
@@ -2095,9 +2108,17 @@ public class RecordManager extends Abstr
LOG_PAGES.debug( "Update RM Header : \n{}", sb.toString() );
}
+ return RECORD_MANAGER_HEADER_BUFFER;
+ }
+
+
+ /**
+ * Write the RecordmanagerHeader in disk
+ */
+ private void writeRecordManagerHeader()
+ {
try
{
-
Integer nbTxnStarted = CONTEXT.get();
if ( ( nbTxnStarted == null ) || ( nbTxnStarted <= 1 ) )
@@ -2331,84 +2352,41 @@ public class RecordManager extends Abstr
return btreeHeaderOffset;
}
-
+
/**
- * Write the B-tree informations on disk. We will write the following informations :
- * <pre>
- * +------------+
- * | pageSize | The B-tree page size (ie, the number of elements per page max)
- * +------------+
- * | nameSize | The B-tree name size
- * +------------+
- * | name | The B-tree name
- * +------------+
- * | keySerSize | The keySerializer FQCN size
- * +------------+
- * | keySerFQCN | The keySerializer FQCN
- * +------------+
- * | valSerSize | The Value serializer FQCN size
- * +------------+
- * | valSerKQCN | The valueSerializer FQCN
- * +------------+
- * | dups | The flags that tell if the dups are allowed
- * +------------+
- * </pre>
- * @param btree The B-tree which header has to be written
- * @return The B-tree header offset
- * @throws IOException If we weren't able to write the B-tree header
+ * Write the RootPage content.
+ *
+ * @param btree The BTree we are working on
+ * @param btreeHeader The BtreeHeader for this BTree
+ * @return The offset of the rootPage
+ * @throws IOException If we have had an error while accessing to the underlying file
*/
- private <K, V> long writeBtreeInfo( BTree<K, V> btree ) throws IOException
+ private <K, V> long writeRootPage( BTree<K, V> btree, BTreeHeader<K, V> btreeHeader ) throws IOException
{
- // We will add the newly managed B-tree at the end of the header.
- byte[] btreeNameBytes = Strings.getBytesUtf8( btree.getName() );
- byte[] keySerializerBytes = Strings.getBytesUtf8( btree.getKeySerializerFQCN() );
- byte[] valueSerializerBytes = Strings.getBytesUtf8( btree.getValueSerializerFQCN() );
-
- int bufferSize =
- INT_SIZE + // The page size
- INT_SIZE + // The name size
- btreeNameBytes.length + // The name
- INT_SIZE + // The keySerializerBytes size
- keySerializerBytes.length + // The keySerializerBytes
- INT_SIZE + // The valueSerializerBytes size
- valueSerializerBytes.length + // The valueSerializerBytes
- INT_SIZE; // The allowDuplicates flag
-
- // Get the pageIOs we need to store the data. We may need more than one.
- PageIO[] btreeHeaderPageIos = getFreePageIOs( bufferSize );
-
- // Keep the B-tree header Offset into the B-tree
- long btreeInfoOffset = btreeHeaderPageIos[0].getOffset();
-
- // Now store the B-tree information data in the pages :
- // - the B-tree page size
- // - the B-tree name
- // - the keySerializer FQCN
- // - the valueSerializer FQCN
- // - the flags that tell if the dups are allowed
- // Starts at 0
- long position = 0L;
-
- // The B-tree page size
- position = store( position, btree.getPageSize(), btreeHeaderPageIos );
+ Page<K, V> rootPage = btreeHeader.getRootPage();
+ long pageId = context.getPageId();
- // The tree name
- position = store( position, btreeNameBytes, btreeHeaderPageIos );
+ context.addPage( pageId, rootPage );
+
+ return pageId;
- // The keySerializer FQCN
- position = store( position, keySerializerBytes, btreeHeaderPageIos );
+ /*
+ PageIO[] rootPageIos = serializePage( btree, btreeHeader.getRevision(), rootPage );
- // The valueSerialier FQCN
- position = store( position, valueSerializerBytes, btreeHeaderPageIos );
+ // Get the reference on the first page
+ long rootPageOffset = rootPageIos[0].getOffset();
- // The allowDuplicates flag
- position = store( position, ( btree.isAllowDuplicates() ? 1 : 0 ), btreeHeaderPageIos );
+ // Store the rootPageOffset into the Btree header and into the rootPage
+ btreeHeader.setRootPageOffset( rootPageOffset );
- // And flush the pages to disk now
- LOG.debug( "Flushing the newly managed '{}' btree header", btree.getName() );
- flushPages( btreeHeaderPageIos );
+ ( ( AbstractPage<K, V> ) rootPage ).setOffset( rootPageOffset );
- return btreeInfoOffset;
+ LOG.debug( "Flushing the newly managed '{}' btree rootpage", btree.getName() );
+
+ // Store the PageIO and the rootPage
+ storePages( rootPageIos );
+ context.addPage( rootPageOffset, rootPage );
+ */
}
@@ -2590,6 +2568,12 @@ public class RecordManager extends Abstr
*/
private void flushPages( PageIO... pageIos ) throws IOException
{
+ if ( pageIos == null )
+ {
+ LOG.debug( "No PageIO to flush" );
+ return;
+ }
+
if ( LOG.isDebugEnabled() )
{
for ( PageIO pageIo : pageIos )
@@ -2627,6 +2611,88 @@ public class RecordManager extends Abstr
}
}
+
+ private <K, V> void flushObjects( Collection<WALObject> walObjects ) throws IOException
+ {
+ if ( ( walObjects == null ) || ( walObjects.size() == 0 ) )
+ {
+ LOG.debug( "No Page to flush" );
+ return;
+ }
+
+ if ( LOG.isDebugEnabled() )
+ {
+ //for ( Page page : pages )
+ {
+ //dump( page );
+ }
+ }
+
+ for ( WALObject walObject : walObjects )
+ {
+ if ( walObject instanceof BTreeHeader )
+ {
+ // We need to update the rootPage offset first
+ PageIO[] pageIos = walObject.serialize();
+ flushPages( pageIos );
+ }
+ else if ( walObject instanceof BTreeInfo )
+ {
+ // Serialize the instance and write it
+ PageIO[] pageIos = walObject.serialize();
+ flushPages( pageIos );
+ }
+ else if ( walObject instanceof PersistedNode )
+ {
+
+ }
+ else if ( walObject instanceof PersistedLeaf )
+ {
+ // We can write pages immediately
+ PageIO[] pageIos = walObject.serialize();
+ flushPages( pageIos );
+ }
+
+ //BTree<K, V> btree = ( ( AbstractPage<K,V> ) page ).getBtree();
+ //PageIO[] pageIos = serializePage( btree, ( ( AbstractPage<K,V> ) page ).getRevision(), page );
+
+
+ //LOG.debug( "Flushing the newly managed '{}' btree rootpage", btree.getName() );
+ //ushPages( pageIos );
+ }
+ }
+
+ /**
+ * Store the pages in the context. If the page has no Offset, we will
+ * use a virtual offset (ie, a negative one)
+ *
+ * @param pageIos The list of pages to write
+ * @throws IOException If the store failed
+ */
+ /* No qualifier */void storePages( PageIO... pageIos ) throws IOException
+ {
+ if ( LOG.isDebugEnabled() )
+ {
+ for ( PageIO pageIo : pageIos )
+ {
+ dump( pageIo );
+ }
+ }
+
+ for ( PageIO pageIo : pageIos )
+ {
+ pageIo.getData().rewind();
+ long offset = pageIo.getOffset();
+
+ LOG.debug( "Writing a page at position {}", offset );
+ //context.addPageIo( offset, pageIo );
+
+ writeCounter.put( offset, writeCounter.containsKey( offset ) ? writeCounter.get( offset ) + 1 : 1 );
+
+ nbUpdatePageIOs.incrementAndGet();
+ }
+ }
+
/**
* Compute the page in which we will store data given an offset, when
@@ -2661,7 +2727,7 @@ public class RecordManager extends Abstr
* @param pageIos The pageIOs we have to store the data in
* @return The new offset
*/
- private long store( long position, byte[] bytes, PageIO... pageIos )
+ /* no qualifier */ long store( long position, byte[] bytes, PageIO... pageIos )
{
if ( bytes != null )
{
@@ -2802,7 +2868,7 @@ public class RecordManager extends Abstr
* @param pageIos The pageIOs we have to store the data in
* @return The new offset
*/
- private long store( long position, int value, PageIO... pageIos )
+ /* no qualifier */ long store( long position, int value, PageIO... pageIos )
{
// Compute the page in which we will store the data given the
// current position
@@ -2877,7 +2943,7 @@ public class RecordManager extends Abstr
* @param pageIos The pageIOs we have to store the data in
* @return The new offset
*/
- private long store( long position, long value, PageIO... pageIos )
+ /* no qualifier */ long store( long position, long value, PageIO... pageIos )
{
// Compute the page in which we will store the data given the
// current position
@@ -3120,7 +3186,7 @@ public class RecordManager extends Abstr
* @param dataSize The data size
* @return An array of pages, enough to store the full data
*/
- private PageIO[] getFreePageIOs( int dataSize ) throws IOException
+ /* No qualifier */ PageIO[] getFreePageIOs( int dataSize ) throws IOException
{
if ( dataSize == 0 )
{
@@ -3163,9 +3229,9 @@ public class RecordManager extends Abstr
// We don't have any free page. Reclaim some new page at the end
// of the file
- PageIO newPage = new PageIO( endOfFileOffset );
+ PageIO newPage = new PageIO( context.getLastOffset() );
- endOfFileOffset += pageSize;
+ context.addLastOffset( pageSize );
ByteBuffer data = ByteBuffer.allocateDirect( pageSize );
@@ -3186,10 +3252,10 @@ public class RecordManager extends Abstr
// We have some existing free page. Fetch it from disk
PageIO pageIo = fetchPage( firstFreePage );
- // Update the firstFreePage pointer
- firstFreePage = pageIo.getNextPage();
+ // Update the firstFreePage pointer
+ firstFreePage = pageIo.getNextPage();
- freePageLock.unlock();
+ freePageLock.unlock();
// overwrite the data of old page
ByteBuffer data = ByteBuffer.allocateDirect( pageSize );
@@ -3921,7 +3987,6 @@ public class RecordManager extends Abstr
config.setName( name );
config.setKeySerializer( keySerializer );
config.setValueSerializer( valueSerializer );
- config.setAllowDuplicates( allowDuplicates );
BTree btree = new PersistedBTree( config );
manage( btree );
@@ -4027,33 +4092,6 @@ public class RecordManager extends Abstr
}
- /**
- * Loads a B-tree holding the values of a duplicate key
- * This tree is also called as dups tree or sub tree
- *
- * @param offset the offset of the B-tree header
- * @return the deserialized B-tree
- */
- /* No qualifier */<K, V> BTree<V, V> loadDupsBtree( long btreeHeaderOffset, BTree<K, V> parentBtree )
- {
- PageIO[] pageIos = null;
- try
- {
- pageIos = readPageIOs( btreeHeaderOffset, Long.MAX_VALUE );
-
- BTree<V, V> subBtree = BTreeFactory.<V, V> createPersistedBTree( BTreeTypeEnum.PERSISTED_SUB );
- loadBtree( pageIos, subBtree, parentBtree );
-
- return subBtree;
- }
- catch ( Exception e )
- {
- // should not happen
- throw new BTreeCreationException( e );
- }
- }
-
-
private void checkFreePages() throws EndOfFileExceededException, IOException
{
//System.out.println( "Checking the free pages, starting from " + Long.toHexString( firstFreePage ) );
Added: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionContext.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionContext.java?rev=1711861&view=auto
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionContext.java (added)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionContext.java Sun Nov 1 23:01:00 2015
@@ -0,0 +1,125 @@
+/*
+ * 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.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The TransactionContext class holds all the modified pages in memory, up to the
+ * moment we have to flush them on disk, when a cmmit is applied, or discard them,
+ * if a rallback is called.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class TransactionContext
+{
+ /** The map containing all the modified pages, using their offset as a key */
+ private Map<Long, WALObject> pageMap = new HashMap<Long, WALObject>();
+
+ /** The incremental counter used to identify pages */
+ private long pageId;
+
+ /** The last offset on disk */
+ private long lastOffset;
+
+ /**
+ * A constructor for the TransactionContext, which initialize the last offset to
+ * the file size.
+ *
+ * @param lastOffset The last offset fo the associated file
+ */
+ public TransactionContext( long lastOffset )
+ {
+ this.lastOffset = lastOffset;
+ pageId = RecordManager.NO_PAGE;
+ }
+
+
+ /**
+ * Retrieve a Page if it has been stored in the context
+ * @param offset the offset of the Page we are looking for
+ * @return The found Page, or null if it does not exist
+ */
+ public WALObject getPage( Long offset )
+ {
+ return pageMap.get( offset );
+ }
+
+
+ /**
+ * Add a page into the TransactionContext
+ *
+ * @param offset The Page's offset
+ * @param pageIo The Page to add
+ */
+ public void addPage( Long offset, WALObject page )
+ {
+ pageMap.put( offset, page );
+ }
+
+
+ /**
+ * @return The list of stored Pages
+ */
+ public Collection<WALObject> getPages()
+ {
+ return pageMap.values();
+ }
+
+
+ /**
+ * @return the lastOffset
+ */
+ public long getLastOffset()
+ {
+ return lastOffset;
+ }
+
+
+ /**
+ * @param lastOffset the lastOffset to set
+ */
+ public void setLastOffset( long lastOffset )
+ {
+ this.lastOffset = lastOffset;
+ }
+
+
+ /**
+ * @param addedSize the size to add
+ */
+ public void addLastOffset( long addedSize )
+ {
+ this.lastOffset += addedSize;
+ }
+
+
+ /**
+ * @return The unique page ID
+ */
+ public long getPageId()
+ {
+ pageId--;
+
+ return pageId;
+ }
+}
Modified: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java?rev=1711861&r1=1711860&r2=1711861&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/TupleCursor.java Sun Nov 1 23:01:00 2015
@@ -23,21 +23,26 @@ package org.apache.directory.mavibot.btr
import java.io.IOException;
import java.util.NoSuchElementException;
+import org.apache.directory.mavibot.btree.exception.CursorException;
import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
/**
* A Cursor is used to fetch elements in a BTree and is returned by the
- * @see BTree#browse method. The cursor <strng>must</strong> be closed
+ * @see BTree#browse method. The cursor <strong>must</strong> be closed
* when the user is done with it.
* <p>
+ * We keep a track of the current position at each level of the B-tree, so
+ * we can navigate in this B-tree forward and backward. Two special positions
+ * are defined : BEFORE_FIRST and AFTER_LAST which are befoe the leftmost and
+ * after the rightmost elements in the B-tree
*
* @param <K> The type for the Key
* @param <V> The type for the stored value
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public class TupleCursor<K, V>
+public class TupleCursor<K, V> //implements Iterator<Tuple<K,V>>
{
/** A marker to tell that we are before the first element */
private static final int BEFORE_FIRST = -1;
@@ -78,59 +83,95 @@ public class TupleCursor<K, V>
/**
- * Change the position in the current cursor to set it after the last key
+ * Positions this Cursor after the last element. This will set the path to the
+ * rightmost page for each level, and the position to the rightmost element
+ * of each page.
+ *
+ * @throws CursorException if there are problems positioning this Cursor or if
+ * this Cursor is closed
*/
- public void afterLast() throws IOException
+ public void afterLast() throws CursorException
{
// First check that we have elements in the BTree
if ( ( stack == null ) || ( stack.length == 0 ) )
{
return;
}
+
+ // Update the parent page.
+ ParentPos<K, V> parentPos = stack[0];
+ parentPos.pos = parentPos.page.getNbElems();
+ Page<K, V> childPage = null;
- Page<K, V> child = null;
+ if ( parentPos.page instanceof PersistedNode )
+ {
+ childPage = ( ( AbstractPage<K, V> ) parentPos.page ).getPage( parentPos.pos );
+ }
- for ( int i = 0; i < depth; i++ )
+ // Go down the Tree, selecting the rightmost element in each Node
+ for ( int i = 1; i < depth; i++ )
{
- ParentPos<K, V> parentPos = stack[i];
+ parentPos = stack[i];
- if ( child != null )
- {
- parentPos.page = child;
- parentPos.pos = child.getNbElems();
- }
- else
- {
- // We have N+1 children if the page is a Node, so we don't decrement the nbElems field
- parentPos.pos = parentPos.page.getNbElems();
- }
+ // We are in the middle of the tree, change the parentPos to be
+ // the one we have selected previously
+ // Set the parentPos to be at the rightmost position for this level.
+ parentPos.page = childPage;
+ parentPos.pos = childPage.getNbElems();
- child = ( ( AbstractPage<K, V> ) parentPos.page ).getPage( parentPos.pos );
+ // Get the child page, and iterate
+ childPage = ( ( AbstractPage<K, V> ) childPage ).getPage( parentPos.pos );
}
- // and leaf
- ParentPos<K, V> parentPos = stack[depth];
+ // Now, we should handle the leaf
+ parentPos = stack[depth];
- if ( child == null )
+ if ( childPage != null )
{
- parentPos.pos = parentPos.page.getNbElems() - 1;
+ // The tree had more than one level, so we make the current parentPos
+ // point on the previously selected leaf.
+ parentPos.page = childPage;
}
- else
+
+ // Finally, set the position after the rightmost element
+ parentPos.pos = AFTER_LAST;
+ }
+
+
+ /**
+ * Determines whether or not a call to get() will succeed.
+ *
+ * @return true if a call to the get() method will succeed, false otherwise
+ */
+ public boolean available()
+ {
+ // First check that we have elements in the BTree
+ if ( ( stack == null ) || ( stack.length == 0 ) )
{
- parentPos.page = child;
- parentPos.pos = child.getNbElems() - 1;
+ return false;
}
- parentPos.valueCursor = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( parentPos.pos ).getCursor();
- parentPos.valueCursor.afterLast();
- parentPos.pos = AFTER_LAST;
+ // Take the leaf and check if we have no mare values
+ ParentPos<K, V> parentPos = stack[depth];
+
+ if ( parentPos.page == null )
+ {
+ // Empty BTree, get out
+ return false;
+ }
+
+ // We must not be AFTER_LAST or BEFORE_FIRST
+ return ( parentPos.pos != BEFORE_FIRST ) && ( parentPos.pos != AFTER_LAST );
}
/**
- * Change the position in the current cursor before the first key
+ * Positions this Cursor before the first element.
+ *
+ * @throws Exception if there are problems positioning this cursor or if
+ * this Cursor is closed
*/
- public void beforeFirst() throws IOException
+ public void beforeFirst() throws CursorException
{
// First check that we have elements in the BTree
if ( ( stack == null ) || ( stack.length == 0 ) )
@@ -138,35 +179,32 @@ public class TupleCursor<K, V>
return;
}
+ ParentPos<K, V> parentPos = stack[0];
+ parentPos.pos = 0;
Page<K, V> child = null;
+
+ if ( parentPos.page instanceof PersistedNode )
+ {
+ child = ( ( AbstractPage<K, V> ) parentPos.page ).getPage( 0 );
+ }
- for ( int i = 0; i < depth; i++ )
+ for ( int i = 1; i < depth; i++ )
{
- ParentPos<K, V> parentPos = stack[i];
+ parentPos = stack[i];
parentPos.pos = 0;
-
- if ( child != null )
- {
- parentPos.page = child;
- }
+ parentPos.page = child;
child = ( ( AbstractPage<K, V> ) parentPos.page ).getPage( 0 );
}
// and leaf
- ParentPos<K, V> parentPos = stack[depth];
+ parentPos = stack[depth];
parentPos.pos = BEFORE_FIRST;
if ( child != null )
{
parentPos.page = child;
}
-
- if ( parentPos.valueCursor != null )
- {
- parentPos.valueCursor = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( 0 ).getCursor();
- parentPos.valueCursor.beforeFirst();
- }
}
@@ -225,13 +263,6 @@ public class TupleCursor<K, V>
}
else
{
- // Check if we have some more value
- if ( ( parentPos.valueCursor != null ) && parentPos.valueCursor.hasNext() )
- {
- // No problem, we still have some values to read
- return true;
- }
-
// Ok, here, we have reached the last value in the leaf. We have to go up and
// see if we have some remaining values
int currentDepth = depth - 1;
@@ -258,13 +289,15 @@ public class TupleCursor<K, V>
/**
- * Find the next key/value
+ * Find the next Tuple, from the current position. If we have no more new element,
+ * a NoSuchElementException will be thrown.
*
* @return A Tuple containing the found key and value
* @throws IOException
- * @throws EndOfFileExceededException
+ * @throws NoSuchElementException When we have reached the end of the B-tree, or if
+ * the B-tree is empty
*/
- public Tuple<K, V> next() throws EndOfFileExceededException, IOException
+ public Tuple<K, V> next() throws NoSuchElementException
{
// First check that we have elements in the BTree
if ( ( stack == null ) || ( stack.length == 0 ) )
@@ -274,46 +307,17 @@ public class TupleCursor<K, V>
ParentPos<K, V> parentPos = stack[depth];
- if ( ( parentPos.page == null ) || ( parentPos.pos == AFTER_LAST ) )
- {
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
- }
-
- if ( parentPos.pos == parentPos.page.getNbElems() )
+ try
{
- // End of the leaf. We have to go back into the stack up to the
- // parent, and down to the leaf
- parentPos = findNextParentPos();
-
- // we also need to check for the type of page cause
- // findNextParentPos will never return a null ParentPos
- if ( ( parentPos == null ) || ( parentPos.page == null ) )
- {
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
- }
- }
-
- V value = null;
-
- if ( parentPos.valueCursor.hasNext() )
- {
- // Deal with the BeforeFirst case
- if ( parentPos.pos == BEFORE_FIRST )
- {
- parentPos.pos++;
- }
-
- value = parentPos.valueCursor.next();
- }
- else
- {
- if ( parentPos.pos == parentPos.page.getNbElems() - 1 )
+ if ( parentPos.pos == parentPos.page.getNbElems() )
{
+ // End of the leaf. We have to go back into the stack up to the
+ // parent, and down to the leaf
parentPos = findNextParentPos();
-
- if ( ( parentPos == null ) || ( parentPos.page == null ) )
+
+ // we also need to check for the type of page cause
+ // findNextParentPos will never return a null ParentPos
+ if ( parentPos == null )
{
// This is the end : no more value
throw new NoSuchElementException( "No more tuples present" );
@@ -323,146 +327,29 @@ public class TupleCursor<K, V>
{
parentPos.pos++;
}
-
- try
- {
- ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( parentPos.pos );
-
- parentPos.valueCursor = valueHolder.getCursor();
-
- value = parentPos.valueCursor.next();
- }
- catch ( IllegalArgumentException e )
- {
- e.printStackTrace();
- }
- }
-
- AbstractPage<K, V> leaf = ( AbstractPage<K, V> ) ( parentPos.page );
- Tuple<K, V> tuple = new Tuple<K, V>( leaf.getKey( parentPos.pos ), value );
-
- return tuple;
- }
-
-
- /**
- * Get the next non-duplicate key.
- * If the BTree contains :
- *
- * <ul>
- * <li><1,0></li>
- * <li><1,1></li>
- * <li><1,2></li>
- * <li><2,0></li>
- * <li><2,1></li>
- * </ul>
- *
- * and cursor is present at <1,1> then the returned tuple will be <2,0> (not <1,2>)
- *
- * @return A Tuple containing the found key and value
- * @throws EndOfFileExceededException
- * @throws IOException
- */
- public Tuple<K, V> nextKey() throws EndOfFileExceededException, IOException
- {
- // First check that we have elements in the BTree
- if ( ( stack == null ) || ( stack.length == 0 ) )
- {
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
}
-
- ParentPos<K, V> parentPos = stack[depth];
-
- if ( parentPos.page == null )
+ catch ( IOException ioe )
{
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
+ throw new NoSuchElementException( ioe.getMessage());
}
- if ( parentPos.pos == ( parentPos.page.getNbElems() - 1 ) )
- {
- // End of the leaf. We have to go back into the stack up to the
- // parent, and down to the next leaf
- ParentPos<K, V> newParentPos = findNextParentPos();
-
- // we also need to check the result of the call to
- // findNextParentPos as it will return a null ParentPos
- if ( ( newParentPos == null ) || ( newParentPos.page == null ) )
- {
- // This is the end : no more value
- AbstractPage<K, V> leaf = ( AbstractPage<K, V> ) ( parentPos.page );
- ValueHolder<V> valueHolder = leaf.getValue( parentPos.pos );
- parentPos.pos = AFTER_LAST;
- parentPos.valueCursor = valueHolder.getCursor();
- parentPos.valueCursor.afterLast();
+ // Get the value
+ ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( parentPos.pos );
- return null;
- }
- else
- {
- parentPos = newParentPos;
- }
- }
- else
- {
- // Get the next key
- parentPos.pos++;
- }
+ V value = valueHolder.get();
- // The key
+ // Get the key
AbstractPage<K, V> leaf = ( AbstractPage<K, V> ) ( parentPos.page );
- Tuple<K, V> tuple = new Tuple<K, V>();
- tuple.setKey( leaf.getKey( parentPos.pos ) );
-
- // The value
- ValueHolder<V> valueHolder = leaf.getValue( parentPos.pos );
- parentPos.valueCursor = valueHolder.getCursor();
- V value = parentPos.valueCursor.next();
- tuple.setValue( value );
+ K key = leaf.getKey( parentPos.pos );
+
+ // Build the Tuple
+ Tuple<K, V> tuple = new Tuple<K, V>( key, value );
return tuple;
}
/**
- * Tells if the cursor can return a next key
- *
- * @return true if there are some more keys
- * @throws IOException
- * @throws EndOfFileExceededException
- */
- public boolean hasNextKey() throws EndOfFileExceededException, IOException
- {
- // First check that we have elements in the BTree
- if ( ( stack == null ) || ( stack.length == 0 ) )
- {
- // This is the end : no more key
- return false;
- }
-
- ParentPos<K, V> parentPos = stack[depth];
-
- if ( parentPos.page == null )
- {
- // This is the end : no more key
- return false;
- }
-
- if ( parentPos.pos == ( parentPos.page.getNbElems() - 1 ) )
- {
- // End of the leaf. We have to go back into the stack up to the
- // parent, and down to the next leaf
- return hasNextParentPos();
- }
- else
- {
- return true;
- }
- }
-
-
- /**
* Tells if the cursor can return a previous element
*
* @return true if there are some more elements
@@ -499,12 +386,6 @@ public class TupleCursor<K, V>
return false;
}
- // Check if we have some more value
- if ( parentPos.valueCursor.hasPrev() )
- {
- return true;
- }
-
// Ok, here, we have reached the first value in the leaf. We have to go up and
// see if we have some remaining values
int currentDepth = depth - 1;
@@ -530,11 +411,13 @@ public class TupleCursor<K, V>
/**
- * Find the previous key/value
+ * Get the previous Tuple, from the current position. If we have no more new element,
+ * a NoMoreElementException will be thrown.
*
* @return A Tuple containing the found key and value
* @throws IOException
- * @throws EndOfFileExceededException
+ * @throws NoSuchElementException When we have reached the beginning of the B-tree, or if
+ * the B-tree is empty
*/
public Tuple<K, V> prev() throws EndOfFileExceededException, IOException
{
@@ -546,197 +429,58 @@ public class TupleCursor<K, V>
ParentPos<K, V> parentPos = stack[depth];
- if ( ( parentPos.page == null ) || ( parentPos.pos == BEFORE_FIRST ) )
+ switch( parentPos.pos )
{
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
- }
-
- if ( ( parentPos.pos == 0 ) && ( !parentPos.valueCursor.hasPrev() ) )
- {
- // End of the leaf. We have to go back into the stack up to the
- // parent, and down to the leaf
- parentPos = findPrevParentPos();
-
- // we also need to check for the type of page cause
- // findPrevParentPos will never return a null ParentPos
- if ( ( parentPos == null ) || ( parentPos.page == null ) )
- {
+ case BEFORE_FIRST :
// This is the end : no more value
throw new NoSuchElementException( "No more tuples present" );
- }
- }
- V value = null;
-
- if ( parentPos.valueCursor.hasPrev() )
- {
- // Deal with the AfterLast case
- if ( parentPos.pos == AFTER_LAST )
- {
+ case AFTER_LAST :
+ // Move the the last element
parentPos.pos = parentPos.page.getNbElems() - 1;
- }
-
- value = parentPos.valueCursor.prev();
- }
- else
- {
- if ( parentPos.pos == 0 )
- {
+ break;
+
+ case 0 :
+ // beginning of the leaf. We have to go back into the stack up to the
+ // parent, and down to the leaf on the left, if possible
parentPos = findPrevParentPos();
- if ( ( parentPos == null ) || ( parentPos.page == null ) )
+ // we also need to check for the type of page cause
+ // findPrevParentPos will never return a null ParentPos
+ if ( parentPos == null )
{
// This is the end : no more value
throw new NoSuchElementException( "No more tuples present" );
}
- }
- else
- {
- parentPos.pos--;
-
- try
- {
- ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( parentPos.pos );
-
- parentPos.valueCursor = valueHolder.getCursor();
- parentPos.valueCursor.afterLast();
-
- value = parentPos.valueCursor.prev();
- }
- catch ( IllegalArgumentException e )
+ else
{
- e.printStackTrace();
+ parentPos.pos--;
}
- }
- }
-
- AbstractPage<K, V> leaf = ( AbstractPage<K, V> ) ( parentPos.page );
- Tuple<K, V> tuple = new Tuple<K, V>( leaf.getKey( parentPos.pos ), value );
-
- return tuple;
- }
-
-
- /**
- * Get the previous non-duplicate key.
- * If the BTree contains :
- *
- * <ul>
- * <li><1,0></li>
- * <li><1,1></li>
- * <li><1,2></li>
- * <li><2,0></li>
- * <li><2,1></li>
- * </ul>
- *
- * and cursor is present at <2,1> then the returned tuple will be <1,0> (not <2,0>)
- *
- * @return A Tuple containing the found key and value
- * @throws EndOfFileExceededException
- * @throws IOException
- */
- public Tuple<K, V> prevKey() throws EndOfFileExceededException, IOException
- {
- // First check that we have elements in the BTree
- if ( ( stack == null ) || ( stack.length == 0 ) )
- {
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
- }
-
- ParentPos<K, V> parentPos = stack[depth];
-
- if ( parentPos.page == null )
- {
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
- }
-
- if ( parentPos.pos == 0 )
- {
- // Beginning of the leaf. We have to go back into the stack up to the
- // parent, and down to the leaf
- parentPos = findPrevParentPos();
-
- if ( ( parentPos == null ) || ( parentPos.page == null ) )
- {
- // This is the end : no more value
- throw new NoSuchElementException( "No more tuples present" );
- }
- }
- else
- {
- if ( parentPos.pos == AFTER_LAST )
- {
- parentPos.pos = parentPos.page.getNbElems() - 1;
- }
- else
- {
+
+ break;
+
+ default :
+ // Simply decrement the position
parentPos.pos--;
- }
+ break;
}
- // Update the Tuple
- AbstractPage<K, V> leaf = ( AbstractPage<K, V> ) ( parentPos.page );
+ // Get the value
+ ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( parentPos.pos );
+ V value = valueHolder.get();
- // The key
- Tuple<K, V> tuple = new Tuple<K, V>();
- tuple.setKey( leaf.getKey( parentPos.pos ) );
-
- // The value
- ValueHolder<V> valueHolder = leaf.getValue( parentPos.pos );
- parentPos.valueCursor = valueHolder.getCursor();
- V value = parentPos.valueCursor.next();
- tuple.setValue( value );
+ // Get the key
+ AbstractPage<K, V> leaf = ( AbstractPage<K, V> ) ( parentPos.page );
+ K key = leaf.getKey( parentPos.pos );
+
+ // Construct the Tuple
+ Tuple<K, V> tuple = new Tuple<K, V>( key, value );
return tuple;
}
/**
- * Tells if the cursor can return a previous key
- *
- * @return true if there are some more keys
- * @throws IOException
- * @throws EndOfFileExceededException
- */
- public boolean hasPrevKey() throws EndOfFileExceededException, IOException
- {
- // First check that we have elements in the BTree
- if ( ( stack == null ) || ( stack.length == 0 ) )
- {
- // This is the end : no more key
- return false;
- }
-
- ParentPos<K, V> parentPos = stack[depth];
-
- if ( parentPos.page == null )
- {
- // This is the end : no more key
- return false;
- }
-
- switch ( parentPos.pos )
- {
- case 0:
- // Beginning of the leaf. We have to go back into the stack up to the
- // parent, and down to the leaf
- return hasPrevParentPos();
-
- case -1:
- // no previous key
- return false;
-
- default:
- // we have a previous key
- return true;
- }
- }
-
-
- /**
* Tells if there is a next ParentPos
*
* @return the new ParentPos instance, or null if we have no following leaf
@@ -836,7 +580,6 @@ public class TupleCursor<K, V>
parentPos = stack[depth];
parentPos.page = child;
parentPos.pos = 0;
- parentPos.valueCursor = ( ( AbstractPage<K, V> ) child ).getValue( 0 ).getCursor();
return parentPos;
}
@@ -847,7 +590,33 @@ public class TupleCursor<K, V>
/**
- * Find the leaf containing the previous elements.
+ * Find the leaf containing the previous elements. We are in
+ *
+ * if the B-tree content is like :
+ * <pre>
+ * .
+ * |
+ * v
+ * +---+---+---+---+
+ * |///| X | Y |///| Level N-1
+ * +---+---+---+---+
+ * | | | | |
+ * <-...---+ | | | +---...->
+ * | | |
+ * <-...---+ | |
+ * | |
+ * +---------+ +-------+
+ * | |
+ * v v
+ * +---+---+---+---+ +---+---+---+---+
+ * |///|///| T |###| | Y |///|///|///| Level N
+ * +---+---+---+---+ +---+---+---+---+
+ * pos pos
+ * New ParentPos Current ParentPos
+ * </pre>
+ *
+ * and we are on Y, then the previous ParentPos instance will contain the page
+ * on the left, teh position beoing on the last element of this page, T
*
* @return the new ParentPos instance, or null if we have no previous leaf
* @throws IOException
@@ -861,6 +630,7 @@ public class TupleCursor<K, V>
return null;
}
+ // Go up one step
int currentDepth = depth - 1;
Page<K, V> child = null;
@@ -868,21 +638,21 @@ public class TupleCursor<K, V>
while ( currentDepth >= 0 )
{
// We first go up the tree, until we reach a page whose current position
- // is not the last one
+ // is not the first one
ParentPos<K, V> parentPos = stack[currentDepth];
if ( parentPos.pos == 0 )
{
- // No more element on the right : go up
+ // No more element on the left : go up
currentDepth--;
}
else
{
- // We can pick the next element at this level
+ // We can pick the previous element at this level
parentPos.pos--;
child = ( ( AbstractPage<K, V> ) parentPos.page ).getPage( parentPos.pos );
- // and go down the tree through the nodes
+ // and go down the tree through the nodes, positioning on the rightmost element
while ( currentDepth < depth - 1 )
{
currentDepth++;
@@ -896,9 +666,6 @@ public class TupleCursor<K, V>
parentPos = stack[depth];
parentPos.pos = child.getNbElems() - 1;
parentPos.page = child;
- ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( parentPos.pos );
- parentPos.valueCursor = valueHolder.getCursor();
- parentPos.valueCursor.afterLast();
return parentPos;
}
@@ -959,7 +726,21 @@ public class TupleCursor<K, V>
/**
- * {@inheritDoc}
+ * Checks if this Cursor is closed. Calls to this operation should not
+ * fail with exceptions if and only if the cursor is in the closed state.
+ *
+ * @return true if this Cursor is closed, false otherwise
+ */
+ public boolean isClosed()
+ {
+ return transaction.isClosed();
+ }
+
+
+ /**
+ * Closes this Cursor and frees any resources it my have allocated.
+ * Repeated calls to this method after this Cursor has already been
+ * called should not fail with exceptions.
*/
public void close()
{
@@ -967,6 +748,62 @@ public class TupleCursor<K, V>
}
+ /**
+ * Closes this Cursor and frees any resources it my have allocated.
+ * Repeated calls to this method after this Cursor has already been
+ * called should not fail with exceptions. The reason argument is
+ * the Exception instance thrown instead of the standard
+ * CursorClosedException.
+ *
+ * @param reason exception thrown when this Cursor is accessed after close
+ */
+ public void close( Exception reason )
+ {
+ transaction.close();
+ }
+
+
+ /**
+ * Gets the object at the current position. Cursor implementations may
+ * choose to reuse element objects by re-populating them on advances
+ * instead of creating new objects on each advance.
+ *
+ * @return the object at the current position
+ * @throws NoSuchElementException if the object at this Cursor's current position
+ * cannot be retrieved, or if this Cursor is closed
+ */
+ public Tuple<K, V> get() throws NoSuchElementException
+ {
+ // First check that we have elements in the BTree
+ if ( ( stack == null ) || ( stack.length == 0 ) )
+ {
+ throw new NoSuchElementException( "No tuple present" );
+ }
+
+ ParentPos<K, V> parentPos = stack[depth];
+
+ if ( ( parentPos.pos != BEFORE_FIRST ) && ( parentPos.pos != AFTER_LAST ) )
+ {
+ // We have some element, build the Tuple
+ // Get the value
+ ValueHolder<V> valueHolder = ( ( AbstractPage<K, V> ) parentPos.page ).getValue( parentPos.pos );
+
+ V value = valueHolder.get();
+
+ // Get the key
+ AbstractPage<K, V> leaf = ( AbstractPage<K, V> ) ( parentPos.page );
+ K key = leaf.getKey( parentPos.pos );
+
+ // Build the Tuple
+ Tuple<K, V> tuple = new Tuple<K, V>( key, value );
+
+ return tuple;
+ }
+
+ throw new NoSuchElementException( "No element at this position : " + parentPos.pos );
+ }
+
+
/**
* Get the creation date
* @return The creation date for this cursor
Modified: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java?rev=1711861&r1=1711860&r2=1711861&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/ValueHolder.java Sun Nov 1 23:01:00 2015
@@ -37,29 +37,17 @@ package org.apache.directory.mavibot.btr
/**
- * @return the number of stored values
+ * @return the value stored in the ValueHolder
*/
- int size();
+ V get();
/**
- * @return a cursor on top of the values
- */
- ValueCursor<V> getCursor();
-
-
- /**
- * @return true if we store the values in a sub btree
- */
- boolean isSubBtree();
-
-
- /**
- * Add a new value in the ValueHolder
+ * Set a new value in the ValueHolder
*
* @param newValue The added value
*/
- void add( V newValue );
+ void set( V newValue );
/**
@@ -68,18 +56,6 @@ package org.apache.directory.mavibot.btr
* @param removedValue The value to remove
*/
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 );
/**
Added: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java?rev=1711861&view=auto
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java (added)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/WALObject.java Sun Nov 1 23:01:00 2015
@@ -0,0 +1,47 @@
+/*
+ * 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;
+
+/**
+ * A WALObject is an object stored in the TransactionContext before weing written on disk.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface WALObject
+{
+ /**
+ * @return The ID associated with the Object
+ */
+ long getId();
+
+
+ /**
+ * @param id Set an ID to this Object
+ */
+ void setId( long id );
+
+
+ /**
+ * @return Serialize the Object into PageIOs
+ */
+ PageIO[] serialize() throws IOException;
+}
Added: directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/CursorException.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/CursorException.java?rev=1711861&view=auto
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/CursorException.java (added)
+++ directory/mavibot/branches/single-value/mavibot/src/main/java/org/apache/directory/mavibot/btree/exception/CursorException.java Sun Nov 1 23:01:00 2015
@@ -0,0 +1,72 @@
+/*
+ * 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.exception;
+
+/**
+ * An class for exceptions which add Cursor specific information to
+ * Exceptions.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CursorException extends Exception
+{
+ /** The serial version UUID */
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ * Creates a new instance of CursorException.
+ */
+ public CursorException()
+ {
+ }
+
+
+ /**
+ * Creates a new instance of CursorException.
+ *
+ * @param explanation The message associated with the exception
+ */
+ public CursorException( String explanation )
+ {
+ super( explanation );
+ }
+
+
+ /**
+ * Creates a new instance of LdapException.
+ */
+ public CursorException( Throwable cause )
+ {
+ super( cause );
+ }
+
+
+ /**
+ * Creates a new instance of CursorException.
+ *
+ * @param explanation The message associated with the exception
+ * @param cause The root cause for this exception
+ */
+ public CursorException( String explanation, Throwable cause )
+ {
+ super( explanation, cause );
+ }
+}
Modified: directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java?rev=1711861&r1=1711860&r2=1711861&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/BulkLoaderTest.java Sun Nov 1 23:01:00 2015
@@ -39,6 +39,7 @@ import java.util.TreeSet;
import org.apache.directory.mavibot.btree.BulkLoader.LevelEnum;
import org.apache.directory.mavibot.btree.exception.BTreeAlreadyManagedException;
+import org.apache.directory.mavibot.btree.exception.CursorException;
import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
import org.apache.directory.mavibot.btree.exception.KeyNotFoundException;
import org.apache.directory.mavibot.btree.serializer.LongSerializer;
@@ -55,7 +56,7 @@ import org.junit.Test;
public class BulkLoaderTest
{
private void checkBtree( BTree<Long, String> oldBtree, BTree<Long, String> newBtree )
- throws EndOfFileExceededException, IOException, KeyNotFoundException
+ throws EndOfFileExceededException, IOException, KeyNotFoundException, CursorException
{
assertEquals( oldBtree.getNbElems(), newBtree.getNbElems() );
@@ -76,79 +77,12 @@ public class BulkLoaderTest
/**
- * Test that we can compact a btree which has no element
- */
- @Test
- public void testInMemoryBulkLoadNoElement() throws IOException, KeyNotFoundException
- {
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- checkBtree( btree, newBtree );
- TupleCursor<Long, String> cursorOld = btree.browse();
- TupleCursor<Long, String> cursorNew = btree.browse();
-
- assertFalse( cursorOld.hasNext() );
- assertFalse( cursorNew.hasNext() );
- }
-
-
- /**
- * Test that we can compact a btree which has a partially full leaf only
- */
- @Ignore
- @Test
- public void testInMemoryBulkLoad3Elements() throws IOException, KeyNotFoundException
- {
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- for ( Long i = 0L; i < 3L; i++ )
- {
- String value = "V" + i;
- btree.insert( i, value );
- }
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- checkBtree( btree, newBtree );
- }
-
-
- /**
- * Test that we can compact a btree which has a 2 full leaves
- */
- @Ignore
- @Test
- public void testInMemoryBulkLoad8Elements() throws IOException, KeyNotFoundException
- {
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- for ( Long i = 0L; i < 8L; i++ )
- {
- String value = "V" + i;
- btree.insert( i, value );
- }
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- checkBtree( btree, newBtree );
- }
-
-
- /**
* Test that we can load 100 BTrees with 0 to 1000 elements
* @throws BTreeAlreadyManagedException
*/
@Test
public void testPersistedBulkLoad1000Elements() throws IOException, KeyNotFoundException,
- BTreeAlreadyManagedException
+ BTreeAlreadyManagedException, CursorException
{
for ( int i = 1000000; i < 1000001; i++ )
{
@@ -266,146 +200,6 @@ public class BulkLoaderTest
/**
- * Test that we can compact a btree which has a full parent node, with all the leaves full.
- */
- @Test
- public void testInMemoryBulkLoad20Elements() throws IOException, KeyNotFoundException
- {
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- for ( Long i = 0L; i < 20L; i++ )
- {
- String value = "V" + i;
- btree.insert( i, value );
- }
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- checkBtree( btree, newBtree );
- }
-
-
- /**
- * Test that we can compact a btree which has two full parent nodes, with all the leaves full.
- * That means we have an upper node with one element.
- */
- @Ignore
- @Test
- public void testInMemoryBulkLoad40Elements() throws IOException, KeyNotFoundException
- {
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- for ( Long i = 0L; i < 40L; i++ )
- {
- String value = "V" + i;
- btree.insert( i, value );
- }
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- checkBtree( btree, newBtree );
- }
-
-
- /**
- * Test that we can compact a btree which has two full parent nodes, with all the leaves full.
- * That means we have an upper node with one element.
- */
- @Test
- public void testInMemoryBulkLoad100Elements() throws IOException, KeyNotFoundException
- {
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- for ( Long i = 0L; i < 100L; i++ )
- {
- String value = "V" + i;
- btree.insert( i, value );
- }
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- checkBtree( btree, newBtree );
- }
-
-
- @Ignore
- @Test
- public void testInMemoryBulkLoadN() throws IOException, KeyNotFoundException
- {
- Random random = new Random( System.nanoTime() );
- long t0 = System.currentTimeMillis();
-
- for ( long n = 0L; n < 2500L; n++ )
- {
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- for ( Long i = 0L; i < n; i++ )
- {
- String value = "V" + i;
- btree.insert( i, value );
- }
-
- //long t1 = System.currentTimeMillis();
-
- //System.out.println( "Delta initial load = " + ( t1 - t0 ) );
-
- //long t2 = System.currentTimeMillis();
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- //long t3 = System.currentTimeMillis();
-
- //System.out.println( "Delta initial load = " + ( t3 - t2 ) );
-
- //System.out.println( "Checking for N = " + n );
- checkBtree( btree, newBtree );
- }
- }
-
-
- @Ignore
- @Test
- public void testInMemoryBulkLoad21() throws IOException, KeyNotFoundException
- {
- Random random = new Random( System.nanoTime() );
- long t0 = System.currentTimeMillis();
-
- BTree<Long, String> btree = BTreeFactory.createInMemoryBTree( "test", LongSerializer.INSTANCE,
- StringSerializer.INSTANCE );
- btree.setPageSize( 4 );
-
- for ( Long i = 0L; i < 21; i++ )
- {
- String value = "V" + i;
- btree.insert( i, value );
- }
-
- //long t1 = System.currentTimeMillis();
-
- //System.out.println( "Delta initial load = " + ( t1 - t0 ) );
-
- //long t2 = System.currentTimeMillis();
-
- BTree<Long, String> newBtree = ( BTree<Long, String> ) BulkLoader.compact( btree );
-
- //long t3 = System.currentTimeMillis();
-
- //System.out.println( "Delta initial load = " + ( t3 - t2 ) );
-
- //System.out.println( "Checking for N = " + 21 );
- checkBtree( btree, newBtree );
- }
-
-
- /**
* test the computeLeafLevel method
*/
@Test
@@ -575,7 +369,7 @@ public class BulkLoaderTest
//@Ignore("The test is failing atm due to the sub-btree construction which is not working correctly when we have too many elements")
@Test
public void testPersistedBulkLoad1000ElementsMultipleValues() throws IOException, KeyNotFoundException,
- BTreeAlreadyManagedException
+ BTreeAlreadyManagedException, CursorException
{
for ( int i = 1; i < 1001; i++ )
{
@@ -709,7 +503,7 @@ public class BulkLoaderTest
*/
@Test
public void testPersistedBulkLoad1000ElementsMultipleValuesDebug() throws IOException, KeyNotFoundException,
- BTreeAlreadyManagedException
+ BTreeAlreadyManagedException, CursorException
{
Random random = new Random( System.currentTimeMillis() );
File file = File.createTempFile( "managedbtreebuilder", ".data" );
Modified: directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java?rev=1711861&r1=1711860&r2=1711861&view=diff
==============================================================================
--- directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java (original)
+++ directory/mavibot/branches/single-value/mavibot/src/test/java/org/apache/directory/mavibot/btree/PageReclaimerTest.java Sun Nov 1 23:01:00 2015
@@ -263,7 +263,6 @@ public class PageReclaimerTest
config.setName( "dump-tree" );
config.setKeySerializer( IntSerializer.INSTANCE );
config.setValueSerializer( StringSerializer.INSTANCE );
- config.setAllowDuplicates( false );
config.setPageSize( 4 );
BTree btree = new PersistedBTree( config );