Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.eclipse.birt.core.btree.BTree Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2008,2010 Actuate Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Actuate Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.birt.core.btree;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.birt.core.i18n.CoreMessages;
import org.eclipse.birt.core.i18n.ResourceConstants;
/**
*
*
* @param
* @param
*/
public class BTree implements BTreeConstants
{
protected static Logger logger = Logger.getLogger( BTree.class.getName( ) );
protected NodeFile file;
protected boolean shareFile;
private int version;
private boolean allowDuplicate;
private boolean allowNullKey;
private int keySize;
private boolean hasValue;
private int valueSize;
private int headNodeId;
private int rootNodeId;
private int freeNodeId;
private int totalBlocks;
private int totalLevels;
private int totalKeys;
private int totalValues;
private int cacheSize;
protected boolean readOnly;
protected BTreeSerializer keySerializer;
protected BTreeSerializer valueSerializer;
protected Comparator comparator;
public BTree( ) throws IOException
{
this( new BTreeOption( ) );
}
public BTree( BTreeOption option ) throws IOException
{
if ( option.file != null )
{
this.shareFile = option.shareFile;
if ( option.file instanceof NodeFile )
{
this.file = (NodeFile) option.file;
}
else
{
this.file = new ReusableBTreeFile( option.file );
}
}
this.comparator = option.comparator;
this.keySerializer = option.keySerializer;
this.valueSerializer = option.valueSerializer;
this.readOnly = option.readOnly;
this.version = BTREE_VERSION_0;
this.rootNodeId = -1;
this.freeNodeId = -1;
this.totalLevels = 0;
this.totalKeys = 0;
this.totalValues = 0;
this.allowDuplicate = option.allowDuplicate;
this.allowNullKey = option.allowNullKey;
this.keySize = option.keySize;
this.hasValue = option.hasValue;
this.valueSize = option.valueSize;
this.headNodeId = option.headNodeId;
this.cacheSize = option.cacheSize;
if ( file != null )
{
if ( file.getTotalBlock( ) > headNodeId )
{
byte[] bytes = new byte[BLOCK_SIZE];
file.readBlock( headNodeId, bytes );
DataInput input = new DataInputStream(
new ByteArrayInputStream( bytes ) );
readTreeHead( input );
}
else
{
ByteArrayOutputStream buffer = new ByteArrayOutputStream(
BLOCK_SIZE );
DataOutput output = new DataOutputStream( buffer );
writeTreeHead( output );
file.writeBlock( headNodeId, buffer.toByteArray( ) );
}
totalBlocks = file.getTotalBlock( );
}
}
public void close( ) throws IOException
{
if ( file == null )
{
//has been closed
return;
}
try
{
if ( !readOnly )
{
// write the header
ByteArrayOutputStream buffer = new ByteArrayOutputStream(
BLOCK_SIZE );
DataOutput output = new DataOutputStream( buffer );
writeTreeHead( output );
file.writeBlock( headNodeId, buffer.toByteArray( ) );
// flush the nodes
for ( BTreeNode node : nodeCaches.values( ) )
{
if ( node.isDirty( ) )
{
writeNode( node );
}
}
}
if ( !shareFile )
{
file.close( );
}
}
finally
{
file = null;
}
}
LeafEntry getFirstEntry( ) throws IOException
{
int nodeId = rootNodeId;
while ( nodeId != -1 )
{
BTreeNode node = loadBTreeNode( nodeId );
try
{
if ( node.getNodeType( ) == NODE_LEAF )
{
return ( (LeafNode) node ).getFirstEntry( );
}
else
{
nodeId = ( (IndexNode) node ).getFirstChild( );
}
}
finally
{
node.unlock( );
}
}
return null;
}
LeafEntry getLastEntry( ) throws IOException
{
int nodeId = rootNodeId;
while ( nodeId != -1 )
{
BTreeNode node = loadBTreeNode( nodeId );
try
{
if ( node.getNodeType( ) == NODE_LEAF )
{
return ( (LeafNode) node ).getLastEntry( );
}
else
{
nodeId = ( (IndexNode) node ).getLastChild( );
}
}
finally
{
node.unlock( );
}
}
return null;
}
protected LeafEntry findEntry( K k ) throws IOException
{
if ( k == null && !allowNullKey )
{
throw new NullPointerException( "k can not be null" );
}
if ( rootNodeId != -1 )
{
BTreeValue key = createKey( k );
BTreeNode root = loadBTreeNode( rootNodeId );
try
{
int nodeType = root.getNodeType( );
if ( nodeType == NODE_INDEX )
{
return ( (IndexNode) root ).find( key );
}
else if ( nodeType == NODE_LEAF )
{
return ( (LeafNode) root ).find( key );
}
}
finally
{
root.unlock( );
}
}
return null;
}
void removeEntry( LeafEntry entry ) throws IOException
{
throw new UnsupportedOperationException( "setEntryValue" );
}
protected LeafEntry insertEntry( K k, V v ) throws IOException
{
BTreeValue key = createKey( k );
@SuppressWarnings("unchecked")
BTreeValue[] values = (BTreeValue[]) new BTreeValue[1];
if ( hasValue( ) )
{
values[0] = createValue( v );
}
return insertEntry( key, values );
}
LeafEntry insertEntry( K k, V[] vs ) throws IOException
{
if ( !allowNullKey && k == null )
{
throw new NullPointerException( "key can not be null" );
}
assert vs != null && vs.length > 0;
BTreeValue key = createKey( k );
if ( !hasValue( ) || vs == null || vs.length == 0 )
{
@SuppressWarnings("unchecked")
BTreeValue[] values = (BTreeValue[]) new BTreeValue[1];
return insertEntry( key, values );
}
@SuppressWarnings("unchecked")
BTreeValue[] values = (BTreeValue[]) new BTreeValue[vs.length];
for ( int i = 0; i < values.length; i++ )
{
values[i] = createValue( vs[i] );
}
return insertEntry( key, values );
}
private LeafEntry insertEntry( BTreeValue key,
BTreeValue[] values ) throws IOException
{
if ( rootNodeId == -1 )
{
LeafNode root = createLeafNode( );
try
{
root.setPrevNodeId( -1 );
root.setNextNodeId( -1 );
rootNodeId = root.getNodeId( );
totalLevels++;
return root.insert( key, values );
}
finally
{
root.unlock( );
}
}
else
{
BTreeNode root = loadBTreeNode( rootNodeId );
try
{
int nodeType = root.getNodeType( );
if ( nodeType == NODE_INDEX )
{
IndexNode indexNode = (IndexNode) root;
LeafEntry insertEntry = indexNode
.insert( key, values );
if ( indexNode.needSplit( ) )
{
IndexEntry splitEntry = indexNode.split( );
if ( splitEntry != null )
{
insertIndex( splitEntry.getKey( ),
splitEntry.getChildNodeId( ) );
}
}
return insertEntry;
}
if ( nodeType == NODE_LEAF )
{
LeafNode leafNode = (LeafNode) root;
LeafEntry insertEntry = leafNode.insert( key, values );
if ( leafNode.needSplit( ) )
{
IndexEntry splitEntry = leafNode.split( );
if ( splitEntry != null )
{
insertIndex( splitEntry.getKey( ),
splitEntry.getChildNodeId( ) );
}
}
return insertEntry;
}
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.UNEXPECTED_NODE_TYPE,
new Object[]{nodeType} ) );
}
finally
{
root.unlock( );
}
}
}
protected void insertIndex( BTreeValue key, int childNodeId )
throws IOException
{
IndexNode newRoot = createIndexNode( );
try
{
newRoot.setPrevNodeId( -1 );
newRoot.setNextNodeId( -1 );
newRoot.setFirstChild( rootNodeId );
newRoot.insertIndex( key, childNodeId );
rootNodeId = newRoot.getNodeId( );
totalLevels++;
}
finally
{
newRoot.unlock( );
}
}
public int getTotalKeys( )
{
return totalKeys;
}
public int getTotalValues( )
{
return totalValues;
}
public V getValue( K key ) throws IOException
{
if ( !hasValue( ) )
{
return null;
}
LeafEntry entry = findEntry( key );
if ( entry != null )
{
K entryKey = getKey( entry.getKey( ) );
if ( comparator.compare( key, entryKey ) == 0 )
{
BTreeValues values = entry.getValues( );
BTreeValues.Value value = values.getFirstValue( );
return getValue( value.getValue( ) );
}
}
return null;
}
public Collection getValues( K key ) throws IOException
{
if ( !hasValue( ) )
{
return null;
}
LeafEntry entry = findEntry( key );
if ( entry != null )
{
K entryKey = getKey( entry.getKey( ) );
if ( comparator.compare( key, entryKey ) == 0 )
{
BTreeValues values = entry.getValues( );
ArrayList list = new ArrayList( values.getValueCount( ) );
BTreeValues.Value value = values.getFirstValue( );
while ( value != null )
{
list.add( getValue( value.getValue( ) ) );
value = value.getNext( );
}
return list;
}
}
return null;
}
public boolean exist( K key ) throws IOException
{
LeafEntry entry = findEntry( key );
if ( entry != null )
{
K entryKey = getKey( entry.getKey( ) );
if ( comparator.compare( key, entryKey ) == 0 )
{
return true;
}
}
return false;
}
public void insert( K k, V v ) throws IOException
{
if ( readOnly )
{
throw new IOException(
CoreMessages.getString( ResourceConstants.READ_ONLY_TREE ) );
}
insertEntry( k, v );
}
public void insert( K k, V[] vs ) throws IOException
{
if ( readOnly )
{
throw new IOException(
CoreMessages.getString( ResourceConstants.READ_ONLY_TREE ) );
}
insertEntry( k, vs );
}
public void remove( K key ) throws IOException
{
LeafEntry entry = findEntry( key );
if ( entry != null )
{
K entryKey = getKey( entry.getKey( ) );
if ( comparator.compare( key, entryKey ) == 0 )
{
removeEntry( entry );
}
}
}
public BTreeCursor createCursor( )
{
return new BTreeCursor( this );
}
int compare( BTreeValue k1, BTreeValue k2 ) throws IOException
{
K key1 = getKey( k1 );
K key2 = getKey( k2 );
if ( key1 == key2 )
{
return 0;
}
if ( key1 == null )
{
return -1;
}
if ( key2 == null )
{
return 1;
}
return comparator.compare( key1, key2 );
}
// cache used by the btree
private LinkedHashMap> nodeCaches = new LinkedHashMap>(
8, 0.75f, true ) {
private static final long serialVersionUID = 1L;
protected boolean removeEldestEntry(
Map.Entry> arg )
{
if ( file == null )
{
// we never remove the cache out if there is no file.
return false;
}
if ( size( ) >= cacheSize )
{
BTreeNode node = arg.getValue( );
if ( node.isLocked( ) )
{
Iterator>> iter = this
.entrySet( ).iterator( );
while ( iter.hasNext( ) )
{
Map.Entry> entry = iter.next( );
BTreeNode value = entry.getValue( );
if ( !value.isLocked( ) )
{
// remove this node
if ( value.isDirty( ) )
{
try
{
writeNode( value );
}
catch ( IOException ex )
{
logger.log(
Level.WARNING,
"failed to write node "
+ value.getNodeId( )
+ " type "
+ value.getNodeType( ), ex );
return false;
}
}
remove( entry.getKey( ) );
break;
}
}
return false;
}
if ( node.isDirty( ) )
{
try
{
writeNode( node );
}
catch ( IOException ex )
{
logger.log( Level.WARNING,
"failed to write node " + node.getNodeId( )
+ " type " + node.getNodeType( ), ex );
return false;
}
}
return true;
}
return false;
}
};
private void writeNode( BTreeNode node ) throws IOException
{
NodeOutputStream out = new NodeOutputStream( file, node.getUsedBlocks( ) );
try
{
DataOutput output = new DataOutputStream( out );
output.writeInt( node.getNodeType( ) );
node.write( output );
node.setDirty( false );
}
finally
{
out.close( );
}
}
synchronized BTreeNode loadBTreeNode( int nodeId ) throws IOException
{
BTreeNode node = nodeCaches.get( nodeId );
if ( node != null )
{
node.lock( );
return node;
}
if ( file == null )
{
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.CANNOT_LOAD_NODE, new Object[]{nodeId} ) );
}
NodeInputStream in = new NodeInputStream( file, nodeId );
try
{
DataInput input = new DataInputStream( in );
int nodeType = input.readInt( );
switch ( nodeType )
{
case NODE_INDEX :
node = new IndexNode( this, nodeId );
break;
case NODE_LEAF :
node = new LeafNode( this, nodeId );
break;
case NODE_VALUE :
node = new ValueNode( this, nodeId );
break;
default :
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.UNEXPECTED_NODE_TYPE,
new Object[]{nodeType, nodeId} ) );
}
node.read( input );
node.setUsedBlocks( in.getUsedBlocks( ) );
node.setDirty( false );
node.lock( );
nodeCaches.put( Integer.valueOf( nodeId ), node );
return node;
}
finally
{
in.close( );
}
}
IndexNode loadIndexNode( int nodeId ) throws IOException
{
BTreeNode node = loadBTreeNode( nodeId );
if ( node instanceof IndexNode )
{
IndexNode indexNode = (IndexNode) node;
return indexNode;
}
node.unlock( );
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.UNEXPECTED_NODE_TYPE,
new Object[]{node.getNodeType( ), node.getNodeId( )} ) );
}
LeafNode loadLeafNode( int nodeId ) throws IOException
{
BTreeNode node = loadBTreeNode( nodeId );
if ( node instanceof LeafNode )
{
LeafNode leafNode = (LeafNode) node;
return leafNode;
}
node.unlock( );
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.UNEXPECTED_NODE_TYPE,
new Object[]{node.getNodeType( ), node.getNodeId( )} ) );
}
ValueNode loadValueNode( int nodeId ) throws IOException
{
BTreeNode node = loadBTreeNode( nodeId );
if ( node instanceof ValueNode )
{
return (ValueNode) node;
}
node.unlock( );
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.UNEXPECTED_NODE_TYPE,
new Object[]{node.getNodeType( ), node.getNodeId( )} ) );
}
protected int allocBlock( ) throws IOException
{
totalBlocks++;
if ( file != null )
{
return file.allocBlock( );
}
return totalBlocks;
}
protected void releaseBlock( int blockId ) throws IOException
{
if ( file != null )
{
file.freeBlock( blockId );
}
}
public LeafNode createLeafNode( ) throws IOException
{
int nodeId = allocBlock( );
LeafNode valueNode = new LeafNode( this, nodeId );
this.nodeCaches.put( nodeId, valueNode );
valueNode.lock( );
return valueNode;
}
public IndexNode createIndexNode( ) throws IOException
{
int nodeId = allocBlock( );
IndexNode indexNode = new IndexNode( this, nodeId );
this.nodeCaches.put( nodeId, indexNode );
indexNode.lock( );
return indexNode;
}
public ValueNode createValueNode( ) throws IOException
{
int nodeId = allocBlock( );
ValueNode valueNode = new ValueNode( this, nodeId );
this.nodeCaches.put( nodeId, valueNode );
valueNode.lock( );
return valueNode;
}
ExternalValueList createExternalValueList( BTreeValues values )
throws IOException
{
ExternalValueList list = new ExternalValueList( this );
BTreeValues.Value value = values.getFirstValue( );
while ( value != null )
{
list.append( value.getValue( ) );
value = value.getNext( );
}
return list;
}
private final BTreeValue NULL_KEY = new BTreeValue( );
BTreeValue createKey( K key ) throws IOException
{
if ( key == null )
{
assert allowNullKey == true;
return NULL_KEY;
}
byte[] keyBytes = keySerializer.getBytes( key );
int keySize = getKeySize( );
if ( keySize != 0 && keySize != keyBytes.length )
{
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.KEY_SIZE_ERROR, new Object[]{
keyBytes.length, keySize} ) );
}
return new BTreeValue( key, keyBytes );
}
protected K getKey( BTreeValue key ) throws IOException
{
if ( key == NULL_KEY )
{
return null;
}
K k = key.getValue( );
if ( k != null )
{
return k;
}
byte[] keyBytes = key.getBytes( );
if ( keyBytes != null )
{
try
{
k = keySerializer.getObject( keyBytes );
key.setValue( k );
}
catch ( ClassNotFoundException ce )
{
throw new IOException( ce.getMessage( ) );
}
}
return k;
}
int writeKey( DataOutput out, BTreeValue key ) throws IOException
{
int size = 0;
if ( allowNullKey )
{
if ( key == NULL_KEY )
{
out.writeBoolean( true );
return 1;
}
out.writeBoolean( false );
size = 1;
}
byte[] bytes = key.getBytes( );
int keySize = getKeySize( );
if ( keySize != 0 && keySize != bytes.length )
{
throw new IOException(
CoreMessages
.getString( ResourceConstants.MISMATCH_KEY_LENGTH ) );
}
if ( keySize == 0 )
{
out.writeInt( bytes.length );
out.write( bytes );
return size + 4 + bytes.length;
}
out.write( bytes );
return size + bytes.length;
}
BTreeValue readKey( DataInput in ) throws IOException
{
if ( allowNullKey )
{
boolean isNull = in.readBoolean( );
if ( isNull )
{
return NULL_KEY;
}
}
int keySize = getKeySize( );
if ( keySize == 0 )
{
keySize = in.readInt( );
}
byte[] keyBytes = new byte[keySize];
in.readFully( keyBytes );
return new BTreeValue( keyBytes );
}
protected V getValue( BTreeValue value ) throws IOException
{
V v = value.getValue( );
if ( v != null )
{
return v;
}
byte[] valueBytes = value.getBytes( );
if ( valueBytes != null )
{
try
{
v = valueSerializer.getObject( valueBytes );
value.setValue( v );
}
catch ( ClassNotFoundException ex )
{
throw new IOException( ex.getMessage( ) );
}
}
return v;
}
private BTreeValue createValue( V value ) throws IOException
{
byte[] valueBytes = valueSerializer.getBytes( value );
int valueSize = getValueSize( );
if ( valueSize != 0 && valueSize != valueBytes.length )
{
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.Value_SIZE_ERROR, new Object[]{
valueBytes.length, valueSize} ) );
}
return new BTreeValue( value, valueBytes );
}
int writeValue( DataOutput out, BTreeValue value ) throws IOException
{
byte[] bytes = value.getBytes( );
if ( valueSize != 0 && valueSize != bytes.length )
{
throw new IOException(
CoreMessages
.getString( ResourceConstants.MISMATCH_VALUE_LENGTH ) );
}
if ( valueSize == 0 )
{
out.writeInt( bytes.length );
out.write( bytes );
return bytes.length + 4;
}
out.write( bytes );
return valueSize;
}
BTreeValue readValue( DataInput in ) throws IOException
{
int size = getValueSize( );
if ( size == 0 )
{
size = in.readInt( );
}
byte[] bytes = new byte[size];
in.readFully( bytes );
return new BTreeValue( bytes );
}
// opened cursor and entries, nodes, once a node is locked, we should never
// remove it out from the key
void lockEntry( LeafEntry entry )
{
entry.getNode( ).lock( );
}
void unlockEntry( LeafEntry entry )
{
entry.getNode( ).unlock( );
}
int getKeySize( )
{
return keySize;
}
int getValueSize( )
{
return valueSize;
}
int getKeySize( BTreeValue key )
{
if ( allowNullKey )
{
if ( key == NULL_KEY )
{
return 1;
}
if ( keySize == 0 )
{
return 5 + key.getBytes( ).length;
}
return keySize + 1;
}
if ( keySize == 0 )
{
return 4 + key.getBytes( ).length;
}
return keySize;
}
int getValueSize( BTreeValue value )
{
if ( valueSize == 0 )
{
return 4 + value.getBytes( ).length;
}
return valueSize;
}
boolean hasValue( )
{
return hasValue;
}
boolean allowDuplicate( )
{
return allowDuplicate;
}
int getRootNodeId( )
{
return rootNodeId;
}
protected class ReusableBTreeFile implements NodeFile
{
BTreeFile file;
ReusableBTreeFile( BTreeFile file )
{
this.file = file;
freeNodeId = -1;
}
public int getTotalBlock( ) throws IOException
{
return file.getTotalBlock( );
}
public int allocBlock( ) throws IOException
{
if ( freeNodeId != -1 )
{
int blockId = freeNodeId;
byte[] bytes = new byte[4];
file.readBlock( freeNodeId, bytes );
freeNodeId = BTreeUtils.bytesToInteger( bytes );
return blockId;
}
return file.allocBlock( );
}
public void freeBlock( int blockId ) throws IOException
{
byte[] bytes = new byte[8];
BTreeUtils.integerToBytes( freeNodeId, bytes );
file.writeBlock( blockId, bytes );
freeNodeId = blockId;
}
public Object lock( ) throws IOException
{
return file.lock( );
}
public void readBlock( int blockId, byte[] bytes ) throws IOException
{
file.readBlock( blockId, bytes );
}
public void unlock( Object lock ) throws IOException
{
file.unlock( lock );
}
public void writeBlock( int blockId, byte[] bytes ) throws IOException
{
file.writeBlock( blockId, bytes );
}
public void close( ) throws IOException
{
file.close( );
}
}
protected void readTreeHead( DataInput in ) throws IOException
{
long tag = in.readLong( );
if ( tag != MAGIC_TAG )
{
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.INVALID_MAGIC_TAG,
new Object[]{Long.toHexString( tag )} ) );
}
version = in.readInt( );
if ( version != BTREE_VERSION_0 )
{
throw new IOException( CoreMessages.getFormattedString(
ResourceConstants.UNSUPPORTED_VERSION,
new Object[]{version} ) );
}
readV0( in );
}
private void readV0( DataInput in ) throws IOException
{
allowDuplicate = in.readBoolean( );
keySize = in.readInt( );
hasValue = in.readBoolean( );
valueSize = in.readInt( );
rootNodeId = in.readInt( );
freeNodeId = in.readInt( );
totalLevels = in.readInt( );
totalKeys = in.readInt( );
totalValues = in.readInt( );
allowNullKey = in.readBoolean( );
}
protected void writeTreeHead( DataOutput out ) throws IOException
{
out.writeLong( MAGIC_TAG );
out.writeInt( BTREE_VERSION_0 );
out.writeBoolean( allowDuplicate );
out.writeInt( keySize );
out.writeBoolean( hasValue );
out.writeInt( valueSize );
out.writeInt( rootNodeId );
out.writeInt( freeNodeId );
out.writeInt( totalLevels );
out.writeInt( totalKeys );
out.writeInt( totalValues );
out.writeBoolean( allowNullKey );
}
void increaseTotalKeys( )
{
totalKeys++;
}
void increaseTotalValues( int count )
{
totalValues += count;
}
public void dump( ) throws IOException
{
System.out.println( "BTREE:" + rootNodeId );
System.out.println( "keySize:" + keySize );
System.out.println( "hasValue:" + hasValue );
System.out.println( "allowDuplicate:" + allowDuplicate );
System.out.println( "valueSize:" + valueSize );
System.out.println( "rootNodeId" );
System.out.println( "freeNodeId" );
System.out.println( "totalLevles:" + totalLevels );
System.out.println( "totalKeys:" + totalKeys );
System.out.println( "totalValues:" + totalValues );
}
public void dumpAll( ) throws IOException
{
dump( );
if ( rootNodeId != -1 )
{
BTreeNode rootNode = loadBTreeNode( rootNodeId );
try
{
rootNode.dumpAll( );
}
finally
{
rootNode.unlock( );
}
}
}
}