blob: a9392234b84fbac46d09ff566b69bd0c687eaa1b [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 jdbm.btree;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.io.Serializable;
import java.util.concurrent.Semaphore;
import jdbm.RecordManager;
import jdbm.RecordManagerFactory;
import jdbm.helper.IntegerComparator;
import jdbm.helper.Tuple;
import jdbm.helper.TupleBrowser;
import jdbm.recman.SnapshotRecordManager;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import com.mycila.junit.concurrent.Concurrency;
import com.mycila.junit.concurrent.ConcurrentJunitRunner;
/**
*
* TODO SnapshotBTree.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@RunWith(ConcurrentJunitRunner.class)
@Concurrency()
public class SnapshotBTree
{
public TemporaryFolder folder = new TemporaryFolder();
private static class IntWrapper implements Serializable
{
int value;
IntWrapper( int value )
{
this.value = value;
}
}
private String getTemporaryFile( String name ) throws IOException
{
String file = folder.newFile( name ).getAbsolutePath();
return file;
}
@Test
public void testBasic1() throws IOException, InterruptedException
{
RecordManager recman;
BTree<Integer, IntWrapper> tree;
int idx;
int numReadThreads = 1;
TestThread readThreads[] = new TestThread[numReadThreads];
TestThread updateThread;
Semaphore browseSem = new Semaphore( 0 );
Semaphore updateSem = new Semaphore( 0 );
recman = RecordManagerFactory.createRecordManager( getTemporaryFile( "testBasic1" ) );
SnapshotRecordManager snapshotRecman = new SnapshotRecordManager( recman, 1 << 12 );
tree = new BTree<Integer, IntWrapper>( snapshotRecman, new IntegerComparator() );
for ( idx = 0; idx < 1024; idx++ )
{
tree.insert( new Integer( idx ), new IntWrapper( idx ), true );
}
for ( idx = 0; idx < numReadThreads; idx++ )
{
readThreads[idx] = new TestThread( true, tree, browseSem, updateSem, numReadThreads );
}
updateThread = new TestThread( false, tree, browseSem, updateSem, numReadThreads );
updateThread.start();
for ( idx = 0; idx < numReadThreads; idx++ )
{
readThreads[idx].start();
}
for ( idx = 0; idx < numReadThreads; idx++ )
{
readThreads[idx].join();
}
updateThread.join();
snapshotRecman.close();
}
class TestThread extends Thread
{
boolean readOnly;
BTree<Integer, IntWrapper> btree;
Semaphore browseSem;
Semaphore updateSem;
int numReadThreads;
TestThread( boolean readOnly, BTree<Integer, IntWrapper> btree, Semaphore firstBrowse,
Semaphore updateDone, int numReadThreads)
{
this.readOnly = readOnly;
this.btree = btree;
this.browseSem = firstBrowse;
this.updateSem = updateDone;
this.numReadThreads = numReadThreads;
}
private void readOnlyActions() throws IOException, InterruptedException
{
int count = 0;
int idx;
TupleBrowser<Integer, IntWrapper> browser = btree.browse();
Tuple<Integer, IntWrapper> tuple = new Tuple();
browseSem.release();
assertTrue( browser.getNext( tuple ) );
assertEquals( tuple.getKey().intValue(), 0 );
count++;
assertTrue( browser.getNext( tuple ) );
assertEquals( tuple.getKey().intValue(), 1 );
count++;
while( browser.getNext( tuple ) )
{
count++;
// Sleep a little randomly.
if ( (count & 7) == 0 )
Thread.sleep( 1 );
assertTrue( tuple.getValue().value != -1 );
}
System.out.println( "count is " + count );
assertEquals( count, 1024 );
browser.close();
updateSem.acquireUninterruptibly();
browser = btree.browse( new Integer( 10 ) );
browseSem.release();
for ( idx = 20; idx < 1024; idx++ )
{
assertTrue( browser.getNext( tuple ) );
System.out.println( "key:"+ tuple.getKey().intValue() + " idx:" + idx );
assertTrue( tuple.getKey().intValue() == idx );
}
browser.close();
}
private void readWriteActions() throws IOException
{
int idx;
for ( idx = 0; idx < numReadThreads; idx++ )
browseSem.acquireUninterruptibly();
Integer key = new Integer( 1023 );
IntWrapper value = btree.find( key );
value.value = -1;
btree.insert( key, value, true );
key = new Integer(512);
value = btree.find( key );
value.value = -1;
btree.insert( key, value , true );
for ( idx = 1024; idx < 2048; idx++ )
{
btree.insert( new Integer( idx ), new IntWrapper( idx ), true );
}
key = new Integer(1);
value = btree.find( key );
value.value = -1;
btree.insert( key, value , true );
btree.insert( new Integer(1024), new IntWrapper( -1 ), true );
for ( idx = 10; idx < 20; idx++ )
{
btree.remove( new Integer( idx ) );
}
updateSem.release();
for ( idx = 0; idx < numReadThreads; idx++ )
browseSem.acquireUninterruptibly();
for ( idx = 0; idx < 10; idx++ )
btree.remove( new Integer( idx ) );
for ( idx = 20; idx < 1024; idx++ )
btree.remove( new Integer( idx ) );
}
public void run()
{
try
{
if ( readOnly )
this.readOnlyActions();
else
this.readWriteActions();
}
catch( IOException e )
{
}
catch( InterruptedException e )
{
}
}
} // end of class TestThread
}