blob: 8de6ff8fbf0062d949c3886dd9a4241e7de2973b [file] [log] [blame]
/*
* 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.UUID;
import org.apache.commons.io.FileUtils;
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;
import org.apache.directory.mavibot.btree.serializer.StringSerializer;
//import org.ehcache.impl.internal.classes.commonslang.SystemUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
/**
* Tests the browse methods on a managed BTree
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class BTreeBrowseTest
{
private BTree<Long, String> btree = null;
private RecordManager recordManager = null;
@Rule
public TemporaryFolder tempFolder = new TemporaryFolder();
private File dataDir = null;
/**
* Create a BTree for this test
*/
@Before
public void startup() throws Exception
{
dataDir = tempFolder.newFolder( UUID.randomUUID().toString() );
openRecordManagerAndBtree();
// Create a new BTree
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
btree = recordManager.addBTree( writeTxn, "test", LongSerializer.INSTANCE, StringSerializer.INSTANCE );
writeTxn.commit();
}
catch ( Exception e )
{
writeTxn.abort();
throw new RuntimeException( e );
}
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
//MavibotInspector.dumpInfos( recordManager, readTxn.getRecordManagerHeader() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
@After
public void cleanup() throws IOException
{
dataDir = new File( System.getProperty( "java.io.tmpdir" ) + "/recordman" );
if ( dataDir.exists() )
{
FileUtils.deleteDirectory( dataDir );
}
recordManager.close();
}
/**
* Reload the BTree into a new record manager
*/
private void openRecordManagerAndBtree()
{
try
{
if ( recordManager != null )
{
recordManager.close();
}
// Now, try to reload the file back
recordManager = new RecordManager( dataDir.getAbsolutePath(), 1024, 1000 );
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
//MavibotInspector.dumpInfos( recordManager, readTxn.getRecordManagerHeader() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
// load the last created btree
readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
if ( btree != null )
{
btree = readTxn.getBTree( btree.getName() );
}
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
catch ( Exception e )
{
throw new RuntimeException( e );
}
}
/**
* Check a tuple
*/
private void checkTuple( Tuple<Long, String> tuple, long key, String value ) throws EndOfFileExceededException,
IOException
{
assertNotNull( tuple );
assertEquals( key, ( long ) tuple.getKey() );
assertEquals( value, tuple.getValue() );
}
/**
* Check a next() call
*/
private void checkNext( TupleCursor<Long, String> cursor, long key, String value, boolean next, boolean prev )
throws EndOfFileExceededException, IOException
{
Tuple<Long, String> tuple = cursor.next();
checkTuple( tuple, key, value );
assertEquals( next, cursor.hasNext() );
assertEquals( prev, cursor.hasPrev() );
}
/**
* Check a prev() call
*/
private void checkPrev( TupleCursor<Long, String> cursor, long key, String value, boolean next, boolean prev )
throws EndOfFileExceededException, IOException
{
Tuple<Long, String> tuple = cursor.prev();
assertNotNull( tuple );
assertEquals( key, ( long ) tuple.getKey() );
assertEquals( value, tuple.getValue() );
assertEquals( next, cursor.hasNext() );
assertEquals( prev, cursor.hasPrev() );
}
/**
* Construct a String representation of a number padded with 0 on the left
*/
private String toString( long value, int size )
{
String valueStr = Long.toString( value );
StringBuilder sb = new StringBuilder();
if ( size > valueStr.length() )
{
for ( int i = valueStr.length(); i < size; i++ )
{
sb.append( "0" );
}
}
sb.append( valueStr );
return sb.toString();
}
//----------------------------------------------------------------------------------------
// The Browse tests
//----------------------------------------------------------------------------------------
/**
* Test the browse methods on an empty btree
*
* @throws KeyNotFoundException
* @throws CursorException
*/
@Test
public void testBrowseEmptyBTree() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
assertFalse( cursor.hasNext() );
assertFalse( cursor.hasPrev() );
try
{
cursor.next();
fail();
}
catch ( NoSuchElementException nsee )
{
// Expected
}
try
{
cursor.prev();
fail();
}
catch ( NoSuchElementException nsee )
{
// Expected
}
assertEquals( 2L, cursor.getRevision() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browse methods on a btree containing just a leaf
*/
@Test
public void testBrowseBTreeLeafNext() throws Exception
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, 1L, "1" );
btree.insert( writeTxn, 4L, "4" );
btree.insert( writeTxn, 2L, "2" );
btree.insert( writeTxn, 3L, "3" );
btree.insert( writeTxn, 5L, "5" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// Move forward
cursor.beforeFirst();
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
checkNext( cursor, 1L, "1", true, false );
checkNext( cursor, 2L, "2", true, true );
checkNext( cursor, 3L, "3", true, true );
checkNext( cursor, 4L, "4", true, true );
checkNext( cursor, 5L, "5", false, true );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browse methods on a btree containing just a leaf
*/
@Test
public void testBrowseBTreeLeafPrev() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, 1L, "1" );
btree.insert( writeTxn, 4L, "4" );
btree.insert( writeTxn, 2L, "2" );
btree.insert( writeTxn, 3L, "3" );
btree.insert( writeTxn, 5L, "5" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// Move backward
cursor.afterLast();
checkPrev( cursor, 5L, "5", false, true );
checkPrev( cursor, 4L, "4", true, true );
checkPrev( cursor, 3L, "3", true, true );
checkPrev( cursor, 2L, "2", true, true );
checkPrev( cursor, 1L, "1", true, false );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browse methods on a btree containing just a leaf and see if we can
* move at the end or at the beginning
*/
@Test
public void testBrowseBTreeLeafFirstLast() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, 1L, "1" );
btree.insert( writeTxn, 4L, "4" );
btree.insert( writeTxn, 2L, "2" );
btree.insert( writeTxn, 3L, "3" );
btree.insert( writeTxn, 5L, "5" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// We should not be able to move backward
try
{
cursor.prev();
fail();
}
catch ( NoSuchElementException nsee )
{
// Expected
}
// Start browsing three elements
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
Tuple<Long, String> tuple = cursor.next();
tuple = cursor.next();
tuple = cursor.next();
// We should be at 3 now
assertTrue( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
assertEquals( 3L, ( long ) tuple.getKey() );
assertEquals( "3", tuple.getValue() );
// Move to the end
cursor.afterLast();
assertTrue( cursor.hasPrev() );
assertFalse( cursor.hasNext() );
// We should not be able to move forward
try
{
cursor.next();
fail();
}
catch ( NoSuchElementException nsee )
{
// Expected
}
// We should be at 5
tuple = cursor.prev();
assertEquals( 5L, ( long ) tuple.getKey() );
assertEquals( "5", tuple.getValue() );
assertTrue( cursor.hasPrev() );
assertFalse( cursor.hasNext() );
// Move back to the origin
cursor.beforeFirst();
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
// We should be at 1
tuple = cursor.next();
assertEquals( 1L, ( long ) tuple.getKey() );
assertEquals( "1", tuple.getValue() );
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browse methods on a btree containing just a leaf and see if we can
* move back and forth
*/
@Test
public void testBrowseBTreeLeafNextPrev() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, 1L, "1" );
btree.insert( writeTxn, 4L, "4" );
btree.insert( writeTxn, 2L, "2" );
btree.insert( writeTxn, 3L, "3" );
btree.insert( writeTxn, 5L, "5" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// We should not be able to move backward
try
{
cursor.prev();
fail();
}
catch ( NoSuchElementException nsee )
{
// Expected
}
// Start browsing three elements
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
Tuple<Long, String> tuple = cursor.next();
tuple = cursor.next();
tuple = cursor.next();
// We should be at 3 now
assertTrue( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
assertEquals( 3L, ( long ) tuple.getKey() );
assertEquals( "3", tuple.getValue() );
// Now, move to the prev value
tuple = cursor.prev();
assertEquals( 2L, ( long ) tuple.getKey() );
assertEquals( "2", tuple.getValue() );
// And to the next value
tuple = cursor.next();
assertEquals( 3L, ( long ) tuple.getKey() );
assertEquals( "3", tuple.getValue() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Shuffle a set of longs
* @param nbElems
* @return
*/
private void shuffle( long[] values )
{
Random r = new Random( System.nanoTime() );
for ( int i = 0; i < values.length; i++ )
{
values[i] = i;
}
for ( int i = 0; i < values.length*10; i++ )
{
int i1 = r.nextInt( values.length ) ;
int i2 = r.nextInt( values.length ) ;
long tmp = values[i1];
values[i1] = values[i2];
values[i2] = tmp;
}
}
@Test
@Ignore
public void testPerf()
{
Random r = new Random( System.nanoTime() );
long[] values = new long[24];
for ( int i = 0; i < 24; )
{
long v = r.nextLong();
boolean found = false;
for ( long old : values )
{
if ( old == v )
{
found = true;
break;
}
}
if ( !found )
{
values[i] = v;
i++;
}
}
long t0 = System.currentTimeMillis();
for ( int i = 0; i < 50000000; i++ )
{
//TreeMap<Long, Long> treeMap = new TreeMap<>();
List<Long> list = new ArrayList<>();
for ( long v : values )
{
//treeMap.put( v, v );
if ( !list.contains( v ) )
{
list.add( v );
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta = " + ( t1 - t0) );
}
/**
* Test the browse methods on a btree containing many nodes
*/
@Test
public void testBrowseBTreeNodesNext() throws Exception
{
// Inject some data
long increment = 100L;
long nbRound = 10_000L;
long t0 = System.currentTimeMillis();
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
long val = i*increment + j;
//System.out.println( "Injecting " + val );
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.insert( writeTxn, val, Long.toString( val ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta add : " + ( t1 - t0 ) );
System.out.println( "Nb cache hits : " + recordManager.nbCacheHits.get() );
System.out.println( "Nb cache misses : " + recordManager.nbCacheMisses.get() );
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// Move forward
cursor.afterLast();
cursor.beforeFirst();
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
t0 = System.currentTimeMillis();
for ( int loop = 0; loop < 1_000L; loop++ )
{
cursor.beforeFirst();
//assertFalse( cursor.hasPrev() );
//assertTrue( cursor.hasNext() );
//Tuple<Long, String> tuple = cursor.next();
checkNext( cursor, 0L, "0", true, false );
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
for ( long i = 1L; i < nbRound - 1; i++ )
{
//assertTrue( cursor.hasNext() );
//tuple = cursor.next();
//assertTrue( cursor.hasPrev() );
checkNext( cursor, i, Long.toString( i ), true, true );
}
assertTrue( cursor.hasNext() );
//tuple = cursor.next();
//assertFalse( cursor.hasNext() );
checkNext( cursor, nbRound - 1L, Long.toString( nbRound - 1L ), false, true );
}
t1 = System.currentTimeMillis();
System.out.println( "Delta browse : " + ( t1 - t0 ) );
System.out.println( "Nb cache hits : " + recordManager.nbCacheHits.get() );
System.out.println( "Nb cache misses : " + recordManager.nbCacheMisses.get() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
@Test
public void testAddRandom() throws Exception
{
// Inject some data
long increment = 100L;
long nbRound = 100_000L;
long t0 = System.currentTimeMillis();
btree.setPageNbElem( 32 ); // Long + String(long) : 8 bytes + [2 - 10] bytes, max, 56 elems/page
long[] values = new long[(int)nbRound];
for ( long i = 0; i < nbRound; i++ )
{
values[(int)i] = i;
}
shuffle( values );
for ( long i = 0; i < nbRound/increment; i++ )
{
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
long val = values[( int )( i * increment + j )];
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.insert( writeTxn, val, Long.toString( val ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta for " + nbRound + " writes : " + ( t1 - t0 ) );
//MavibotInspector.check( recordManager );
long[] counters = new long[12];
long smaller = Long.MAX_VALUE;
long higher = 0L;
long sum = 0L;
Random rand = new Random( System.nanoTime() );
for ( int k = 0; k < 12; k++ )
{
long tread0 = System.currentTimeMillis();
for ( int i = 0; i < 10; i++ )
{
int counter = 0;
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
for ( int j = 0; j < nbRound; j++ )
{
long key = Math.abs( rand.nextLong()%nbRound );
btree.get( readTxn, key );
counter++;
}
/*
TupleCursor<Long, String> cursor = btree.browse( readTxn );
while ( cursor.hasNext() )
{
cursor.next();
counter++;
}
*/
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
assertEquals( nbRound, counter );
}
long tread1 = System.currentTimeMillis();
System.out.println( "Delta for " + ( nbRound * 1000 ) + " reads[" + k + "] : " + ( tread1 - tread0 ) );
counters[k] = ( tread1 - tread0 );
if ( counters[k] < smaller )
{
smaller = counters[k];
}
if ( counters[k] > higher )
{
higher = counters[k];
}
sum += counters[k];
System.out.println( "Hits : " + recordManager.nbCacheHits );
System.out.println( "Misses : " + recordManager.nbCacheMisses );
}
sum -= smaller;
sum -= higher;
System.out.println( "Average : " + ( sum / 10 ) );
// Now delete the elements
shuffle( values );
long tt0 = System.currentTimeMillis();
//increment = 1L;
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
int elemNb = ( int )( i * increment + j );
long val = values[elemNb];
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.delete( writeTxn, val );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long tt1 = System.currentTimeMillis();
System.out.println( "Delta for " + nbRound + " deletes : " + ( tt1 - tt0 ) );
}
@Test
public void testReopen() throws Exception
{
// Inject some data
long increment = 1L;
long nbRound = 100L;
long t0 = System.currentTimeMillis();
long[] values = new long[(int)nbRound];
for ( long i = 0; i < nbRound; i++ )
{
values[(int)i] = i;
}
//shuffle( values );
//printValues( values );
values = new long[]
{
38, 40, 61, 34, 9, 59, 78, 30, 42, 76, 84, 52, 37, 58, 88, 27, 24, 22, 33, 39,
74, 44, 65, 45, 70, 98, 64, 99, 31, 19, 95, 57, 35, 90, 68, 1, 12, 69, 77, 73, 83,
6, 96, 80, 7, 23, 43, 85, 36, 48, 32, 66, 53, 87, 16, 10, 15, 13, 5, 91, 54, 71,
92, 72, 82, 63, 97, 62, 26, 56, 41, 18, 11, 3, 21, 75, 46, 67, 93, 2, 28, 29, 25,
14, 0, 94, 4, 81, 20, 55, 8, 79, 51, 50, 60, 86, 89, 47, 49, 17
};
for ( long i = 0; i < nbRound/increment; i++ )
{
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
int pos = ( int )( i * increment + j );
long val = values[pos];
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.insert( writeTxn, val, Long.toString( val ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
recordManager.close();
recordManager = new RecordManager( dataDir.getAbsolutePath() );
int counter = 0;
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
while ( cursor.hasNext() )
{
cursor.next();
counter++;
}
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
assertEquals( nbRound, counter );
// Now delete the elements
//shuffle( values );
//printValues( values );
values = new long[]
{
13, 42, 95, 59, 96, 62, 39, 90, 32, 5, 20, 7, 37, 63, 25, 17, 23, 97, 4, 16,
53, 69, 89, 9, 80, 71, 19, 22, 31, 33, 12, 29, 34, 65, 6, 57, 15, 18, 24, 93, 38,
92, 83, 98, 28, 0, 21, 94, 8, 64, 14, 40, 48, 26, 41, 66, 81, 52, 82, 88, 68, 74,
55, 84, 54, 79, 61, 87, 67, 99, 36, 47, 1, 86, 58, 50, 51, 75, 49, 56, 27, 78, 60,
45, 30, 77, 46, 73, 35, 43, 91, 85, 70, 44, 11, 10, 3, 72, 2, 76
};
increment = 1L;
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
int elemNb = ( int )( i * increment + j );
long val = values[elemNb];
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.delete( writeTxn, val );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
}
private void printValues( long[] values )
{
boolean isFirst = true;
int nbVal = 0;
StringBuilder sb = new StringBuilder();
for ( long val : values )
{
if ( isFirst )
{
sb.append( " long[] values = new long[]\n {\n " );
isFirst = false;
}
else
{
sb.append( ", " );
}
if ( nbVal == 20 )
{
nbVal = 0;
sb.append( "\n " );
}
else
{
nbVal++;
}
sb.append( val );
}
sb.append( "\n };" );
System.out.println( sb.toString() );
}
@Test
public void testDeleteDebug() throws Exception
{
btree.setPageNbElem( 4 );
// Inject some data
long increment = 20L;
long nbRound = 1000L;
long t0 = System.currentTimeMillis();
long[] values = new long[]
{
962, 598, 975, 719, 246, 498, 482, 326, 205, 777, 73, 12, 847, 428, 934, 533, 149, 20, 334, 686,
139, 40, 640, 438, 838, 999, 827, 560, 658, 868, 798, 55, 112, 315, 435, 153, 451, 280, 570, 769, 665,
821, 86, 780, 587, 557, 900, 59, 884, 657, 240, 324, 448, 287, 92, 693, 169, 439, 959, 677, 254, 23,
212, 22, 387, 765, 596, 915, 486, 573, 219, 339, 304, 16, 187, 823, 933, 423, 109, 113, 741, 436, 420,
290, 250, 926, 181, 150, 321, 558, 67, 628, 432, 90, 745, 302, 586, 742, 521, 910, 978, 314, 322, 568,
295, 221, 178, 316, 360, 552, 747, 309, 578, 588, 8, 503, 244, 468, 261, 269, 846, 170, 367, 815, 459,
750, 607, 662, 399, 427, 79, 496, 7, 15, 203, 717, 264, 664, 799, 887, 687, 278, 143, 793, 383, 623,
553, 325, 446, 536, 335, 692, 297, 257, 273, 495, 699, 499, 60, 308, 141, 58, 951, 976, 106, 480, 901,
947, 104, 224, 861, 146, 694, 466, 547, 229, 525, 133, 262, 748, 487, 801, 283, 878, 505, 718, 906, 230,
709, 164, 182, 862, 49, 582, 831, 300, 2, 614, 527, 621, 402, 194, 585, 253, 667, 215, 108, 963, 886,
648, 161, 350, 924, 391, 422, 63, 775, 405, 740, 381, 601, 98, 970, 948, 688, 500, 53, 344, 35, 803,
771, 61, 235, 708, 892, 0, 42, 701, 208, 863, 356, 713, 802, 158, 920, 888, 24, 974, 540, 368, 794,
770, 492, 561, 370, 29, 622, 17, 619, 893, 983, 817, 567, 345, 767, 818, 564, 995, 929, 199, 425, 174,
816, 424, 992, 515, 569, 602, 218, 659, 781, 216, 225, 790, 416, 213, 627, 103, 551, 579, 954, 372, 171,
398, 768, 75, 909, 833, 33, 822, 969, 679, 882, 695, 167, 649, 592, 964, 263, 788, 864, 41, 227, 876,
896, 875, 268, 691, 609, 418, 319, 606, 421, 732, 68, 542, 479, 464, 36, 826, 122, 668, 493, 944, 537,
96, 508, 147, 660, 516, 475, 941, 37, 298, 461, 114, 891, 13, 841, 584, 997, 766, 674, 313, 656, 160,
787, 384, 172, 689, 65, 559, 762, 286, 785, 837, 100, 931, 867, 120, 949, 942, 129, 4, 115, 359, 755,
354, 987, 39, 676, 724, 624, 11, 365, 458, 705, 245, 825, 782, 895, 911, 144, 866, 443, 835, 946, 156,
773, 21, 714, 54, 419, 756, 470, 743, 338, 341, 204, 734, 238, 357, 807, 267, 855, 47, 433, 460, 544,
604, 829, 548, 943, 550, 532, 990, 353, 671, 131, 471, 871, 340, 201, 501, 51, 452, 562, 510, 196, 851,
883, 965, 28, 337, 727, 77, 574, 507, 481, 546, 200, 539, 565, 362, 912, 43, 778, 595, 34, 666, 409,
27, 66, 491, 814, 226, 389, 608, 291, 407, 472, 454, 673, 168, 3, 638, 366, 210, 277, 397, 519, 469,
95, 758, 956, 563, 889, 123, 738, 902, 198, 710, 981, 955, 760, 97, 166, 819, 260, 850, 957, 351, 549,
434, 632, 57, 809, 32, 299, 259, 1, 581, 848, 860, 396, 828, 744, 274, 746, 414, 214, 327, 26, 99,
71, 415, 14, 494, 683, 786, 38, 31, 986, 820, 64, 348, 395, 626, 634, 9, 852, 531, 307, 543, 958,
455, 132, 806, 594, 330, 994, 935, 752, 968, 761, 504, 430, 288, 796, 897, 647, 282, 918, 706, 233, 730,
332, 117, 25, 485, 757, 162, 642, 824, 93, 83, 333, 222, 441, 52, 363, 857, 928, 529, 232, 84, 776,
843, 483, 700, 711, 456, 523, 591, 655, 853, 251, 369, 960, 996, 654, 101, 393, 797, 50, 859, 292, 795,
406, 590, 932, 85, 530, 352, 145, 725, 922, 927, 388, 275, 937, 961, 175, 513, 284, 885, 749, 124, 753,
437, 804, 832, 840, 111, 258, 242, 630, 121, 78, 739, 764, 572, 107, 830, 779, 94, 509, 808, 890, 159,
684, 707, 457, 236, 980, 880, 940, 88, 600, 759, 192, 331, 952, 731, 239, 184, 899, 663, 317, 207, 318,
979, 392, 234, 462, 189, 580, 105, 763, 478, 18, 939, 467, 364, 904, 643, 938, 620, 858, 998, 811, 417,
813, 720, 135, 445, 10, 46, 783, 228, 898, 715, 408, 873, 612, 48, 571, 231, 792, 905, 675, 680, 704,
252, 526, 358, 716, 615, 426, 394, 599, 916, 248, 220, 751, 126, 678, 522, 812, 431, 726, 839, 349, 346,
157, 134, 87, 844, 62, 74, 894, 512, 490, 404, 528, 281, 69, 712, 836, 834, 279, 82, 474, 800, 271,
945, 610, 669, 791, 917, 444, 217, 524, 382, 541, 342, 617, 410, 152, 737, 136, 163, 930, 361, 907, 636,
877, 518, 127, 403, 223, 130, 772, 682, 237, 914, 400, 881, 872, 633, 685, 312, 211, 729, 449, 310, 19,
936, 188, 272, 266, 118, 625, 611, 465, 810, 142, 125, 151, 735, 256, 670, 593, 650, 328, 440, 984, 870,
378, 520, 566, 723, 556, 616, 255, 646, 545, 514, 371, 320, 605, 347, 249, 476, 165, 950, 702, 138, 506,
966, 265, 576, 185, 56, 774, 698, 805, 177, 629, 190, 305, 390, 186, 323, 644, 183, 76, 635, 209, 80,
583, 869, 923, 991, 789, 375, 577, 155, 639, 116, 988, 502, 128, 672, 645, 270, 285, 180, 343, 971, 385,
511, 247, 137, 110, 119, 989, 442, 736, 879, 429, 603, 294, 697, 589, 450, 6, 690, 179, 45, 72, 473,
453, 311, 243, 463, 754, 661, 874, 30, 534, 303, 919, 631, 681, 376, 722, 488, 972, 993, 489, 925, 447,
651, 355, 842, 154, 81, 575, 733, 921, 903, 703, 148, 484, 653, 379, 70, 554, 967, 652, 973, 301, 721,
597, 276, 306, 380, 977, 477, 641, 197, 206, 377, 535, 497, 696, 293, 373, 908, 845, 191, 618, 555, 538,
728, 784, 411, 982, 140, 289, 5, 176, 413, 517, 296, 102, 173, 44, 613, 386, 856, 91, 89, 241, 913,
849, 953, 865, 637, 193, 985, 401, 412, 202, 195, 336, 374, 329, 854
};
for ( long i = 0; i < nbRound; i++ )
{
values[(int)i] = i;
}
//shuffle( values );
//printValues( values );
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
long val = values[( int )( i * increment + j )];
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.insert( writeTxn, val, Long.toString( val ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
int counter = 0;
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
while ( cursor.hasNext() )
{
cursor.next();
counter++;
}
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
assertEquals( nbRound, counter );
readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
// Now delete the elements
//shuffle( values );
//printValues( values );
values = new long[]
{
477, 459, 542, 462, 119, 743, 714, 881, 24, 561, 550, 583, 38, 562, 417, 954, 893, 421, 173, 25,
766, 70, 928, 685, 797, 839, 313, 599, 885, 386, 573, 246, 763, 936, 430, 380, 327, 169, 318, 631, 677,
332, 123, 596, 312, 449, 105, 129, 533, 435, 985, 465, 978, 3, 315, 911, 463, 632, 520, 323, 142, 19,
937, 609, 755, 216, 614, 329, 617, 628, 87, 440, 745, 222, 616, 842, 657, 856, 776, 405, 373, 841, 292,
389, 107, 309, 947, 460, 930, 43, 636, 961, 886, 703, 57, 718, 431, 39, 643, 224, 383, 269, 896, 346,
579, 512, 147, 910, 448, 234, 706, 995, 296, 917, 442, 131, 721, 487, 209, 126, 339, 555, 33, 475, 876,
135, 957, 408, 199, 571, 557, 554, 396, 31, 35, 8, 948, 395, 914, 905, 214, 601, 809, 64, 761, 551,
700, 575, 106, 65, 193, 275, 606, 892, 41, 875, 420, 852, 168, 879, 238, 618, 996, 356, 515, 91, 553,
402, 26, 895, 83, 756, 227, 788, 784, 964, 974, 391, 494, 748, 334, 211, 942, 864, 452, 682, 270, 50,
653, 593, 367, 68, 861, 289, 900, 218, 711, 413, 615, 656, 854, 869, 534, 923, 675, 285, 673, 267, 932,
497, 316, 139, 620, 567, 751, 759, 48, 965, 314, 845, 630, 658, 172, 384, 707, 683, 186, 953, 406, 32,
783, 728, 587, 882, 15, 559, 539, 742, 870, 828, 655, 713, 22, 716, 984, 693, 749, 723, 972, 114, 511,
345, 27, 264, 350, 704, 662, 272, 970, 621, 454, 484, 437, 916, 310, 560, 358, 200, 684, 196, 324, 890,
92, 20, 605, 546, 127, 291, 526, 790, 337, 732, 151, 758, 966, 924, 578, 423, 818, 701, 66, 590, 441,
752, 582, 453, 991, 793, 230, 804, 377, 245, 705, 648, 153, 295, 623, 128, 258, 833, 753, 989, 100, 425,
496, 600, 7, 152, 342, 439, 176, 143, 73, 810, 592, 674, 495, 538, 192, 122, 979, 306, 671, 540, 271,
519, 754, 164, 805, 777, 665, 501, 821, 522, 474, 125, 692, 308, 158, 456, 365, 819, 846, 277, 263, 221,
543, 353, 175, 51, 155, 687, 604, 960, 796, 254, 720, 443, 6, 897, 336, 278, 719, 891, 572, 872, 447,
466, 779, 997, 398, 351, 480, 159, 253, 612, 949, 814, 328, 789, 60, 565, 299, 162, 467, 851, 531, 212,
906, 727, 803, 228, 799, 827, 40, 689, 58, 986, 568, 231, 201, 768, 82, 873, 77, 348, 775, 45, 624,
28, 134, 969, 49, 154, 18, 364, 999, 676, 633, 668, 737, 778, 971, 547, 170, 840, 436, 21, 444, 798,
232, 85, 874, 666, 108, 925, 862, 481, 629, 934, 446, 410, 871, 317, 392, 516, 699, 530, 887, 335, 859,
30, 229, 78, 645, 902, 800, 301, 67, 355, 619, 563, 834, 988, 379, 903, 322, 2, 300, 394, 667, 381,
10, 717, 149, 427, 409, 217, 787, 724, 963, 830, 148, 69, 235, 469, 124, 597, 97, 549, 794, 378, 341,
785, 801, 847, 849, 478, 260, 145, 920, 652, 837, 973, 843, 177, 762, 188, 962, 347, 491, 844, 922, 608,
907, 992, 670, 697, 184, 23, 344, 510, 880, 865, 262, 935, 207, 458, 330, 982, 654, 878, 595, 868, 112,
939, 607, 321, 532, 528, 72, 663, 294, 369, 411, 182, 251, 130, 698, 817, 760, 951, 722, 366, 712, 850,
857, 544, 136, 509, 412, 86, 117, 79, 113, 215, 382, 101, 426, 102, 103, 933, 244, 359, 634, 884, 503,
290, 672, 644, 265, 651, 94, 816, 577, 500, 223, 527, 750, 735, 226, 338, 362, 586, 450, 541, 434, 249,
588, 121, 836, 598, 918, 240, 994, 422, 403, 288, 388, 397, 472, 659, 564, 625, 42, 204, 493, 191, 537,
187, 715, 237, 208, 738, 505, 926, 853, 220, 639, 393, 93, 12, 647, 326, 281, 451, 118, 782, 640, 990,
374, 940, 213, 944, 832, 138, 471, 773, 908, 977, 202, 55, 268, 53, 116, 464, 998, 650, 319, 680, 210,
729, 952, 286, 11, 764, 611, 433, 955, 400, 160, 780, 570, 822, 407, 349, 866, 284, 490, 709, 171, 185,
558, 502, 479, 461, 225, 694, 980, 390, 813, 418, 938, 104, 89, 241, 311, 913, 280, 357, 904, 976, 638,
178, 476, 424, 679, 771, 370, 298, 166, 63, 483, 807, 203, 489, 189, 95, 283, 62, 331, 525, 695, 860,
368, 678, 16, 363, 75, 855, 946, 37, 959, 646, 792, 219, 414, 252, 956, 54, 195, 642, 603, 302, 791,
486, 372, 261, 34, 361, 150, 1, 726, 146, 521, 580, 276, 432, 325, 734, 157, 696, 233, 919, 731, 255,
110, 909, 806, 993, 257, 688, 293, 835, 132, 499, 156, 194, 740, 536, 808, 320, 594, 181, 641, 340, 746,
690, 376, 498, 115, 206, 61, 757, 47, 867, 576, 820, 637, 399, 610, 385, 730, 297, 180, 141, 248, 266,
517, 56, 17, 236, 802, 767, 812, 591, 360, 921, 649, 602, 183, 725, 710, 488, 535, 772, 627, 898, 98,
901, 507, 163, 589, 552, 273, 584, 975, 770, 664, 958, 929, 71, 899, 84, 669, 894, 46, 774, 848, 419,
987, 795, 304, 333, 9, 282, 5, 354, 514, 404, 927, 983, 585, 574, 781, 303, 545, 581, 29, 556, 259,
96, 877, 529, 811, 825, 415, 548, 120, 375, 287, 445, 945, 243, 14, 99, 686, 438, 635, 863, 508, 482,
826, 90, 111, 736, 428, 769, 473, 88, 660, 824, 823, 950, 416, 239, 702, 931, 13, 889, 915, 0, 144,
343, 741, 566, 941, 371, 661, 829, 733, 161, 274, 401, 815, 513, 981, 76, 305, 250, 205, 883, 455, 626,
968, 786, 967, 44, 943, 681, 198, 739, 506, 858, 523, 80, 133, 765, 708, 744, 179, 468, 429, 485, 256,
457, 4, 242, 74, 518, 52, 524, 691, 387, 492, 307, 912, 831, 613, 888, 167, 247, 838, 81, 279, 109,
190, 352, 470, 59, 140, 174, 504, 165, 747, 137, 622, 36, 569, 197
};
increment = 1L;
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
int elemNb = ( int )( i * increment + j );
long val = values[elemNb];
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.delete( writeTxn, val );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
}
@Test
public void testDelete() throws Exception
{
//btree.setPageNbElem( 8 );
// Inject some data
long increment = 1_000L;
long nbRound = 10_000L;
long t0 = System.currentTimeMillis();
long[] values = new long[(int)nbRound];
for ( long i = 0; i < nbRound; i++ )
{
values[(int)i] = i;
}
shuffle( values );
//printValues( values );
/*values = new long[]
{
71, 61, 17, 29, 86, 3, 26, 40, 73, 89, 15, 83, 65, 34, 53, 24, 14, 1, 36, 75,
80, 74, 23, 6, 19, 94, 2, 90, 85, 98, 41, 84, 69, 79, 56, 48, 52, 72, 39, 13, 57,
12, 45, 97, 59, 5, 35, 16, 58, 21, 81, 54, 42, 28, 66, 22, 91, 64, 51, 60, 70, 62,
92, 46, 4, 37, 32, 96, 31, 50, 33, 77, 99, 27, 49, 67, 47, 43, 68, 78, 20, 9, 38,
8, 18, 25, 10, 30, 0, 82, 76, 87, 55, 44, 95, 88, 93, 11, 63, 7
};
*/
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
long val = values[( int )( i * increment + j )];
//System.out.println( "\n\nInjecting " + val );
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.insert( writeTxn, val, Long.toString( val ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
int counter = 0;
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
while ( cursor.hasNext() )
{
cursor.next();
counter++;
}
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
assertEquals( nbRound, counter );
// Now delete the elements
shuffle( values );
//printValues( values );
/*
values = new long[]
{
88, 87, 32, 74, 16, 18, 70, 99, 62, 19, 5, 40, 7, 73, 21, 22, 79, 13, 89, 9,
42, 17, 20, 68, 8, 65, 78, 31, 30, 69, 92, 57, 50, 29, 98, 34, 52, 35, 12, 27, 1,
53, 82, 39, 44, 76, 55, 61, 24, 10, 36, 14, 33, 48, 80, 15, 28, 64, 49, 97, 77, 43,
47, 56, 37, 71, 81, 63, 6, 38, 84, 23, 93, 67, 95, 96, 54, 60, 91, 51, 94, 58, 85,
11, 83, 72, 45, 0, 46, 26, 2, 25, 86, 3, 59, 75, 90, 66, 41, 4
};
//increment = 1L;
*/
long tt0 = System.currentTimeMillis();
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
int elemNb = ( int )( i * increment + j );
long val = values[elemNb];
//System.out.println( "Deleting " + elemNb + "th element : " + val );
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.delete( writeTxn, val );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long tt1 = System.currentTimeMillis();
System.out.println( "Delta for " + nbRound + " : " + ( tt1 - tt0 ) );
}
@Test
public void testDeleteRandom() throws Exception
{
btree.setPageNbElem( 4 );
// Inject some data
long increment = 1L;
long t0 = System.currentTimeMillis();
//long[] values = new long[(int)nbRound];
long[] values = new long[]
{
6, 9, 4, 13, 10, 12, 11, 3, 2, 8,
15, 16, 7, 14, 1, 5, 0
};
long nbRound = values.length;
/*
for ( long i = 0; i < nbRound; i++ )
{
values[(int)i] = i;
}
shuffle( values );
*/
for ( long i = 0; i < nbRound/increment; i++ )
{
//System.out.println( "\nInserting " + i + " in the tree ---->" );
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
long val = values[( int )( i * increment + j )];
//System.out.println( "Injecting " + val );
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.insert( writeTxn, val, Long.toString( val ) );
}
System.out.println( btree );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta for " + nbRound + " : " + ( t1 - t0 ) );
int counter = 0;
/*values = new long[]
{
13, 14
};*/
for ( long i = 0; i < nbRound/increment; i++ )
{
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
long val = values[( int )( i * increment + j )];
System.out.println( "Deleting " + val );
btree.delete( writeTxn, val );
System.out.println( btree );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
}
/**
* Test the browse methods on a btree containing many nodes
*/
@Test
public void testDeleteBTreeNodes() throws Exception
{
// Inject some data
long increment = 2L;
long nbRound = 32L;
long t0 = System.currentTimeMillis();
for ( long i = 0; i < nbRound/increment; i++ )
{
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long j = 0; j < increment; j++ )
{
long val = i*increment + j;
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.insert( writeTxn, val, Long.toString( val ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
}
long t1 = System.currentTimeMillis();
System.out.println( "Delta add : " + ( t1 - t0 ) );
System.out.println( "File name : " + dataDir );
long[] values = new long[(int)nbRound];
for ( long i = 0; i < nbRound; i++ )
{
values[(int)i] = i;
}
shuffle( values );
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
long t10 = System.currentTimeMillis();
for ( int i = 0; i < nbRound/increment; i++ )
{
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( int j = 0; j < increment; j++ )
{
int index = (int)(i*increment + j);
//MavibotInspector.check( recordManager, recordManager.getRecordManagerHeader() );
btree.delete( writeTxn, values[index] );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Check that we can still browse the tree
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> readBtree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = readBtree.browse( readTxn );
cursor.beforeFirst();
int nbElems = 0;
while ( cursor.hasNext() )
{
cursor.next();
nbElems++;
}
assertEquals( nbElems, nbRound - increment * ( i + 1 ) );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
long t11 = System.currentTimeMillis();
System.out.println( "Delta delete : " + ( t11 - t10 ) );
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// Move forward
cursor.afterLast();
cursor.beforeFirst();
assertFalse( cursor.hasPrev() );
assertFalse( cursor.hasNext() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browse methods on a btree containing many nodes
*/
@Test
public void testBrowseBTreeNodesPrev() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long i = 1; i < 1_000L; i++ )
{
btree.insert( writeTxn, i, Long.toString( i ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
//MavibotInspector.check( recordManager, recordManager.getCurrentRecordManagerHeader() );
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// Move backward
cursor.afterLast();
assertTrue( cursor.hasPrev() );
assertFalse( cursor.hasNext() );
checkPrev( cursor, 999L, "999", false, true );
for ( long i = 998L; i > 1L; i-- )
{
checkPrev( cursor, i, Long.toString( i ), true, true );
}
assertTrue( cursor.hasPrev() );
checkPrev( cursor, 1L, "1", true, false );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browse methods on a btree containing just a leaf with duplicate values
*/
@Test
public void testBrowseBTreeLeafNextDupsN() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
// Inject some duplicate data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, 1L, "1" );
btree.insert( writeTxn, 1L, "4" );
btree.insert( writeTxn, 1L, "2" );
btree.insert( writeTxn, 2L, "3" );
btree.insert( writeTxn, 3L, "5" );
btree.insert( writeTxn, 3L, "7" );
btree.insert( writeTxn, 3L, "6" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// Move forward
cursor.beforeFirst();
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
checkNext( cursor, 1L, "2", true, false );
checkNext( cursor, 2L, "3", true, true );
checkNext( cursor, 3L, "6", false, true );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
//----------------------------------------------------------------------------------------
// The BrowseFrom tests
//----------------------------------------------------------------------------------------
/**
* Test the browseFrom method on an empty tree
*/
@Test
public void testBrowseFromEmptyBTree() throws IOException, BTreeAlreadyManagedException
{
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browseFrom( readTxn, 1L );
assertFalse( cursor.hasNext() );
assertFalse( cursor.hasPrev() );
try
{
cursor.next();
fail();
}
catch ( NoSuchElementException nsee )
{
// Expected
}
try
{
cursor.prev();
fail();
}
catch ( NoSuchElementException nsee )
{
// Expected
}
assertEquals( -1L, cursor.getRevision() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browseFrom methods on a btree containing just a leaf
*/
@Test
public void testBrowseFromBTreeLeaf() throws IOException, BTreeAlreadyManagedException
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, 1L, "1" );
btree.insert( writeTxn, 7L, "7" );
btree.insert( writeTxn, 3L, "3" );
btree.insert( writeTxn, 5L, "5" );
btree.insert( writeTxn, 9L, "9" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor, starting at 5
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browseFrom( readTxn, 5L );
assertTrue( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
assertEquals( 5L, cursor.get().key.longValue() );
// Move forward
checkNext( cursor, 7L, "7", true, true );
checkNext( cursor, 9L, "9", false, true );
cursor.close();
// now, start at 5 and move backward
cursor = btree.browseFrom( readTxn, 5L );
assertTrue( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
// Move backward
checkPrev( cursor, 3L, "3", true, true );
checkPrev( cursor, 1L, "1", true, false );
cursor.close();
// Start at the first key
cursor = btree.browseFrom( readTxn, 1L );
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
checkNext( cursor, 3L, "3", true, true );
// Start before the first key
cursor = btree.browseFrom( readTxn, 0L );
assertFalse( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
checkNext( cursor, 1L, "1", true, false );
checkNext( cursor, 3L, "3", true, true );
// Start at the last key
cursor = btree.browseFrom( readTxn, 9L );
assertTrue( cursor.hasPrev() );
assertFalse( cursor.hasNext() );
checkPrev( cursor, 7L, "7", true, true );
// Start after the last key
cursor = btree.browseFrom( readTxn, 10L );
assertTrue( cursor.hasPrev() );
assertFalse( cursor.hasNext() );
checkPrev( cursor, 9L, "9", false, true );
checkPrev( cursor, 7L, "7", true, true );
// Start in the middle with a non existent key
cursor = btree.browseFrom( readTxn, 4L );
assertTrue( cursor.hasPrev() );
assertTrue( cursor.hasNext() );
checkNext( cursor, 7L, "7", true, true );
// Start in the middle with a non existent key
cursor = btree.browseFrom( readTxn, 4L );
checkPrev( cursor, 3L, "3", true, true );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the browseFrom method on a btree with a non existing key
*/
@Test
public void testBrowseFromBTreeNodesNotExistingKey() throws IOException, BTreeAlreadyManagedException
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long i = 0; i <= 1000L; i += 2 )
{
btree.insert( writeTxn, i, Long.toString( i ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browseFrom( readTxn, 1500L );
assertFalse( cursor.hasNext() );
assertTrue( cursor.hasPrev() );
assertEquals( 1000L, cursor.prev().getKey().longValue() );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the TupleCursor.moveToPrevNonDuplicateKey method on a B-tree containing nodes
*/
@Test
public void testPrevKey() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
for ( long i = 1; i < 1000L; i++ )
{
try
{
btree.insert( writeTxn, i, Long.toString( i ) );
}
catch ( Exception e )
{
e.printStackTrace();
}
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
// Create the cursor
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
// Move backward
cursor.afterLast();
assertTrue( cursor.hasPrev() );
assertFalse( cursor.hasNext() );
boolean next = false;
boolean prev = true;
for ( long i = 999L; i > 0L; i-- )
{
Tuple<Long, String> tuple = cursor.prev();
if ( i == 1L )
{
prev = false;
}
checkTuple( tuple, i, Long.toString( i ) );
assertEquals( next, cursor.hasNext() );
assertEquals( prev, cursor.hasPrev() );
if ( i == 999L )
{
next = true;
}
}
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
/**
* Test the overwriting of elements
*/
@Test
public void testOverwrite() throws Exception
{
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, 1L, "1" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
assertTrue( btree.hasKey( readTxn, 1L ) );
assertEquals( "1", btree.get( readTxn, 1L ) );
writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
btree.insert( writeTxn, 1L, "10" );
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
assertTrue( btree.hasKey( readTxn, 1L ) );
assertEquals( "10", btree.get( readTxn, 1L ) );
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
btree.close();
}
//@Ignore("test used for debugging")
@Test
public void testAdd20Random() throws IOException, BTreeAlreadyManagedException, KeyNotFoundException, CursorException
{
long[] values = new long[]
{
14, 7, 43, 37, 49, 3, 20, 26, 17, 29,
40, 33, 21, 18, 9, 30, 45, 36, 12, 8
};
btree.setPageNbElem( 4 );
// Inject some data
WriteTransaction writeTxn = null;
try
{
writeTxn = recordManager.beginWriteTransaction();
for ( long value : values )
{
BTree<Long, String> btree = writeTxn.getBTree( "test" );
btree.insert( writeTxn, value, Long.toString( value ) );
}
writeTxn.commit();
}
catch ( IOException ioe )
{
if ( writeTxn != null )
{
writeTxn.abort();
}
}
MavibotInspector.check( recordManager );
Transaction readTxn = null;
try
{
readTxn = recordManager.beginReadTransaction();
BTree<Long, String> btree = readTxn.getBTree( "test" );
TupleCursor<Long, String> cursor = btree.browse( readTxn );
while ( cursor.hasNext() )
{
cursor.next();
}
readTxn.commit();
readTxn.commit();
}
catch ( Exception e )
{
if ( readTxn != null )
{
readTxn.abort();
}
}
}
}