Skip to content

Commit

Permalink
LuceneLabelScanStore gets told if it's read-only
Browse files Browse the repository at this point in the history
previously it was always writable, no matter what the neo4j config said.
Integerestingly compliance testing tested the LuceneLabelScanStore directly
and it asserted that a read-only label scan store shouldn't be able to
create an initial store.

When looking at the rest of the stores, they are actually created, even when
read-only mode is set. Label scan store just happened to not fail when it was
in read-only mode. So now lss aligns with stores in general in that they can
be created even in read-only mode.
  • Loading branch information
tinwelint committed Jan 31, 2017
1 parent aec2a6e commit d2b2ef8
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 26 deletions.
Expand Up @@ -188,7 +188,7 @@ public DirectStoreAccess directStoreAccess()
Dependencies dependencies = new Dependencies();
dependencies.satisfyDependencies( Config.defaults(), fileSystem,
new SimpleLogService( logProvider, logProvider ), indexStoreView, pageCache );
KernelContext kernelContext = new SimpleKernelContext( fileSystem, directory, UNKNOWN, dependencies );
KernelContext kernelContext = new SimpleKernelContext( directory, UNKNOWN, dependencies );
LabelScanStore labelScanStore = startLabelScanStore( config, dependencies, kernelContext );
directStoreAccess = new DirectStoreAccess( nativeStores, labelScanStore, createIndexes( fileSystem,
config, operationalMode ) );
Expand Down
Expand Up @@ -20,7 +20,6 @@
package org.neo4j.kernel.api.impl.labelscan;

import org.hamcrest.Matcher;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -123,10 +122,15 @@ public void forceShouldNotForceWriterOnReadOnlyScanStore()
}

@Test
public void failToStartIfLabelScanStoreIndexDoesNotExistInReadOnlyMode()
public void shouldStartIfLabelScanStoreIndexDoesNotExistInReadOnlyMode() throws IOException
{
expectedException.expectCause( Matchers.instanceOf( UnsupportedOperationException.class ) );
// WHEN
start( false, true );

// THEN

// no exception
assertTrue( store.isEmpty() );
}

@Test
Expand Down
Expand Up @@ -24,7 +24,6 @@
import java.util.function.Supplier;

import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.api.impl.labelscan.LabelScanIndex;
import org.neo4j.kernel.api.impl.labelscan.LuceneLabelScanIndexBuilder;
import org.neo4j.kernel.api.impl.labelscan.LuceneLabelScanStore;
import org.neo4j.kernel.api.labelscan.LabelScanStore;
Expand Down Expand Up @@ -78,13 +77,13 @@ public LabelScanStore build()
{
// TODO: Replace with kernel extension based lookup
LabelScanStore.Monitor monitor = new LoggingMonitor( logProvider.getLog( LuceneLabelScanStore.class ) );
LabelScanIndex index = LuceneLabelScanIndexBuilder.create()
LuceneLabelScanIndexBuilder indexBuilder = LuceneLabelScanIndexBuilder.create()
.withFileSystem( fileSystem )
.withIndexRootFolder( getStoreDirectory( storeDir ) )
.withConfig( config )
.withOperationalMode( operationalMode )
.build();
labelScanStore = new LuceneLabelScanStore( index, new FullLabelStream( storeViewSupplier ), monitor );
.withOperationalMode( operationalMode );
labelScanStore = new LuceneLabelScanStore( indexBuilder, new FullLabelStream( storeViewSupplier ),
monitor );

try
{
Expand Down
Expand Up @@ -71,4 +71,9 @@ public LabelScanIndex build()
return isReadOnly() ? new ReadOnlyDatabaseLabelScanIndex( format, storageBuilder.build() )
: new WritableDatabaseLabelScanIndex( format, storageBuilder.build() );
}

public LabelScanIndex buildWritable()
{
return new WritableDatabaseLabelScanIndex( format, storageBuilder.build() );
}
}
Expand Up @@ -23,7 +23,6 @@

import java.io.File;
import java.io.IOException;

import org.neo4j.graphdb.ResourceIterator;
import org.neo4j.io.pagecache.IOLimiter;
import org.neo4j.kernel.api.labelscan.AllEntriesLabelScanReader;
Expand All @@ -36,16 +35,19 @@

