Skip to content

Commit

Permalink
GBPTree can start as read only
Browse files Browse the repository at this point in the history
  • Loading branch information
burqen committed Apr 18, 2017
1 parent 752824e commit 818d742
Show file tree
Hide file tree
Showing 9 changed files with 232 additions and 32 deletions.
Expand Up @@ -288,6 +288,11 @@ default void recoveryCompleted( long numberOfPagesVisited, long numberOfCleanedC
*/
private final Monitor monitor;

/**
* Indicate that index was opened in a read only mode.
*/
private final boolean readOnly;

/**
* Whether or not this tree has been closed. Accessed and changed solely in
* {@link #close()} to be able to close tree multiple times gracefully.
Expand All @@ -300,6 +305,7 @@ default void recoveryCompleted( long numberOfPagesVisited, long numberOfCleanedC
* be written in index header.
* If the index exists it will be opened and the {@link Layout} will be matched with the information
* in the header. At the very least {@link Layout#identifier()} will be matched.
* If index is opened in read only mode, no writes are allowed.
*
* @param pageCache {@link PageCache} to use to map index file
* @param indexFile {@link File} containing the actual index
Expand All @@ -310,13 +316,15 @@ default void recoveryCompleted( long numberOfPagesVisited, long numberOfCleanedC
* @param monitor {@link Monitor} for monitoring {@link GBPTree}.
* @param headerReader reads header data, previously written using {@link #checkpoint(IOLimiter, Consumer)}
* or {@link #close()}
* @param readOnly true if tree should be opened in read only mode.
* @throws IOException on page cache error
*/
public GBPTree( PageCache pageCache, File indexFile, Layout<KEY,VALUE> layout, int tentativePageSize,
Monitor monitor, Header.Reader headerReader ) throws IOException
Monitor monitor, Header.Reader headerReader, boolean readOnly ) throws IOException
{
this.indexFile = indexFile;
this.monitor = monitor;
this.readOnly = readOnly;
this.generation = Generation.generation( GenerationSafePointer.MIN_GENERATION, GenerationSafePointer.MIN_GENERATION + 1 );
long rootId = IdSpace.MIN_TREE_NODE_ID;
setRoot( rootId, Generation.unstableGeneration( generation ) );
Expand Down Expand Up @@ -408,6 +416,10 @@ private PagedFile openOrCreate( PageCache pageCache, File indexFile,
{
// First time
monitor.noStoreFile();
if ( readOnly )
{
throw new UnsupportedOperationException( "Can't create new GBPTree in read only mode." );
}
pageSize = pageSizeForCreation == 0 ? pageCache.pageSize() : pageSizeForCreation;
if ( pageSize > pageCache.pageSize() )
{
Expand Down Expand Up @@ -690,6 +702,11 @@ public void checkpoint( IOLimiter ioLimiter ) throws IOException

private void checkpoint( IOLimiter ioLimiter, Header.Writer headerWriter ) throws IOException
{
if ( readOnly )
{
throw new UnsupportedOperationException( "Can't checkpoint in read only mode." );
}

if ( !changesSinceLastCheckpoint && headerWriter == CARRY_OVER_PREVIOUS_HEADER )
{
// No changes has happened since last checkpoint was called, no need to do another checkpoint
Expand Down Expand Up @@ -774,6 +791,10 @@ public void close() throws IOException
*/
public Writer<KEY,VALUE> writer() throws IOException
{
if ( readOnly )
{
throw new UnsupportedOperationException( "Can't open writer in read only mode." );
}
if ( !writerTaken.compareAndSet( false, true ) )
{
throw new IllegalStateException( "Writer in " + this + " is already acquired by someone else. " +
Expand Down Expand Up @@ -823,6 +844,10 @@ private void setRoot( long rootId, long rootGeneration )
*/
public void prepareForRecovery() throws IOException
{
if ( readOnly )
{
throw new UnsupportedOperationException( "Can't prepare for recovery in read only mode." );
}
if ( changesSinceLastCheckpoint )
{
throw new IllegalStateException( "It seems that this method has been called in the wrong state. " +
Expand All @@ -845,6 +870,10 @@ public void prepareForRecovery() throws IOException
*/
public void finishRecovery() throws IOException
{
if ( readOnly )
{
throw new UnsupportedOperationException( "Can't initiate finish recovery in read only mode." );
}
// For the time being there's an issue where update that come in before a crash
// may be applied in a different order than when they get recovered.
// This may have structural changes be different during recovery than what they were
Expand Down
Expand Up @@ -83,22 +83,6 @@ public class CrashGenerationCleanerTest
crashed( successor() )
);

private class SimpleMonitor implements GBPTree.Monitor
{
boolean recoveryCompleted;
private long numberOfPagesVisited;
private long numberOfCleanedCrashPointers;

@Override
public void recoveryCompleted( long numberOfPagesVisited, long numberOfCleanedCrashPointers,
long durationMillis )
{
recoveryCompleted = true;
this.numberOfPagesVisited = numberOfPagesVisited;
this.numberOfCleanedCrashPointers = numberOfCleanedCrashPointers;
}
}

@Before
public void setupPagedFile() throws IOException
{
Expand All @@ -122,7 +106,7 @@ public void shouldNotCrashOnEmptyFile() throws Exception
initializeFile( pagedFile, pages );

// WHEN
SimpleMonitor monitor = new SimpleMonitor();
SimpleRecoveryCompleteMonitor monitor = new SimpleRecoveryCompleteMonitor();
crashGenerationCleaner( pagedFile, 0, pages.length, monitor ).clean();

// THEN
Expand All @@ -141,7 +125,7 @@ public void shouldNotReportErrorsOnCleanPages() throws Exception
initializeFile( pagedFile, pages );

// WHEN
SimpleMonitor monitor = new SimpleMonitor();
SimpleRecoveryCompleteMonitor monitor = new SimpleRecoveryCompleteMonitor();
crashGenerationCleaner( pagedFile, 0, pages.length, monitor ).clean();

// THEN
Expand Down Expand Up @@ -174,7 +158,7 @@ public void shouldCleanOneCrashPerPage() throws Exception
initializeFile( pagedFile, pages );

// WHEN
SimpleMonitor monitor = new SimpleMonitor();
SimpleRecoveryCompleteMonitor monitor = new SimpleRecoveryCompleteMonitor();
crashGenerationCleaner( pagedFile, 0, pages.length, monitor ).clean();

// THEN
Expand Down Expand Up @@ -202,7 +186,7 @@ public void shouldCleanMultipleCrashPerPage() throws Exception
initializeFile( pagedFile, pages );

// WHEN
SimpleMonitor monitor = new SimpleMonitor();
SimpleRecoveryCompleteMonitor monitor = new SimpleRecoveryCompleteMonitor();
crashGenerationCleaner( pagedFile, 0, pages.length, monitor ).clean();

// THEN
Expand All @@ -227,7 +211,7 @@ public void shouldCleanLargeFile() throws Exception
initializeFile( pagedFile, pages );

// WHEN
SimpleMonitor monitor = new SimpleMonitor();
SimpleRecoveryCompleteMonitor monitor = new SimpleRecoveryCompleteMonitor();
crashGenerationCleaner( pagedFile, 0, numberOfPages, monitor ).clean();

// THEN
Expand All @@ -236,7 +220,7 @@ public void shouldCleanLargeFile() throws Exception
}

private CrashGenerationCleaner crashGenerationCleaner( PagedFile pagedFile, int lowTreeNodeId, int highTreeNodeId,
SimpleMonitor monitor )
SimpleRecoveryCompleteMonitor monitor )
{
return new CrashGenerationCleaner( pagedFile, corruptableTreeNode, lowTreeNodeId, highTreeNodeId,
stableGeneration, unstableGeneration, monitor );
Expand All @@ -255,15 +239,15 @@ private void initializeFile( PagedFile pagedFile, Page... pages ) throws IOExcep
}

/* Assertions */
private void assertCleanedCrashPointers( SimpleMonitor monitor,
private void assertCleanedCrashPointers( SimpleRecoveryCompleteMonitor monitor,
int expectedNumberOfCleanedCrashPointers )
{
assertEquals( "Expected number of cleaned crash pointers to be " +
expectedNumberOfCleanedCrashPointers + " but was " + monitor.numberOfCleanedCrashPointers,
expectedNumberOfCleanedCrashPointers, monitor.numberOfCleanedCrashPointers );
}

private void assertPagesVisisted( SimpleMonitor monitor, int expectedNumberOfPagesVisited )
private void assertPagesVisisted( SimpleRecoveryCompleteMonitor monitor, int expectedNumberOfPagesVisited )
{
assertEquals( "Expected number of visited pages to be " + expectedNumberOfPagesVisited +
" but was " + monitor.numberOfPagesVisited,
Expand Down
Expand Up @@ -98,7 +98,7 @@ public void shouldDetectFormatChange() throws Throwable
// THEN everything should work, otherwise there has likely been a format change
PageCache pageCache = pageCacheRule.getPageCache( fsRule.get() );
try ( GBPTree<MutableLong,MutableLong> tree =
new GBPTree<>( pageCache, storeFile, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER ) )
new GBPTree<>( pageCache, storeFile, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER, false ) )
{
try
{
Expand Down Expand Up @@ -174,7 +174,7 @@ private void createAndZipTree( File storeFile ) throws IOException
{
PageCache pageCache = pageCacheRule.getPageCache( fsRule.get() );
try ( GBPTree<MutableLong,MutableLong> tree =
new GBPTree<>( pageCache, storeFile, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER ) )
new GBPTree<>( pageCache, storeFile, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER, false ) )
{
MutableLong insertKey = new MutableLong();
MutableLong insertValue = new MutableLong();
Expand Down
Expand Up @@ -107,7 +107,7 @@ private GBPTree<MutableLong,MutableLong> createIndex( GBPTree.Monitor monitor )
PageCache pageCache =
pageCacheRule.getPageCache( fs.get(), config().withPageSize( pageSize ).withAccessChecks( true ) );
return index = new GBPTree<>( pageCache, directory.file( "index" ),
layout, 0/*use whatever page cache says*/, monitor, NO_HEADER );
layout, 0/*use whatever page cache says*/, monitor, NO_HEADER, false );
}

@After
Expand Down
Expand Up @@ -76,7 +76,7 @@ private GBPTree<MutableLong,MutableLong> createIndex( int pageSize, GBPTree.Moni
{
pageCache = pageCacheRule.getPageCache( fs.get(), config().withPageSize( pageSize ).withAccessChecks( true ) );
return index = new GBPTree<>( pageCache, directory.file( "index" ),
layout, 0/*use whatever page cache says*/, monitor, NO_HEADER );
layout, 0/*use whatever page cache says*/, monitor, NO_HEADER, false );
}

@After
Expand Down
Expand Up @@ -388,7 +388,7 @@ private long[] modificationData( int min, int max )

private static GBPTree<MutableLong,MutableLong> createIndex( PageCache pageCache, File file ) throws IOException
{
return new GBPTree<>( pageCache, file, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER );
return new GBPTree<>( pageCache, file, new SimpleLongLayout(), 0, NO_MONITOR, NO_HEADER, false );
}

private PageCache createPageCache()
Expand Down

0 comments on commit 818d742

Please sign in to comment.