You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2014/05/03 09:36:12 UTC
svn commit: r1592158 - in
/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree:
MavibotInspector.java RecordManager.java
Author: elecharny
Date: Sat May 3 07:36:11 2014
New Revision: 1592158
URL: http://svn.apache.org/r1592158
Log:
Moved the check methods out of the recordManager, otherwise this class would be overly long. They are now in MavibotInspector.
Modified:
directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/MavibotInspector.java
directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/MavibotInspector.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/MavibotInspector.java?rev=1592158&r1=1592157&r2=1592158&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/MavibotInspector.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/MavibotInspector.java Sat May 3 07:36:11 2014
@@ -25,10 +25,14 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Set;
+import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException;
+import org.apache.directory.mavibot.btree.exception.InvalidBTreeException;
import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.apache.directory.mavibot.btree.util.Strings;
/**
@@ -176,6 +180,382 @@ public class MavibotInspector
return true;
}
+
+
+ /**
+ * Check the whole file
+ */
+ /* no qualifier */ static void check( RecordManager recordManager )
+ {
+ try
+ {
+ // First check the RMheader
+ ByteBuffer recordManagerHeader = ByteBuffer.allocate( RecordManager.RECORD_MANAGER_HEADER_SIZE );
+ long fileSize = recordManager.fileChannel.size();
+
+ if ( fileSize < RecordManager.RECORD_MANAGER_HEADER_SIZE )
+ {
+ throw new InvalidBTreeException( "File size too small : " + fileSize );
+ }
+
+ // Read the RMHeader
+ recordManager.fileChannel.read( recordManagerHeader, 0L );
+ recordManagerHeader.flip();
+
+ // The page size. It must be a power of 2, and above 16.
+ int pageSize = recordManagerHeader.getInt();
+
+ if ( ( pageSize < 0 ) || ( pageSize < 32 ) || ( ( pageSize & ( ~pageSize + 1 ) ) != pageSize ) )
+ {
+ throw new InvalidBTreeException( "Wrong page size : " + pageSize );
+ }
+
+ // Compute the number of pages in this file
+ long nbPages = ( fileSize - RecordManager.RECORD_MANAGER_HEADER_SIZE ) / pageSize;
+
+ // The number of trees. It must be at least 2 and > 0
+ int nbBtrees = recordManagerHeader.getInt();
+
+ if ( nbBtrees < 0 )
+ {
+ throw new InvalidBTreeException( "Wrong nb trees : " + nbBtrees );
+ }
+
+ // The first free page offset. It must be either -1 or below file size
+ // and its value must be a modulo of pageSize
+ long firstFreePage = recordManagerHeader.getLong();
+
+ if ( firstFreePage > fileSize )
+ {
+ throw new InvalidBTreeException( "First free page pointing after the end of the file : "
+ + firstFreePage );
+ }
+
+ if ( ( firstFreePage != RecordManager.NO_PAGE ) && ( ( ( firstFreePage - RecordManager.RECORD_MANAGER_HEADER_SIZE ) % pageSize ) != 0 ) )
+ {
+ throw new InvalidBTreeException( "First free page not pointing to a correct offset : " + firstFreePage );
+ }
+
+ int nbPageBits = ( int ) ( nbPages / RecordManager.INT_SIZE );
+
+ // Create an array of pages to be checked
+ // We use one bit per page. It's 0 when the page
+ // hasn't been checked, 1 otherwise.
+ int[] checkedPages = new int[nbPageBits + 1];
+
+ // Then the free files
+ checkFreePages( recordManager, checkedPages, pageSize, firstFreePage );
+
+ // The B-trees
+ checkBtrees( recordManager, checkedPages, pageSize, nbBtrees );
+ }
+ catch ( Exception e )
+ {
+ // We catch the exception and rethrow it immediately to be able to
+ // put a breakpoint here
+ e.printStackTrace();
+ throw new InvalidBTreeException( "Error : " + e.getMessage() );
+ }
+ }
+
+
+ /**
+ * Check each B-tree we manage
+ * @throws IOException
+ * @throws EndOfFileExceededException
+ * @throws ClassNotFoundException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ private static void checkBtrees( RecordManager recordManager, int[] checkedPages, int pageSize, int nbBtrees ) throws EndOfFileExceededException,
+ IOException, InstantiationException, IllegalAccessException, ClassNotFoundException
+ {
+ // Iterate on each B-tree until we have exhausted all of them. The number
+ // of btrees is just used to check that we have the correct number
+ // of stored B-trees, as they are all linked.
+ long position = RecordManager.RECORD_MANAGER_HEADER_SIZE;
+
+ for ( int i = 0; i < nbBtrees; i++ )
+ {
+ // Load the pageIOs containing the B-tree
+ PageIO[] pageIos = recordManager.readPageIOs( position, Long.MAX_VALUE );
+
+ // Check that they are correctly linked and not already used
+ int pageNb = 0;
+
+ for ( PageIO currentPageIo : pageIos )
+ {
+ //
+ long nextPageOffset = currentPageIo.getNextPage();
+
+ if ( pageNb == pageIos.length - 1 )
+ {
+ if ( nextPageOffset != RecordManager.NO_PAGE )
+ {
+ throw new InvalidBTreeException( "The pointer to the next page is not valid, expected NO_PAGE" );
+ }
+ }
+ else
+ {
+ if ( nextPageOffset == RecordManager.NO_PAGE )
+ {
+ throw new InvalidBTreeException( "The pointer to the next page is not valid, NO_PAGE" );
+ }
+ }
+
+ if ( ( nextPageOffset != RecordManager.NO_PAGE ) && ( ( nextPageOffset - RecordManager.RECORD_MANAGER_HEADER_SIZE ) % pageSize != 0 ) )
+ {
+ throw new InvalidBTreeException( "The pointer to the next page is not valid" );
+ }
+
+ // Update the array of processed pages
+ setCheckedPage( recordManager, checkedPages, currentPageIo.getOffset(), pageSize );
+ }
+
+ // Now check the B-tree
+ long nextBtree = checkBtree( recordManager, checkedPages, pageIos, pageSize, i == nbBtrees - 1 );
+
+ if ( ( nextBtree == RecordManager.NO_PAGE ) && ( i < nbBtrees - 1 ) )
+ {
+ throw new InvalidBTreeException( "The pointer to the next B-tree is incorrect" );
+ }
+
+ position = nextBtree;
+ }
+ }
+
+
+ /**
+ * Check a B-tree
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ * @throws ClassNotFoundException
+ */
+ private static long checkBtree( RecordManager recordManager, int[] checkedPages, PageIO[] pageIos, int pageSize, boolean isLast )
+ throws EndOfFileExceededException, IOException, InstantiationException, IllegalAccessException,
+ ClassNotFoundException
+ {
+ long dataPos = 0L;
+
+ // The B-tree current revision
+ long revision = recordManager.readLong( pageIos, dataPos );
+ dataPos += RecordManager.LONG_SIZE;
+
+ // The nb elems in the tree
+ long nbElems = recordManager.readLong( pageIos, dataPos );
+ dataPos += RecordManager.LONG_SIZE;
+
+ // The B-tree rootPage offset
+ long rootPageOffset = recordManager.readLong( pageIos, dataPos );
+
+ if ( ( rootPageOffset < 0 ) || ( rootPageOffset > recordManager.fileChannel.size() ) )
+ {
+ throw new InvalidBTreeException( "The rootpage is incorrect : " + rootPageOffset );
+ }
+
+ dataPos += RecordManager.LONG_SIZE;
+
+ // The next B-tree offset
+ long nextBtreeOffset = recordManager.readLong( pageIos, dataPos );
+
+ if ( ( ( rootPageOffset < 0 ) && ( !isLast ) ) || ( nextBtreeOffset > recordManager.fileChannel.size() ) )
+ {
+ throw new InvalidBTreeException( "The rootpage is incorrect : " + rootPageOffset );
+ }
+
+ dataPos += RecordManager.LONG_SIZE;
+
+ // The B-tree page size
+ int btreePageSize = recordManager.readInt( pageIos, dataPos );
+
+ if ( ( btreePageSize < 2 ) || ( ( btreePageSize & ( ~btreePageSize + 1 ) ) != btreePageSize ) )
+ {
+ throw new InvalidBTreeException( "The B-tree page size is not a power of 2 : " + btreePageSize );
+ }
+
+ dataPos += RecordManager.INT_SIZE;
+
+ // The tree name
+ ByteBuffer btreeNameBytes = recordManager.readBytes( pageIos, dataPos );
+ dataPos += RecordManager.INT_SIZE;
+
+ dataPos += btreeNameBytes.limit();
+ String btreeName = Strings.utf8ToString( btreeNameBytes );
+
+ // The keySerializer FQCN
+ ByteBuffer keySerializerBytes = recordManager.readBytes( pageIos, dataPos );
+
+ String keySerializerFqcn = null;
+ dataPos += RecordManager.INT_SIZE;
+
+ if ( keySerializerBytes != null )
+ {
+ dataPos += keySerializerBytes.limit();
+ keySerializerFqcn = Strings.utf8ToString( keySerializerBytes );
+ }
+ else
+ {
+ keySerializerFqcn = "";
+ }
+
+ // The valueSerialier FQCN
+ ByteBuffer valueSerializerBytes = recordManager.readBytes( pageIos, dataPos );
+
+ String valueSerializerFqcn = null;
+ dataPos += RecordManager.INT_SIZE;
+
+ if ( valueSerializerBytes != null )
+ {
+ dataPos += valueSerializerBytes.limit();
+ valueSerializerFqcn = Strings.utf8ToString( valueSerializerBytes );
+ }
+ else
+ {
+ valueSerializerFqcn = "";
+ }
+
+ // The B-tree allowDuplicates flag
+ int allowDuplicates = recordManager.readInt( pageIos, dataPos );
+ dataPos += RecordManager.INT_SIZE;
+
+ // Now, check the rootPage, which can be a Leaf or a Node, depending
+ // on the number of elements in the tree : if it's above the pageSize,
+ // it's a Node, otherwise it's a Leaf
+ Class<?> valueSerializer = Class.forName( valueSerializerFqcn );
+ Class<?> keySerializer = Class.forName( keySerializerFqcn );
+
+ /*
+ checkRoot( checkedPages, rootPageOffset, pageSize, nbElems,
+ ( ElementSerializer<?> ) keySerializer.newInstance(),
+ ( ElementSerializer<?> ) valueSerializer.newInstance(), allowDuplicates != 0 );
+ */
+
+ return nextBtreeOffset;
+ }
+
+
+ /**
+ * Check the free pages
+ *
+ * @param checkedPages
+ * @throws IOException
+ */
+ private static void checkFreePages( RecordManager recordManager, int[] checkedPages, int pageSize, long firstFreePage )
+ throws IOException
+ {
+ if ( firstFreePage == RecordManager.NO_PAGE )
+ {
+ return;
+ }
+
+ // Now, read all the free pages
+ long currentOffset = firstFreePage;
+ long fileSize = recordManager.fileChannel.size();
+
+ while ( currentOffset != RecordManager.NO_PAGE )
+ {
+ if ( currentOffset > fileSize )
+ {
+ System.out.println( "Wrong free page offset, above file size : " + currentOffset );
+ return;
+ }
+
+ try
+ {
+ PageIO pageIo = recordManager.fetchPage( currentOffset );
+
+ if ( currentOffset != pageIo.getOffset() )
+ {
+ System.out.println( "PageIO offset is incorrect : " + currentOffset + "-"
+ + pageIo.getOffset() );
+ return;
+ }
+
+ setCheckedPage( recordManager, checkedPages, currentOffset, pageSize );
+
+ long newOffset = pageIo.getNextPage();
+ currentOffset = newOffset;
+ }
+ catch ( IOException ioe )
+ {
+ throw new InvalidBTreeException( "Cannot fetch page at : " + currentOffset );
+ }
+ }
+
+ dumpCheckedPages( recordManager, checkedPages );
+ }
+
+
+ private static void setCheckedPage( RecordManager recordManager, int[] checkedPages, long offset, int pageSize )
+ {
+ int pageNumber = ( int ) offset / pageSize;
+ int nbBitsPage = ( RecordManager.INT_SIZE << 3 );
+ long pageMask = checkedPages[ pageNumber / nbBitsPage ];
+ long mask = 1L << pageNumber % nbBitsPage;
+
+ if ( ( pageMask & mask ) != 0 )
+ {
+ throw new InvalidBTreeException( "The page " + offset + " has already been referenced" );
+ }
+
+ pageMask |= mask;
+
+ checkedPages[ pageNumber / nbBitsPage ] |= pageMask;
+ }
+
+
+ /**
+ * Output the pages that has been seen ('1') and those which has not been seen ('0'). The '.' represent non-pages
+ * at the end of the file.
+ */
+ private static void dumpCheckedPages( RecordManager recordManager, int[] checkedPages ) throws IOException
+ {
+ StringBuilder sb = new StringBuilder();
+ int i = -1;
+ int nbPagesChecked = 0;
+ long fileSize = recordManager.fileChannel.size();
+ long nbPages = ( fileSize - RecordManager.RECORD_MANAGER_HEADER_SIZE ) / recordManager.pageSize;
+
+
+ for ( int checkedPage : checkedPages )
+ {
+ if ( i == -1 )
+ {
+ i = 0;
+ }
+ else
+ {
+ i++;
+ sb.append( " " );
+ }
+
+ sb.append( "[" ).append( i ).append( "] " );
+
+
+ for ( int j = 0; j < 32; j++ )
+ {
+ if ( nbPagesChecked >= nbPages )
+ {
+ sb.append( "." );
+ }
+ else
+ {
+ if ( ( checkedPage & ( 1 << j ) ) == 0 )
+ {
+ sb.append( "0" );
+ }
+ else
+ {
+ sb.append( "1" );
+ }
+ }
+
+ nbPagesChecked++;
+ }
+ }
+
+ System.out.println( sb.toString() );
+ }
public void start() throws Exception
@@ -221,7 +601,14 @@ public class MavibotInspector
break;
case '4':
- rm.checkFreePages();
+ int pageSize = rm.getPageSize();
+ long fileSize = rm.fileChannel.size();
+ long nbPages = fileSize / pageSize;
+ int nbPageBits = ( int ) ( nbPages / RecordManager.INT_SIZE );
+ int[] checkedPages = new int[nbPageBits + 1];
+ long firstFreePage = rm.firstFreePage;
+
+ checkFreePages( rm, checkedPages, pageSize, firstFreePage );
break;
case '5':
@@ -229,7 +616,7 @@ public class MavibotInspector
break;
case '6':
- rm.check();
+ check( rm );
break;
case '7':
Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java?rev=1592158&r1=1592157&r2=1592158&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java Sat May 3 07:36:11 2014
@@ -80,13 +80,13 @@ public class RecordManager extends Abstr
private File file;
/** The channel used to read and write data */
- private FileChannel fileChannel;
+ /* no qualifier */ FileChannel fileChannel;
/** The number of managed B-trees */
private int nbBtree;
/** The first and last free page */
- private long firstFreePage;
+ /* no qualifier */ long firstFreePage;
/** The list of available free pages */
List<PageIO> freePages = new ArrayList<PageIO>();
@@ -119,8 +119,8 @@ public class RecordManager extends Abstr
/** Some constants */
private static final int BYTE_SIZE = 1;
- private static final int INT_SIZE = 4;
- private static final int LONG_SIZE = 8;
+ /* no qualifier */ static final int INT_SIZE = 4;
+ /* no qualifier */ static final int LONG_SIZE = 8;
/** The default page size */
public static final int DEFAULT_PAGE_SIZE = 512;
@@ -129,7 +129,7 @@ public class RecordManager extends Abstr
private static final int MIN_PAGE_SIZE = 64;
/** The RecordManager header size */
- private static int RECORD_MANAGER_HEADER_SIZE = DEFAULT_PAGE_SIZE;
+ /* no qualifier */ static int RECORD_MANAGER_HEADER_SIZE = DEFAULT_PAGE_SIZE;
/** A global buffer used to store the RecordManager header */
private static ByteBuffer RECORD_MANAGER_HEADER_BUFFER;
@@ -142,7 +142,7 @@ public class RecordManager extends Abstr
{ ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xFF, ( byte ) 0xF8 };
/** The RecordManager underlying page size. */
- private int pageSize = DEFAULT_PAGE_SIZE;
+ /* no qualifier */ int pageSize = DEFAULT_PAGE_SIZE;
/** The set of managed B-trees */
private Map<String, BTree<Object, Object>> managedBtrees;
@@ -1019,7 +1019,7 @@ public class RecordManager extends Abstr
* @param position The position in the data stored in those pages
* @return The byte[] we have read
*/
- private ByteBuffer readBytes( PageIO[] pageIos, long position )
+ /* no qualifier */ ByteBuffer readBytes( PageIO[] pageIos, long position )
{
// Read the byte[] length first
int length = readInt( pageIos, position );
@@ -1087,7 +1087,7 @@ public class RecordManager extends Abstr
* @param position The position in the data stored in those pages
* @return The int we have read
*/
- private int readInt( PageIO[] pageIos, long position )
+ /* no qualifier */ int readInt( PageIO[] pageIos, long position )
{
// Compute the page in which we will store the data given the
// current position
@@ -1177,7 +1177,7 @@ public class RecordManager extends Abstr
* @param position The position in the data stored in those pages
* @return The long we have read
*/
- private long readLong( PageIO[] pageIos, long position )
+ /* no qualifier */ long readLong( PageIO[] pageIos, long position )
{
// Compute the page in which we will store the data given the
// current position
@@ -1353,7 +1353,7 @@ public class RecordManager extends Abstr
if ( LOG_CHECK.isDebugEnabled() )
{
- check();
+ MavibotInspector.check( this );
}
}
@@ -2218,7 +2218,7 @@ public class RecordManager extends Abstr
if ( LOG_CHECK.isDebugEnabled() )
{
- check();
+ MavibotInspector.check( this );
}
return newBtreeHeaderOffset;
@@ -2647,7 +2647,7 @@ public class RecordManager extends Abstr
if ( LOG_CHECK.isDebugEnabled() )
{
- check();
+ MavibotInspector.check( this );
}
return pageHolder;
@@ -2845,7 +2845,7 @@ public class RecordManager extends Abstr
* @param offset The position in the file
* @return The found page
*/
- private PageIO fetchPage( long offset ) throws IOException, EndOfFileExceededException
+ /* no qualifier */ PageIO fetchPage( long offset ) throws IOException, EndOfFileExceededException
{
checkOffset( offset );
@@ -3279,7 +3279,7 @@ public class RecordManager extends Abstr
if ( LOG_CHECK.isDebugEnabled() )
{
- check();
+ MavibotInspector.check( this );
}
}
@@ -3511,7 +3511,7 @@ public class RecordManager extends Abstr
if ( LOG_CHECK.isDebugEnabled() )
{
- check();
+ MavibotInspector.check( this );
}
return btree;
@@ -3529,131 +3529,8 @@ public class RecordManager extends Abstr
closedTransactionsQueue.add( revisionName );
}
- private void setCheckedPage( int[] checkedPages, long offset, int pageSize )
- {
- int pageNumber = ( int ) offset / pageSize;
- int nbBitsPage = ( INT_SIZE << 3 );
- long pageMask = checkedPages[ pageNumber / nbBitsPage ];
- long mask = 1L << pageNumber % nbBitsPage;
-
- if ( ( pageMask & mask ) != 0 )
- {
- throw new InvalidBTreeException( "The page " + offset + " has already been referenced" );
- }
-
- pageMask |= mask;
-
- checkedPages[ pageNumber / nbBitsPage ] |= pageMask;
- }
-
-
- /**
- * Check the free pages
- *
- * @param checkedPages
- * @throws IOException
- */
- private void checkFreePages( int[] checkedPages, int pageSize, long firstFreePage )
- throws IOException
- {
- if ( firstFreePage == NO_PAGE )
- {
- return;
- }
-
- // Now, read all the free pages
- long currentOffset = firstFreePage;
- long fileSize = fileChannel.size();
-
- while ( currentOffset != NO_PAGE )
- {
- if ( currentOffset > fileSize )
- {
- System.out.println( "Wrong free page offset, above file size : " + currentOffset );
- return;
- }
-
- try
- {
- PageIO pageIo = fetchPage( currentOffset );
-
- if ( currentOffset != pageIo.getOffset() )
- {
- System.out.println( "PageIO offset is incorrect : " + currentOffset + "-"
- + pageIo.getOffset() );
- return;
- }
-
- setCheckedPage( checkedPages, currentOffset, pageSize );
-
- long newOffset = pageIo.getNextPage();
- currentOffset = newOffset;
- }
- catch ( IOException ioe )
- {
- throw new InvalidBTreeException( "Cannot fetch page at : " + currentOffset );
- }
- }
-
- dumpCheckedPages( checkedPages );
- }
-
/**
- * Output the pages that has been seen ('1') and those which has not been seen ('0'). The '.' represent non-pages
- * at the end of the file.
- */
- private void dumpCheckedPages( int[] checkedPages ) throws IOException
- {
- StringBuilder sb = new StringBuilder();
- int i = -1;
- int nbPagesChecked = 0;
- long fileSize = fileChannel.size();
- long nbPages = ( fileSize - RECORD_MANAGER_HEADER_SIZE ) / pageSize;
-
-
- for ( int checkedPage : checkedPages )
- {
- if ( i == -1 )
- {
- i = 0;
- }
- else
- {
- i++;
- sb.append( " " );
- }
-
- sb.append( "[" ).append( i ).append( "] " );
-
-
- for ( int j = 0; j < 32; j++ )
- {
- if ( nbPagesChecked >= nbPages )
- {
- sb.append( "." );
- }
- else
- {
- if ( ( checkedPage & ( 1 << j ) ) == 0 )
- {
- sb.append( "0" );
- }
- else
- {
- sb.append( "1" );
- }
- }
-
- nbPagesChecked++;
- }
- }
-
- System.out.println( sb.toString() );
- }
-
-
- /**
* Check the root page for a given B-tree
* @throws IOException
* @throws EndOfFileExceededException
@@ -3764,259 +3641,7 @@ public class RecordManager extends Abstr
}
}
-
- /**
- * Check a B-tree
- * @throws IllegalAccessException
- * @throws InstantiationException
- * @throws ClassNotFoundException
- */
- private long checkBtree( int[] checkedPages, PageIO[] pageIos, int pageSize, boolean isLast )
- throws EndOfFileExceededException, IOException, InstantiationException, IllegalAccessException,
- ClassNotFoundException
- {
- long dataPos = 0L;
-
- // The B-tree current revision
- long revision = readLong( pageIos, dataPos );
- dataPos += LONG_SIZE;
-
- // The nb elems in the tree
- long nbElems = readLong( pageIos, dataPos );
- dataPos += LONG_SIZE;
-
- // The B-tree rootPage offset
- long rootPageOffset = readLong( pageIos, dataPos );
-
- if ( ( rootPageOffset < 0 ) || ( rootPageOffset > fileChannel.size() ) )
- {
- throw new InvalidBTreeException( "The rootpage is incorrect : " + rootPageOffset );
- }
-
- dataPos += LONG_SIZE;
-
- // The next B-tree offset
- long nextBtreeOffset = readLong( pageIos, dataPos );
-
- if ( ( ( rootPageOffset < 0 ) && ( !isLast ) ) || ( nextBtreeOffset > fileChannel.size() ) )
- {
- throw new InvalidBTreeException( "The rootpage is incorrect : " + rootPageOffset );
- }
-
- dataPos += LONG_SIZE;
-
- // The B-tree page size
- int btreePageSize = readInt( pageIos, dataPos );
-
- if ( ( btreePageSize < 2 ) || ( ( btreePageSize & ( ~btreePageSize + 1 ) ) != btreePageSize ) )
- {
- throw new InvalidBTreeException( "The B-tree page size is not a power of 2 : " + btreePageSize );
- }
-
- dataPos += INT_SIZE;
-
- // The tree name
- ByteBuffer btreeNameBytes = readBytes( pageIos, dataPos );
- dataPos += INT_SIZE;
-
- dataPos += btreeNameBytes.limit();
- String btreeName = Strings.utf8ToString( btreeNameBytes );
-
- // The keySerializer FQCN
- ByteBuffer keySerializerBytes = readBytes( pageIos, dataPos );
-
- String keySerializerFqcn = null;
- dataPos += INT_SIZE;
-
- if ( keySerializerBytes != null )
- {
- dataPos += keySerializerBytes.limit();
- keySerializerFqcn = Strings.utf8ToString( keySerializerBytes );
- }
- else
- {
- keySerializerFqcn = "";
- }
-
- // The valueSerialier FQCN
- ByteBuffer valueSerializerBytes = readBytes( pageIos, dataPos );
-
- String valueSerializerFqcn = null;
- dataPos += INT_SIZE;
-
- if ( valueSerializerBytes != null )
- {
- dataPos += valueSerializerBytes.limit();
- valueSerializerFqcn = Strings.utf8ToString( valueSerializerBytes );
- }
- else
- {
- valueSerializerFqcn = "";
- }
-
- // The B-tree allowDuplicates flag
- int allowDuplicates = readInt( pageIos, dataPos );
- dataPos += INT_SIZE;
-
- // Now, check the rootPage, which can be a Leaf or a Node, depending
- // on the number of elements in the tree : if it's above the pageSize,
- // it's a Node, otherwise it's a Leaf
- Class<?> valueSerializer = Class.forName( valueSerializerFqcn );
- Class<?> keySerializer = Class.forName( keySerializerFqcn );
-
- /*
- checkRoot( checkedPages, rootPageOffset, pageSize, nbElems,
- ( ElementSerializer<?> ) keySerializer.newInstance(),
- ( ElementSerializer<?> ) valueSerializer.newInstance(), allowDuplicates != 0 );
- */
-
- return nextBtreeOffset;
- }
-
-
- /**
- * Check each B-tree we manage
- * @throws IOException
- * @throws EndOfFileExceededException
- * @throws ClassNotFoundException
- * @throws IllegalAccessException
- * @throws InstantiationException
- */
- private void checkBtrees( int[] checkedPages, int pageSize, int nbBtrees ) throws EndOfFileExceededException,
- IOException, InstantiationException, IllegalAccessException, ClassNotFoundException
- {
- // Iterate on each B-tree until we have exhausted all of them. The number
- // of btrees is just used to check that we have the correct number
- // of stored B-trees, as they are all linked.
- long position = RECORD_MANAGER_HEADER_SIZE;
-
- for ( int i = 0; i < nbBtrees; i++ )
- {
- // Load the pageIOs containing the B-tree
- PageIO[] pageIos = readPageIOs( position, Long.MAX_VALUE );
-
- // Check that they are correctly linked and not already used
- int pageNb = 0;
-
- for ( PageIO currentPageIo : pageIos )
- {
- //
- long nextPageOffset = currentPageIo.getNextPage();
-
- if ( pageNb == pageIos.length - 1 )
- {
- if ( nextPageOffset != NO_PAGE )
- {
- throw new InvalidBTreeException( "The pointer to the next page is not valid, expected NO_PAGE" );
- }
- }
- else
- {
- if ( nextPageOffset == NO_PAGE )
- {
- throw new InvalidBTreeException( "The pointer to the next page is not valid, NO_PAGE" );
- }
- }
-
- if ( ( nextPageOffset != NO_PAGE ) && ( ( nextPageOffset - RECORD_MANAGER_HEADER_SIZE ) % pageSize != 0 ) )
- {
- throw new InvalidBTreeException( "The pointer to the next page is not valid" );
- }
-
- // Update the array of processed pages
- setCheckedPage( checkedPages, currentPageIo.getOffset(), pageSize );
- }
-
- // Now check the B-tree
- long nextBtree = checkBtree( checkedPages, pageIos, pageSize, i == nbBtrees - 1 );
-
- if ( ( nextBtree == NO_PAGE ) && ( i < nbBtrees - 1 ) )
- {
- throw new InvalidBTreeException( "The pointer to the next B-tree is incorrect" );
- }
-
- position = nextBtree;
- }
- }
-
-
- /**
- * Check the whole file
- */
- /* no qualifier */ void check()
- {
- try
- {
- // First check the RMheader
- ByteBuffer recordManagerHeader = ByteBuffer.allocate( RECORD_MANAGER_HEADER_SIZE );
- long fileSize = fileChannel.size();
-
- if ( fileSize < RECORD_MANAGER_HEADER_SIZE )
- {
- throw new InvalidBTreeException( "File size too small : " + fileSize );
- }
-
- // Read the RMHeader
- fileChannel.read( recordManagerHeader, 0L );
- recordManagerHeader.flip();
-
- // The page size. It must be a power of 2, and above 16.
- int pageSize = recordManagerHeader.getInt();
-
- if ( ( pageSize < 0 ) || ( pageSize < 32 ) || ( ( pageSize & ( ~pageSize + 1 ) ) != pageSize ) )
- {
- throw new InvalidBTreeException( "Wrong page size : " + pageSize );
- }
-
- // Compute the number of pages in this file
- long nbPages = ( fileSize - RECORD_MANAGER_HEADER_SIZE ) / pageSize;
-
- // The number of trees. It must be at least 2 and > 0
- int nbBtrees = recordManagerHeader.getInt();
-
- if ( nbBtrees < 0 )
- {
- throw new InvalidBTreeException( "Wrong nb trees : " + nbBtrees );
- }
-
- // The first free page offset. It must be either -1 or below file size
- // and its value must be a modulo of pageSize
- long firstFreePage = recordManagerHeader.getLong();
-
- if ( firstFreePage > fileSize )
- {
- throw new InvalidBTreeException( "First free page pointing after the end of the file : "
- + firstFreePage );
- }
-
- if ( ( firstFreePage != NO_PAGE ) && ( ( ( firstFreePage - RECORD_MANAGER_HEADER_SIZE ) % pageSize ) != 0 ) )
- {
- throw new InvalidBTreeException( "First free page not pointing to a correct offset : " + firstFreePage );
- }
-
- int nbPageBits = ( int ) ( nbPages / 32 );
-
- // Create an array of pages to be checked
- // We use one bit per page. It's 0 when the page
- // hasn't been checked, 1 otherwise.
- int[] checkedPages = new int[nbPageBits + 1];
-
- // Then the free files
- checkFreePages( checkedPages, pageSize, firstFreePage );
-
- // The B-trees
- checkBtrees( checkedPages, pageSize, nbBtrees );
- }
- catch ( Exception e )
- {
- // We catch the exception and rethrow it immediately to be able to
- // put a breakpoint here
- e.printStackTrace();
- throw new InvalidBTreeException( "Error : " + e.getMessage() );
- }
- }
-
-
+
/**
* Loads a B-tree holding the values of a duplicate key
* This tree is also called as dups tree or sub tree
@@ -4047,7 +3672,7 @@ public class RecordManager extends Abstr
/**
* Check the free pages list
*/
- /* no qualifier */ void checkFreePages()
+ /* no qualifier void checkFreePages()
{
try
{