ByteBuffer header = ByteBuffer.allocate( HEADER_SIZE );
long fileSize = fileChannel.size();
if ( fileSize < HEADER_SIZE )
{
throw new InvalidBTreeException( "File size too small : " + fileSize );
}
// Read the header
fileChannel.read( header, 0L );
header.flip();
// The page size. It must be a power of 2, and above 16.
int pageSize = header.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 - HEADER_SIZE ) / pageSize;
// The number of trees. It must be at least 2 and > 0
int nbBTrees = header.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 = header.getLong();
if ( firstFreePage > fileSize )
{
throw new InvalidBTreeException( "First free page pointing after the end of the file : "
+ firstFreePage );
}
if ( ( firstFreePage != NO_PAGE ) && ( ( ( firstFreePage - HEADER_SIZE ) % pageSize ) != 0 ) )
{
throw new InvalidBTreeException( "First free page not pointing to a correct offset : " + firstFreePage );
}
int nbPageBits = ( int ) ( nbPages / 64 );
// 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.
long[] checkedPages = new long[nbPageBits + 1];
// Then the free files
checkFreePages( checkedPages, pageSize, firstFreePage );
// The BTrees
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() );
}
}