Author: elecharny
Date: Thu Jun 6 06:04:58 2013
New Revision: 1490166
URL: http://svn.apache.org/r1490166
Log:
Updated the way the free pages are managed. Some tests are failing.
Added:
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/InMemoryBTreeTestOps.java
labs/mavibot/trunk/mavibot/src/test/resources/
labs/mavibot/trunk/mavibot/src/test/resources/log4j.properties
Modified:
labs/mavibot/trunk/mavibot/pom.xml
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractResult.java
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ModifyResult.java
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/RecordManager.java
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/SplitResult.java
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/StringSerializer.java
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/RecordManagerTest.java
Modified: labs/mavibot/trunk/mavibot/pom.xml
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/pom.xml?rev=1490166&r1=1490165&r2=1490166&view=diff
==============================================================================
--- labs/mavibot/trunk/mavibot/pom.xml (original)
+++ labs/mavibot/trunk/mavibot/pom.xml Thu Jun 6 06:04:58 2013
@@ -36,6 +36,10 @@
<properties>
<junit.version>4.10</junit.version>
<commons.collections.version>3.2.1</commons.collections.version>
+ <commons.io.version>2.4</commons.io.version>
+ <log4j.version>1.2.17</log4j.version>
+ <slf4j.api.version>1.7.5</slf4j.api.version>
+ <slf4j.log4j12.version>1.7.5</slf4j.log4j12.version>
</properties>
<dependencies>
@@ -55,10 +59,28 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.4</version>
- <scope>test</scope>
+ <version>${commons.io.version}</version>
+ </dependency>
+
+ <!-- Logging dependencies -->
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.api.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${slf4j.log4j12.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>${log4j.version}</version>
</dependency>
-
</dependencies>
<build>
Modified:
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractResult.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractResult.java?rev=1490166&r1=1490165&r2=1490166&view=diff
==============================================================================
---
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractResult.java
(original)
+++
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/AbstractResult.java
Thu Jun 6 06:04:58 2013
@@ -75,4 +75,32 @@ import java.util.List;
{
copiedPage.add( page );
}
+
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append( "\n copiedPage = <" );
+
+ boolean isFirst = true;
+
+ for ( Page<K, V> copiedPage : getCopiedPages() )
+ {
+ if ( isFirst )
+ {
+ isFirst = false;
+ }
+ else
+ {
+ sb.append( ", " );
+ }
+
+ sb.append( copiedPage.getOffset() );
+ }
+
+ sb.append( ">" );
+
+ return sb.toString();
+ }
}
Modified:
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ModifyResult.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ModifyResult.java?rev=1490166&r1=1490165&r2=1490166&view=diff
==============================================================================
---
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ModifyResult.java
(original)
+++
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/ModifyResult.java
Thu Jun 6 06:04:58 2013
@@ -97,6 +97,7 @@ import java.util.List;
sb.append( "ModifyResult, old value = " ).append( modifiedValue );
sb.append( ", modifiedPage = " ).append( modifiedPage );
+ sb.append( super.toString() );
return sb.toString();
}
Modified:
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/RecordManager.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/RecordManager.java?rev=1490166&r1=1490165&r2=1490166&view=diff
==============================================================================
---
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/RecordManager.java
(original)
+++
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/RecordManager.java
Thu Jun 6 06:04:58 2013
@@ -31,6 +31,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
import org.apache.mavibot.btree.exception.BTreeAlreadyManagedException;
import org.apache.mavibot.btree.exception.EndOfFileExceededException;
@@ -72,6 +73,14 @@ public class RecordManager
private long firstFreePage;
private long lastFreePage;
+ /** The list of available free pages */
+ List<PageIO> freePages = new ArrayList<PageIO>();
+
+ /** A counter to track the number of free pages */
+ public AtomicLong nbFreedPages = new AtomicLong( 0 );
+ public AtomicLong nbCreatedPages = new AtomicLong( 0 );
+ public AtomicLong nbReusedPages = new AtomicLong( 0 );
+
/** The offset of the end of the file */
private long endOfFileOffset;
@@ -130,18 +139,21 @@ public class RecordManager
/** A deserializer for Offsets */
private static final LongSerializer OFFSET_SERIALIZER = new
LongSerializer();
-
private static final String REVISION_BTREE_NAME = "_revisionBTree_";
private static final String COPIED_PAGE_BTREE_NAME = "_copiedPageBTree_";
-
+
private static final String OFFSET_BTREE_NAME = "_offsetBTree_";
-
+
private BTree<String, Long> offsetBTree;
-
+
/** A flag set to true if we want to keep old revisions */
private boolean keepRevisions;
-
+
+ /** A global buffer used for free pages */
+ private static ByteBuffer FREE_PAGE_BUFFER;
+
+
/**
* Create a Record manager which will either create the underlying file
* or load an existing one. If a folder is provided, then we will create
@@ -154,6 +166,7 @@ public class RecordManager
this( fileName, DEFAULT_PAGE_SIZE );
}
+
/**
* Create a Record manager which will either create the underlying file
* or load an existing one. If a folder is provider, then we will create
@@ -165,7 +178,9 @@ public class RecordManager
public RecordManager( String fileName, int pageSize )
{
managedBTrees = new LinkedHashMap<String, BTree<?, ?>>();
-
+
+ FREE_PAGE_BUFFER = ByteBuffer.allocateDirect( pageSize );
+
// Open the file or create it
File tmpFile = new File( fileName );
boolean isNewFile = false;
@@ -275,7 +290,8 @@ public class RecordManager
endOfFileOffset = fileChannel.size();
// Now, initialize the Copied Page BTree
- copiedPageBTree = new BTree<RevisionName, long[]>(
COPIED_PAGE_BTREE_NAME, new RevisionNameSerializer(), new LongArraySerializer()
);
+ copiedPageBTree = new BTree<RevisionName, long[]>(
COPIED_PAGE_BTREE_NAME, new RevisionNameSerializer(),
+ new LongArraySerializer() );
// and initialize the Revision BTree
revisionBTree = new BTree<RevisionName, Long>( REVISION_BTREE_NAME,
new RevisionNameSerializer(),
@@ -283,7 +299,7 @@ public class RecordManager
offsetBTree = new BTree<String, Long>( OFFSET_BTREE_NAME, new
StringSerializer(),
new LongSerializer() );
-
+
// Inject these BTrees into the RecordManager
try
{
@@ -355,29 +371,29 @@ public class RecordManager
nextBtreeOffset = revisionBTree.getNextBTreeOffset();
pageIos = readPages( nextBtreeOffset, Long.MAX_VALUE );
-
+
offsetBTree = BTreeFactory.createBTree();
offsetBTree.setBtreeOffset( nextBtreeOffset );
loadBTree( pageIos, offsetBTree );
-
+
// Then process the next ones
-// for ( int i = 2; i < nbBtree; i++ )
-// {
-// // Create the BTree
-// BTree<?, ?> btree = BTreeFactory.createBTree();
-// btree.setBtreeOffset( nextBtreeOffset );
-//
-// // Read the associated pages
-// pageIos = readPages( nextBtreeOffset, Long.MAX_VALUE );
-//
-// // Load the BTree
-// loadBTree( pageIos, btree );
-// nextBtreeOffset = btree.getNextBTreeOffset();
-//
-// // Store it into the managedBtrees map
-// managedBTrees.put( btree.getName(), btree );
-// }
+ // for ( int i = 2; i < nbBtree; i++ )
+ // {
+ // // Create the BTree
+ // BTree<?, ?> btree = BTreeFactory.createBTree();
+ // btree.setBtreeOffset( nextBtreeOffset );
+ //
+ // // Read the associated pages
+ // pageIos = readPages( nextBtreeOffset,
Long.MAX_VALUE );
+ //
+ // // Load the BTree
+ // loadBTree( pageIos, btree );
+ // nextBtreeOffset = btree.getNextBTreeOffset();
+ //
+ // // Store it into the managedBtrees map
+ // managedBTrees.put( btree.getName(), btree );
+ // }
// We are done ! Let's finish with the last initilization parts
endOfFileOffset = fileChannel.size();
@@ -587,22 +603,22 @@ public class RecordManager
for ( int i = 0; i < nbElems; i++ )
{
ElementHolder valueHolder;
-
- if( btree.isAllowDuplicates() )
+
+ if ( btree.isAllowDuplicates() )
{
String value = StringSerializer.INSTANCE.deserialize(
byteBuffer );
BTree dupValueContainer = getManagedTree( value );
- valueHolder = new DuplicateKeyMemoryHolder( btree,
dupValueContainer );
+ valueHolder = new DuplicateKeyMemoryHolder( btree,
dupValueContainer );
}
else
{
Object value = btree.getValueSerializer().deserialize(
byteBuffer );
-
+
valueHolder = new MemoryHolder( btree, value );
}
BTreeFactory.setValue( ( ( Leaf ) page ), i, valueHolder );
-
+
Object key = btree.getKeySerializer().deserialize( byteBuffer
);
BTreeFactory.setKey( page, i, key );
@@ -956,7 +972,7 @@ public class RecordManager
// The allowDuplicates flag
position = store( position, ( btree.isAllowDuplicates() ? 1 : 0 ),
pageIos );
-
+
// And flush the pages to disk now
flushPages( pageIos );
flushPages( rootPageIos );
@@ -978,7 +994,7 @@ public class RecordManager
lastAddedBTreeOffset = btreeOffset;
offsetBTree.insert( name, btreeOffset, 0 );
-
+
// Last, not least, update the number of managed BTrees in the header
updateRecordManagerHeader();
}
@@ -1077,7 +1093,7 @@ public class RecordManager
}
else
{
- if( btree.isAllowDuplicates() )
+ if ( btree.isAllowDuplicates() )
{
DuplicateKeyMemoryHolder value = (
DuplicateKeyMemoryHolder ) ( ( Leaf ) page ).getValue( pos );
String duplicateContainerName = ( ( BTree )
value.getValue( btree ) ).getName();
@@ -1088,7 +1104,7 @@ public class RecordManager
ElementHolder value = ( ( Leaf ) page ).getValue( pos
);
buffer = btree.getValueSerializer().serialize(
value.getValue( btree ) );
}
-
+
serializedData.add( buffer );
dataSize += buffer.length;
}
@@ -1681,6 +1697,8 @@ public class RecordManager
{
if ( firstFreePage == NO_PAGE )
{
+ nbCreatedPages.incrementAndGet();
+
// We don't have any free page. Reclaim some new page at the end
// of the file
PageIO newPage = new PageIO( endOfFileOffset );
@@ -1693,16 +1711,34 @@ public class RecordManager
newPage.setNextPage( NO_PAGE );
newPage.setSize( 0 );
+ LOG.debug( "Created a new page at offset {}", newPage.getOffset()
);
+
return newPage;
}
else
{
- // We have some existing free page. Fetch one from there.
+ nbReusedPages.incrementAndGet();
+
+ // We have some existing free page. Fetch it from disk
PageIO pageIo = fetchPage( firstFreePage );
- // Point to the next free page
+ // Update the firstFreePage pointer
firstFreePage = pageIo.getNextPage();
+ pageIo.setNextPage( NO_PAGE );
+ pageIo.setSize( 0 );
+
+ LOG.debug( "Reused page at offset {}", pageIo.getOffset() );
+
+ // If we don't have any more free page, update the last free page
pointer too
+ if ( firstFreePage == NO_PAGE )
+ {
+ lastFreePage = NO_PAGE;
+ }
+
+ // Update the header
+ updateRecordManagerHeader();
+
return pageIo;
}
}
@@ -1834,13 +1870,13 @@ public class RecordManager
{
// TODO : we must wait for the last write to finish
- for( BTree tree : managedBTrees.values() )
+ for ( BTree tree : managedBTrees.values() )
{
tree.close();
}
-
+
managedBTrees.clear();
-
+
// Write the data
fileChannel.force( true );
@@ -1875,26 +1911,29 @@ public class RecordManager
long firstFreePage = header.getLong();
long lastFreePage = header.getLong();
- System.out.println( "RecordManager" );
- System.out.println( "-------------" );
- System.out.println( " Header " );
- System.out.println( " '" + Strings.dumpBytes( header.array() ) +
"'" );
- System.out.println( " page size : " + pageSize );
- System.out.println( " nbTree : " + nbBTree );
- System.out.println( " firstFreePage : " + firstFreePage );
- System.out.println( " lastFreePage : " + lastFreePage );
+ if ( LOG.isDebugEnabled() )
+ {
+ LOG.debug( "RecordManager" );
+ LOG.debug( "-------------" );
+ LOG.debug( " Header " );
+ LOG.debug( " '{}'", Strings.dumpBytes( header.array() ) );
+ LOG.debug( " page size : {}", pageSize );
+ LOG.debug( " nbTree : {}", nbBTree );
+ LOG.debug( " firstFreePage : {}", firstFreePage );
+ LOG.debug( " lastFreePage : {}", lastFreePage );
+ }
long position = HEADER_SIZE;
// Dump the BTrees
for ( int i = 0; i < nbBTree; i++ )
{
- System.out.println( " Btree[" + i + "]" );
+ LOG.debug( " Btree[{}]", i );
PageIO[] pageIos = readPages( position, Long.MAX_VALUE );
for ( PageIO pageIo : pageIos )
{
- System.out.println( " " + pageIo );
+ LOG.debug( " {}", pageIo );
}
}
}
@@ -1919,11 +1958,11 @@ public class RecordManager
public Set<String> getManagedTrees()
{
Set<String> btrees = new HashSet<String>( managedBTrees.keySet() );
-
+
btrees.remove( COPIED_PAGE_BTREE_NAME );
btrees.remove( REVISION_BTREE_NAME );
btrees.remove( OFFSET_BTREE_NAME );
-
+
return btrees;
}
@@ -1937,12 +1976,12 @@ public class RecordManager
*/
/* No qualifier */void storeRootPage( BTree btree, Page rootPage ) throws
IOException
{
- if( !isKeepRevisions() )
+ if ( !isKeepRevisions() )
{
return;
}
-
- if( ( btree == copiedPageBTree ) || ( btree == revisionBTree ) || (
btree == offsetBTree ) )
+
+ if ( ( btree == copiedPageBTree ) || ( btree == revisionBTree ) || (
btree == offsetBTree ) )
{
return;
}
@@ -1989,131 +2028,136 @@ public class RecordManager
*/
public BTree getManagedTree( String name )
{
- if( name.startsWith( "1.3.6.1.4.1.18060.0.4.1.2.50" ) )
+ if ( name.startsWith( "1.3.6.1.4.1.18060.0.4.1.2.50" ) )
{
- System.out.println("");
+ LOG.debug( "" );
}
-
+
BTree tree = managedBTrees.get( name );
-
- if( tree == null )
+
+ if ( tree == null )
{
try
{
- if( !offsetBTree.hasKey( name ) )
+ if ( !offsetBTree.hasKey( name ) )
{
return null;
}
-
+
long treeOffset = offsetBTree.get( name );
-
+
// Create the BTree
BTree<?, ?> btree = BTreeFactory.createBTree();
btree.setBtreeOffset( treeOffset );
-
+
// Read the associated pages
PageIO[] pageIos = readPages( treeOffset, Long.MAX_VALUE );
// Load the BTree
loadBTree( pageIos, btree );
-
+
// Store it into the managedBtrees map
managedBTrees.put( btree.getName(), btree );
-
+
return btree;
}
- catch( Exception e )
+ catch ( Exception e )
{
throw new RuntimeException( e );
}
}
-
+
return tree;
}
-
-
+
+
/**
- *
- * TODO addFreePages.
- *
- * @param btree
- * @param freePages
+ * Move a list of pages to the free page list. A logical page is
associated with on
+ * or physical PageIO, which are on the disk. We have to move all those
PagIO instance
+ * to the free list, and do the same in memory (we try to keep a reference
to a set of
+ * free pages.
+ *
+ * @param btree The BTree which were owning the pages
+ * @param pages The pages to free
+ * @throws IOException
+ * @throws EndOfFileExceededException
*/
- public void addFreePages( BTree btree, List<Page> freePages )
+ /* Package protected */void addFreePages( BTree btree, List<Page> pages )
throws EndOfFileExceededException,
+ IOException
{
- if( ( btree == copiedPageBTree ) || ( btree == revisionBTree ) || (
btree == offsetBTree ) )
+ if ( ( btree == copiedPageBTree ) || ( btree == revisionBTree ) || (
btree == offsetBTree ) )
{
return;
}
-
- if( ( freePages == null ) || freePages.isEmpty() )
+
+ if ( ( pages == null ) || pages.isEmpty() )
{
return;
}
- // if the btree doesn't keep revisions just add them to the free page
list
- if( !keepRevisions )
+ if ( !keepRevisions )
{
- int start = 0;
- PageIO tailPage = null;
+ // if the btree doesn't keep revisions, we can safely move
+ // the pages to the free page list.
+ // NOTE : potential improvement : we can update the header only
when
+ // we have processed all the logical pages.
+ for ( Page page : pages )
+ {
+ // Retrieve all the PageIO associated with this logical page
+ long pageIoOffset = page.getOffset();
+ long firstPageIoOffset = page.getOffset();
+ long lastPageIoOffset = NO_PAGE;
- ByteBuffer data = ByteBuffer.allocateDirect( pageSize );
+ // Iterate on the pageIOs
+ while ( pageIoOffset != NO_PAGE )
+ {
+ // Keep a track of the current page
+ lastPageIoOffset = pageIoOffset;
- if( firstFreePage == NO_PAGE )
- {
- tailPage = new PageIO( freePages.get( start ).getOffset() );
+ // Retrieve the first physical page from disk
+ PageIO pageIo = fetchPage( pageIoOffset );
- firstFreePage = tailPage.getOffset();
- start = 1;
- }
- else if( lastFreePage != NO_PAGE )
- {
- tailPage = new PageIO( lastFreePage );
- }
-
- tailPage.setData( data );
- tailPage.setNextPage( NO_PAGE );
- tailPage.setSize( 0 );
-
- try
- {
- flushPages( tailPage );
-
- if( freePages.size() > start )
+ // Get the next offset
+ pageIoOffset = pageIo.getNextPage();
+ }
+
+ // Update the pointers
+ if ( firstFreePage == NO_PAGE )
{
- for( ; start < freePages.size(); start++ )
- {
- long nextOffset = freePages.get( start ).getOffset();
- tailPage.setNextPage( nextOffset );
-
- PageIO next = new PageIO( nextOffset );
- data = ByteBuffer.allocateDirect( pageSize );
- next.setData( data );
- next.setNextPage( NO_PAGE );
- next.setSize( 0 );
-
- flushPages( tailPage, next );
- tailPage = next;
- }
+ firstFreePage = firstPageIoOffset;
+ lastFreePage = lastPageIoOffset;
}
-
- lastFreePage = tailPage.getOffset();
- }
- catch( IOException e )
- {
- throw new RuntimeException( e );
+ else
+ {
+ // Fetch the last free pageIO
+ PageIO previousLastFreePage = fetchPage( lastFreePage );
+
+ // update its pointer to the next free pageIo
+ previousLastFreePage.setNextPage( firstPageIoOffset );
+
+ // And flush it to disk
+ flushPages( previousLastFreePage );
+
+ // We can update the lastFreePage offset
+ lastFreePage = lastPageIoOffset;
+ }
+
+ // Last, not least, flush the header
+ updateRecordManagerHeader();
}
}
else
{
- for( Page p : freePages )
+ LOG.debug( "We should not get there" );
+
+ for ( Page p : pages )
{
addFreePage( btree, p );
}
}
}
-
+
/**
*
* TODO addFreePage.
@@ -2127,8 +2171,8 @@ public class RecordManager
{
RevisionName revision = new RevisionName( freePage.getRevision(),
btree.getName() );
long[] offsetArray = null;
-
- if( copiedPageBTree.hasKey( revision ) )
+
+ if ( copiedPageBTree.hasKey( revision ) )
{
offsetArray = copiedPageBTree.get( revision );
long[] tmp = new long[offsetArray.length + 1];
@@ -2139,18 +2183,18 @@ public class RecordManager
{
offsetArray = new long[1];
}
-
+
offsetArray[offsetArray.length - 1] = freePage.getOffset();
-
+
copiedPageBTree.insert( revision, offsetArray, 0 );
}
- catch( Exception e )
+ catch ( Exception e )
{
throw new RuntimeException( e );
}
}
-
-
+
+
/**
* @return the keepRevisions
*/
@@ -2168,7 +2212,7 @@ public class RecordManager
this.keepRevisions = keepRevisions;
}
-
+
/**
* Creates a BTree and automatically adds it to the list of managed btrees
*
@@ -2181,20 +2225,68 @@ public class RecordManager
* @throws BTreeAlreadyManagedException
*/
@SuppressWarnings("all")
- public BTree addBTree( String name, ElementSerializer<?> keySerializer,
ElementSerializer<?> valueSerializer, boolean allowDuplicates ) throws
IOException, BTreeAlreadyManagedException
+ public BTree addBTree( String name, ElementSerializer<?> keySerializer,
ElementSerializer<?> valueSerializer,
+ boolean allowDuplicates ) throws IOException,
BTreeAlreadyManagedException
{
BTreeConfiguration config = new BTreeConfiguration();
-
+
config.setName( name );
config.setKeySerializer( keySerializer );
config.setValueSerializer( valueSerializer );
config.setAllowDuplicates( allowDuplicates );
config.setType( BTreeTypeEnum.MANAGED );
-
+
BTree btree = new BTree( config );
manage( btree );
-
+
return btree;
}
+
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.append( "RM free pages : [" );
+
+ if ( firstFreePage != NO_PAGE )
+ {
+ long current = firstFreePage;
+ boolean isFirst = true;
+
+ while ( current != NO_PAGE )
+ {
+ if ( isFirst )
+ {
+ isFirst = false;
+ }
+ else
+ {
+ sb.append( ", " );
+ }
+
+ PageIO pageIo;
+
+ try
+ {
+ pageIo = fetchPage( current );
+ sb.append( pageIo.getOffset() );
+ current = pageIo.getNextPage();
+ }
+ catch ( EndOfFileExceededException e )
+ {
+ e.printStackTrace();
+ }
+ catch ( IOException e )
+ {
+ e.printStackTrace();
+ }
+
+ }
+ }
+
+ sb.append( "]" );
+
+ return sb.toString();
+ }
}
Modified:
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/SplitResult.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/SplitResult.java?rev=1490166&r1=1490165&r2=1490166&view=diff
==============================================================================
---
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/SplitResult.java
(original)
+++
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/SplitResult.java
Thu Jun 6 06:04:58 2013
@@ -112,6 +112,7 @@ import java.util.List;
sb.append( "SplitResult, new pivot = " ).append( pivot );
sb.append( "\n leftPage = " ).append( leftPage );
sb.append( "\n rightPage = " ).append( rightPage );
+ sb.append( super.toString() );
return sb.toString();
}
Modified:
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/StringSerializer.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/StringSerializer.java?rev=1490166&r1=1490165&r2=1490166&view=diff
==============================================================================
---
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/StringSerializer.java
(original)
+++
labs/mavibot/trunk/mavibot/src/main/java/org/apache/mavibot/btree/serializer/StringSerializer.java
Thu Jun 6 06:04:58 2013
@@ -177,24 +177,39 @@ public class StringSerializer extends Ab
break;
default:
- try
- {
- byte[] strBytes = element.getBytes( "UTF-8" );
-
- bytes = new byte[strBytes.length + 4];
+ char[] chars = element.toCharArray();
+ byte[] tmpBytes = new byte[chars.length * 2];
- System.arraycopy( strBytes, 0, bytes, 4, strBytes.length );
+ int pos = 0;
+ len = 0;
- bytes[0] = ( byte ) ( strBytes.length >>> 24 );
- bytes[1] = ( byte ) ( strBytes.length >>> 16 );
- bytes[2] = ( byte ) ( strBytes.length >>> 8 );
- bytes[3] = ( byte ) ( strBytes.length );
- }
- catch ( UnsupportedEncodingException uee )
+ for ( char c : chars )
{
- // if this happens something is really strange
- throw new RuntimeException( uee );
+ if ( ( c & 0xFF80 ) == 0 )
+ {
+ tmpBytes[pos++] = ( byte ) c;
+ }
+ else if ( ( c & 0xF800 ) == 0 )
+ {
+ tmpBytes[pos++] = ( byte ) ( ( byte ) 0x00C0 | ( byte
) ( ( c & 0x07C0 ) >> 6 ) );
+ tmpBytes[pos++] = ( byte ) ( ( byte ) 0x80 | ( byte )
( c & 0x003F ) );
+ }
+ else
+ {
+ tmpBytes[pos++] = ( byte ) ( ( byte ) 0x80 | ( byte )
( c & 0x001F ) );
+ tmpBytes[pos++] = ( byte ) ( ( byte ) 0x80 | ( byte )
( c & 0x07C0 ) );
+ tmpBytes[pos++] = ( byte ) ( ( byte ) 0xE0 | ( byte )
( c & 0x7800 ) );
+ }
}
+
+ bytes = new byte[pos + 4];
+
+ bytes[0] = ( byte ) ( pos >>> 24 );
+ bytes[1] = ( byte ) ( pos >>> 16 );
+ bytes[2] = ( byte ) ( pos >>> 8 );
+ bytes[3] = ( byte ) ( pos );
+
+ System.arraycopy( tmpBytes, 0, bytes, 4, pos );
}
return bytes;
@@ -246,8 +261,39 @@ public class StringSerializer extends Ab
byte[] bytes = new byte[len];
buffer.get( bytes );
+ char[] chars = new char[len];
+ int clen = 0;
+
+ for ( int i = 0; i < len; i++ )
+ {
+ byte b = bytes[i];
+
+ if ( b >= 0 )
+ {
+ chars[clen++] = ( char ) b;
+ }
+ else
+ {
+ if ( ( b & 0xE0 ) == 0 )
+ {
+ // 3 bytes long char
+ i++;
+ byte b2 = bytes[i];
+ i++;
+ byte b3 = bytes[i];
+ chars[clen++] = ( char ) ( ( ( b & 0x000F ) << 12
) | ( ( b2 & 0x003F ) << 6 ) | ( ( b3 & 0x003F ) ) );
+ }
+ else
+ {
+ // 2 bytes long char
+ i++;
+ byte b2 = bytes[i];
+ chars[clen++] = ( char ) ( ( ( b & 0x001F ) << 6 )
| ( b2 & 0x003F ) );
+ }
+ }
+ }
- return Strings.utf8ToString( bytes );
+ return new String( chars, 0, clen );
}
}
Added:
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/InMemoryBTreeTestOps.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/InMemoryBTreeTestOps.java?rev=1490166&view=auto
==============================================================================
---
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/InMemoryBTreeTestOps.java
(added)
+++
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/InMemoryBTreeTestOps.java
Thu Jun 6 06:04:58 2013
@@ -0,0 +1,114 @@
+package org.apache.mavibot.btree;
+
+
+/*
+ * 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.
+ *
+ */
+import java.io.IOException;
+import java.util.Random;
+
+import org.apache.mavibot.btree.serializer.LongSerializer;
+import org.apache.mavibot.btree.serializer.StringSerializer;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+
+/**
+ * A class to test multi-threaded operations on the btree
+ *
+ * @author <a href="mailto:[email protected]">Mavibot labs Project</a>
+ */
+public class InMemoryBTreeTestOps
+{
+ /** The btree we use */
+ private static BTree<Long, String> btree;
+
+
+ /**
+ * Create the btree once
+ * @throws IOException If the creation failed
+ */
+ @BeforeClass
+ public static void setup() throws IOException
+ {
+ btree = new BTree<Long, String>( "test", new LongSerializer(), new
StringSerializer() );
+ }
+
+
+ /**
+ * Close the btree
+ */
+ @AfterClass
+ public static void shutdown() throws IOException
+ {
+ btree.close();
+ }
+
+
+ /**
+ * Create a btree with 500 000 elements in it
+ * @throws IOException If the creation failed
+ */
+ private void createTree() throws IOException
+ {
+ Random random = new Random( System.nanoTime() );
+
+ int nbElems = 500000;
+
+ // Create a BTree with 500 000 entries
+ btree.setPageSize( 32 );
+ for ( int i = 0; i < nbElems; i++ )
+ {
+ Long key = ( long ) random.nextLong();
+ String value = Long.toString( key );
+
+ try
+ {
+ btree.insert( key, value );
+
+ if ( i % 100000 == 0 )
+ {
+ System.out.println( "Written " + i + " elements" );
+ }
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace();
+ System.out.println( btree );
+ System.out.println( "Error while adding " + value );
+ return;
+ }
+ }
+
+ }
+
+
+ @Test
+ public void testCreateTree() throws InterruptedException, IOException
+ {
+
+ long t0 = System.currentTimeMillis();
+
+ // Start the writer
+ createTree();
+ long t1 = System.currentTimeMillis();
+ System.out.println( "Time to create a tree with 500 in memory:" + ( (
t1 - t0 ) ) + " Mseconds" );
+ }
+}
Modified:
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/RecordManagerTest.java
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/RecordManagerTest.java?rev=1490166&r1=1490165&r2=1490166&view=diff
==============================================================================
---
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/RecordManagerTest.java
(original)
+++
labs/mavibot/trunk/mavibot/src/test/java/org/apache/mavibot/btree/RecordManagerTest.java
Thu Jun 6 06:04:58 2013
@@ -39,7 +39,6 @@ import org.apache.mavibot.btree.exceptio
import org.apache.mavibot.btree.serializer.LongSerializer;
import org.apache.mavibot.btree.serializer.StringSerializer;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@@ -49,7 +48,7 @@ import org.junit.rules.TemporaryFolder;
* test the RecordManager
* @author <a href="mailto:[email protected]">Mavibot labs Project</a>
*/
-@Ignore("ignoring till RM functionality is standardized")
+//@Ignore("ignoring till RM functionality is standardized")
public class RecordManagerTest
{
private BTree<Long, String> btree = null;
@@ -66,15 +65,15 @@ public class RecordManagerTest
public void createBTree()
{
dataDir = tempFolder.newFolder( UUID.randomUUID().toString() );
-
+
openRecordManagerAndBtree();
try
{
// Create a new BTree
- btree = ( BTree<Long, String> ) recordManager1.addBTree( "test",
new LongSerializer(), new StringSerializer(), false );
+ btree = recordManager1.addBTree( "test", new LongSerializer(), new
StringSerializer(), false );
}
- catch( Exception e )
+ catch ( Exception e )
{
throw new RuntimeException( e );
}
@@ -85,21 +84,21 @@ public class RecordManagerTest
{
try
{
- if( recordManager1 != null )
+ if ( recordManager1 != null )
{
recordManager1.close();
}
-
+
// Now, try to reload the file back
recordManager1 = new RecordManager( dataDir.getAbsolutePath() );
-
+
// load the last created btree
- if( btree != null )
+ if ( btree != null )
{
btree = recordManager1.getManagedTree( btree.getName() );
}
}
- catch( Exception e )
+ catch ( Exception e )
{
throw new RuntimeException( e );
}
@@ -224,19 +223,51 @@ public class RecordManagerTest
* Test the creation of a RecordManager with a BTree containing 100 000
elements
*/
@Test
- @Ignore("This is a performance test")
+ //@Ignore("This is a performance test")
public void testRecordManagerWithBTreeLeafNode100K() throws IOException,
BTreeAlreadyManagedException,
KeyNotFoundException
{
+ // Don't keep any revision
+ recordManager1.setKeepRevisions( false );
+
+ String fileName = dataDir.getAbsolutePath() + "/mavibot.db";
+ File file = new File( fileName );
+ long fileSize = file.length();
+ System.out.println( "----- Size before = " + fileSize );
+
// Now, add some elements in the BTree
long t0 = System.currentTimeMillis();
- for ( long i = 0L; i < 100000L; i++ )
+ for ( Long i = 0L; i < 100000L; i++ )
{
- btree.insert( i, "V" + i );
+ String value = "V" + i;
+ btree.insert( i, value );
+
+ /*
+ if ( !recordManager1.check() )
+ {
+ System.out.println( "Failure while adding element " + i );
+ fail();
+ }
+ */
+
+ if ( i % 10000 == 0 )
+ {
+ fileSize = file.length();
+ System.out.println( "----- Size after insertion of " + i + " =
" + fileSize );
+ System.out.println( recordManager1 );
+ //System.out.println( btree );
+ }
}
long t1 = System.currentTimeMillis();
+ fileSize = file.length();
+ System.out.println( "Size after insertion of 100 000 elements : " +
fileSize );
System.out.println( "Time taken to write 100 000 elements : " + ( t1 -
t0 ) );
+ System.out.println( " Nb elem/s : " + ( ( 100000 * 1000 ) / ( t1 - t0
) ) );
+ System.out.println( "Nb created page " +
recordManager1.nbCreatedPages.get() );
+ System.out.println( "Nb allocated page " +
recordManager1.nbReusedPages.get() );
+ System.out.println( "Nb page we have freed " +
recordManager1.nbFreedPages.get() );
+ System.out.println( recordManager1 );
// Now, try to reload the file back
openRecordManagerAndBtree();
@@ -800,42 +831,43 @@ public class RecordManagerTest
int pageSize = 8;
int numKeys = 2;
String name = "duplicateTree";
-
- BTree<Long,String> dupsTree = new BTree( name, null, new
LongSerializer(), new StringSerializer(), pageSize, true );
-
+
+ BTree<Long, String> dupsTree = new BTree( name, null, new
LongSerializer(), new StringSerializer(), pageSize,
+ true );
+
recordManager1.manage( dupsTree );
-
- for( long i=0; i < numKeys; i++ )
+
+ for ( long i = 0; i < numKeys; i++ )
{
- for( int k=0; k < pageSize + 1; k++ )
+ for ( int k = 0; k < pageSize + 1; k++ )
{
dupsTree.insert( i, String.valueOf( k ) );
}
}
-
+
// Now, try to reload the file back
openRecordManagerAndBtree();
-
+
dupsTree = recordManager1.getManagedTree( name );
-
-// Cursor<Long, String> cursor1 = dupsTree.browse();
-// while( cursor1.hasNext() )
-// {
-// System.out.println( cursor1.next() );
-// }
-// cursor1.close();
-
- for( long i=0; i < numKeys; i++ )
+
+ // Cursor<Long, String> cursor1 = dupsTree.browse();
+ // while( cursor1.hasNext() )
+ // {
+ // System.out.println( cursor1.next() );
+ // }
+ // cursor1.close();
+
+ for ( long i = 0; i < numKeys; i++ )
{
BTree<String, String> values = dupsTree.getValues( i );
-// Cursor<String, String> cursor = values.browse();
-// while( cursor.hasNext() )
-// {
-// System.out.println( cursor.next() );
-// }
-// cursor.close();
-
- for( int k=0; k < pageSize + 1; k++ )
+ // Cursor<String, String> cursor = values.browse();
+ // while( cursor.hasNext() )
+ // {
+ // System.out.println( cursor.next() );
+ // }
+ // cursor.close();
+
+ for ( int k = 0; k < pageSize + 1; k++ )
{
assertTrue( values.hasKey( String.valueOf( k ) ) );
}
Added: labs/mavibot/trunk/mavibot/src/test/resources/log4j.properties
URL:
http://svn.apache.org/viewvc/labs/mavibot/trunk/mavibot/src/test/resources/log4j.properties?rev=1490166&view=auto
==============================================================================
--- labs/mavibot/trunk/mavibot/src/test/resources/log4j.properties (added)
+++ labs/mavibot/trunk/mavibot/src/test/resources/log4j.properties Thu Jun 6
06:04:58 2013
@@ -0,0 +1,32 @@
+#############################################################################
+# 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.
+#############################################################################
+log4j.rootCategory=OFF, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p
[%c-%X{Replica}] - %m%n
+#log4j.appender.stdout.layout.ConversionPattern=[%d{HH:mm:ss}] %p
[%c-%X{Replica}] %C{1}.%M@%L - %m%n
+
+log4j.appender.file=org.apache.log4j.RollingFileAppender
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=[%d{HH:mm:ss}] %p [%c] - %m%n
+log4j.appender.file.File=/tmp/server-integ.log
+log4j.appender.file.MaxFileSize=7168KB
+log4j.appender.file.MaxBackupIndex=100
+
+#log4j.logger.org=FATAL
+log4j.logger.org.apache.mavibot.btree=ERROR
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]