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 != recordManager.pageSize ) || ( 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 ) || ( nbBtrees != recordManager.nbBtree ) )
{
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 != RecordManager.NO_PAGE )
{
checkOffset( recordManager, firstFreePage );
}
int nbPageBits = ( int ) ( nbPages / 32 );
// Create an array of pages to be checked for each B-tree, plus
// two others for the free pages and the global one
// We use one bit per page. It's 0 when the page
// hasn't been checked, 1 otherwise.
Map<String, int[]> checkedPages = new HashMap<String, int[]>(nbBtrees + 4);
// The global page array
checkedPages.put( GLOBAL_PAGES_NAME, new int[nbPageBits + 1] );
// The freePages array
checkedPages.put( FREE_PAGES_NAME, new int[nbPageBits + 1] );
// The B-tree of B-trees array
checkedPages.put( RecordManager.BTREE_OF_BTREES_NAME, new int[nbPageBits + 1] );
// Last, the Copied Pages B-tree array
checkedPages.put( RecordManager.COPIED_PAGE_BTREE_NAME, new int[nbPageBits + 1] );
// Check the free files
checkFreePages( recordManager, checkedPages );
// The B-trees offsets
long currentBtreeOfBtreesOffset = recordManagerHeader.getLong();
long previousBtreeOfBtreesOffset = recordManagerHeader.getLong();
long currentCopiedPagesBtreeOffset = recordManagerHeader.getLong();
long previousCopiedPagesBtreeOffset = recordManagerHeader.getLong();
// Check that the previous BOB offset is not pointing to something
if ( previousBtreeOfBtreesOffset != RecordManager.NO_PAGE )
{
System.out.println( "The previous Btree of Btrees offset is not valid : "
+ previousBtreeOfBtreesOffset );
return;
}
// Check that the previous CPB offset is not pointing to something
if ( previousCopiedPagesBtreeOffset != RecordManager.NO_PAGE )
{
System.out.println( "The previous Copied Pages Btree offset is not valid : "
+ previousCopiedPagesBtreeOffset );
return;
}
// Check that the current BOB offset is valid
checkOffset( recordManager, currentBtreeOfBtreesOffset );
// Check that the current CPB offset is valid
checkOffset( recordManager, currentCopiedPagesBtreeOffset );
// Now, check the BTree of Btrees
checkBtreeOfBtrees( recordManager, checkedPages );
// And the Copied Pages BTree
checkBtree( recordManager, currentCopiedPagesBtreeOffset, checkedPages );
// We can now dump the checked pages
dumpCheckedPages( recordManager, checkedPages );
}
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() );
}
}