public class LuceneLabelScanStore implements LabelScanStore
{
private final LabelScanIndex luceneIndex;
private final LuceneLabelScanIndexBuilder indexBuilder;
private volatile LabelScanIndex luceneIndex;
// We get in a full store stream here in case we need to fully rebuild the store if it's missing or corrupted.
private final FullStoreChangeStream fullStoreStream;
private final Monitor monitor;
private boolean needsRebuild;
private boolean switchBackToReadOnly;

public LuceneLabelScanStore( LabelScanIndex luceneIndex, FullStoreChangeStream fullStoreStream,
Monitor monitor )
public LuceneLabelScanStore( LuceneLabelScanIndexBuilder indexBuilder,
FullStoreChangeStream fullStoreStream, Monitor monitor )
{
this.luceneIndex = luceneIndex;
this.indexBuilder = indexBuilder;
this.luceneIndex = indexBuilder.build();
this.fullStoreStream = fullStoreStream;
this.monitor = monitor;
}
Expand Down Expand Up @@ -94,7 +96,7 @@ public void init() throws IOException
{
monitor.noIndex();

luceneIndex.create();
create();
needsRebuild = true;
}
else if ( !luceneIndex.isValid() )
Expand All @@ -114,6 +116,18 @@ else if ( !luceneIndex.isValid() )
}
}

private void create() throws IOException
{
if ( luceneIndex.isReadOnly() )
{
luceneIndex.close();
luceneIndex = indexBuilder.buildWritable();
luceneIndex.create();
switchBackToReadOnly = true;
// We'll switch back in start() later
}
}

@Override
public void start() throws IOException
{
Expand All @@ -125,6 +139,13 @@ public void start() throws IOException
monitor.rebuilt( numberOfNodes );
needsRebuild = false;
}

if ( switchBackToReadOnly )
{
luceneIndex.close();
luceneIndex = indexBuilder.build();
luceneIndex.open();
}
}

@Override
Expand Down
Expand Up @@ -80,25 +80,27 @@ public LuceneLabelScanStoreExtension()
@Override
public LabelScanStoreProvider newInstance( KernelContext context, Dependencies dependencies ) throws Throwable
{
boolean ephemeral = dependencies.getConfig().get( GraphDatabaseFacadeFactory.Configuration.ephemeral );
DirectoryFactory directoryFactory = directoryFactory( ephemeral, dependencies.fileSystem() );
Config config = dependencies.getConfig();
boolean ephemeral = config.get( GraphDatabaseFacadeFactory.Configuration.ephemeral );
FileSystemAbstraction fileSystem = dependencies.fileSystem();
DirectoryFactory directoryFactory = directoryFactory( ephemeral, fileSystem );

LabelScanIndex index = getLuceneIndex( context, directoryFactory, dependencies.fileSystem() );
LuceneLabelScanIndexBuilder indexBuilder = getIndexBuilder( context, directoryFactory, fileSystem, config );
LogProvider logger = dependencies.getLogService().getInternalLogProvider();
Monitor loggingMonitor = new LoggingMonitor( logger.getLog( LuceneLabelScanStore.class ), monitor );
LuceneLabelScanStore scanStore = new LuceneLabelScanStore( index,
LuceneLabelScanStore scanStore = new LuceneLabelScanStore( indexBuilder,
new FullLabelStream( dependencies.indexStoreView() ), loggingMonitor );

return new LabelScanStoreProvider( LABEL_SCAN_STORE_NAME, scanStore, priority );
}

private LabelScanIndex getLuceneIndex( KernelContext context, DirectoryFactory directoryFactory,
FileSystemAbstraction fileSystem )
private LuceneLabelScanIndexBuilder getIndexBuilder( KernelContext context, DirectoryFactory directoryFactory,
FileSystemAbstraction fileSystem, Config config )
{
return LuceneLabelScanIndexBuilder.create()
.withDirectoryFactory( directoryFactory )
.withFileSystem( fileSystem )
.withIndexRootFolder( LabelScanStoreProvider.getStoreDirectory( context.storeDir() ) )
.build();
.withConfig( config );
}
}
Expand Up @@ -68,15 +68,14 @@ protected LabelScanStore createLabelScanStore( FileSystemAbstraction fs, File ro
Config config = Config.defaults().with( MapUtil.stringMap(
GraphDatabaseSettings.read_only.name(), String.valueOf( readOnly ) ) );

LabelScanIndex index = LuceneLabelScanIndexBuilder.create()
LuceneLabelScanIndexBuilder indexBuilder = LuceneLabelScanIndexBuilder.create()
.withDirectoryFactory( directoryFactory )
.withIndexStorage( indexStorage )
.withOperationalMode( OperationalMode.single )
.withConfig( config )
.withDocumentFormat( documentFormat )
.build();
.withDocumentFormat( documentFormat );

return new LuceneLabelScanStore( index, asStream( existingData ), monitor );
return new LuceneLabelScanStore( indexBuilder, asStream( existingData ), monitor );
}

@Override
Expand Down

0 comments on commit d2b2ef8

Please sign in to comment.