Skip to content

Commit

Permalink
Resolve absolute store directory before constructing 3.5 specific pro…
Browse files Browse the repository at this point in the history
…perties.

If store dir is not absolute its possible to have its parent as null
if we will try to resolve store directory.
  • Loading branch information
MishaDemianenko committed Aug 24, 2018
1 parent 1094a13 commit 1447a86
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 69 deletions.
Expand Up @@ -19,35 +19,45 @@
*/
package db;

import org.junit.Rule;
import org.junit.Test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import java.io.File;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.facade.GraphDatabaseFacadeFactory;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.graphdb.factory.module.CommunityEditionModule;
import org.neo4j.graphdb.factory.module.PlatformModule;
import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction;
import org.neo4j.io.fs.DefaultFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache;
import org.neo4j.io.pagecache.impl.muninn.StandalonePageCacheFactory;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.factory.DatabaseInfo;
import org.neo4j.kernel.impl.store.MetaDataStore;
import org.neo4j.kernel.impl.storemigration.StoreUpgrader;
import org.neo4j.kernel.lifecycle.LifecycleException;
import org.neo4j.test.TestGraphDatabaseFactory;
import org.neo4j.test.extension.Inject;
import org.neo4j.test.extension.TestDirectoryExtension;
import org.neo4j.test.rule.TestDirectory;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.neo4j.io.pagecache.impl.muninn.StandalonePageCacheFactory.createPageCache;

public class DatabaseStartupTest
@ExtendWith( TestDirectoryExtension.class )
class DatabaseStartupTest
{
@Rule
public final TestDirectory testDirectory = TestDirectory.testDirectory();
@Inject
private TestDirectory testDirectory;

@Test
public void startTheDatabaseWithWrongVersionShouldFailWithUpgradeNotAllowed() throws Throwable
void startTheDatabaseWithWrongVersionShouldFailWithUpgradeNotAllowed() throws Throwable
{
// given
// create a store
Expand All @@ -62,29 +72,20 @@ public void startTheDatabaseWithWrongVersionShouldFailWithUpgradeNotAllowed() th

// mess up the version in the metadatastore
try ( FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction();
PageCache pageCache = StandalonePageCacheFactory.createPageCache( fileSystem ) )
PageCache pageCache = createPageCache( fileSystem ) )
{
MetaDataStore.setRecord( pageCache, testDirectory.databaseLayout().metadataStore(),
MetaDataStore.Position.STORE_VERSION, MetaDataStore.versionStringToLong( "bad" ));
}

// when
try
{
new TestGraphDatabaseFactory().newEmbeddedDatabase( databaseDir );
fail( "It should have failed." );
}
catch ( RuntimeException ex )
{
// then
assertTrue( ex.getCause() instanceof LifecycleException );
assertTrue( ex.getCause().getCause() instanceof IllegalArgumentException );
assertEquals( "Unknown store version 'bad'", ex.getCause().getCause().getMessage() );
}
RuntimeException exception = assertThrows( RuntimeException.class, () -> new TestGraphDatabaseFactory().newEmbeddedDatabase( databaseDir ) );
assertTrue( exception.getCause() instanceof LifecycleException );
assertTrue( exception.getCause().getCause() instanceof IllegalArgumentException );
assertEquals( "Unknown store version 'bad'", exception.getCause().getCause().getMessage() );
}

@Test
public void startTheDatabaseWithWrongVersionShouldFailAlsoWhenUpgradeIsAllowed() throws Throwable
void startTheDatabaseWithWrongVersionShouldFailAlsoWhenUpgradeIsAllowed() throws Throwable
{
// given
// create a store
Expand All @@ -100,24 +101,70 @@ public void startTheDatabaseWithWrongVersionShouldFailAlsoWhenUpgradeIsAllowed()
// mess up the version in the metadatastore
String badStoreVersion = "bad";
try ( FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction();
PageCache pageCache = StandalonePageCacheFactory.createPageCache( fileSystem ) )
PageCache pageCache = createPageCache( fileSystem ) )
{
MetaDataStore.setRecord( pageCache, testDirectory.databaseLayout().metadataStore(),
MetaDataStore.Position.STORE_VERSION, MetaDataStore.versionStringToLong( badStoreVersion ) );
MetaDataStore.setRecord( pageCache, testDirectory.databaseLayout().metadataStore(), MetaDataStore.Position.STORE_VERSION,
MetaDataStore.versionStringToLong( badStoreVersion ) );
}

RuntimeException exception = assertThrows( RuntimeException.class,
() -> new TestGraphDatabaseFactory().newEmbeddedDatabaseBuilder( databaseDirectory ).setConfig( GraphDatabaseSettings.allow_upgrade,
"true" ).newGraphDatabase() );
assertTrue( exception.getCause() instanceof LifecycleException );
assertTrue( exception.getCause().getCause() instanceof StoreUpgrader.UnexpectedUpgradingStoreVersionException );
}

@Test
void startTestDatabaseOnProvidedNonAbsoluteFile()
{
File directory = new File( "notAbsoluteDirectory" );
new TestGraphDatabaseFactory().newImpermanentDatabase( directory ).shutdown();
}

@Test
void startCommunityDatabaseOnProvidedNonAbsoluteFile()
{
File directory = new File( "notAbsoluteDirectory" );
EphemeralCommunityFacadeFactory factory = new EphemeralCommunityFacadeFactory();
GraphDatabaseFactory databaseFactory = new EphemeralGraphDatabaseFactory( factory );
GraphDatabaseService service = databaseFactory.newEmbeddedDatabase( directory );
service.shutdown();
}

private static class EphemeralCommunityFacadeFactory extends GraphDatabaseFacadeFactory
{
EphemeralCommunityFacadeFactory()
{
super( DatabaseInfo.COMMUNITY, CommunityEditionModule::new );
}

// when
try
@Override
protected PlatformModule createPlatform( File storeDir, Config config, Dependencies dependencies )
{
new TestGraphDatabaseFactory().newEmbeddedDatabaseBuilder( databaseDirectory )
.setConfig( GraphDatabaseSettings.allow_upgrade, "true" ).newGraphDatabase();
fail( "It should have failed." );
return new PlatformModule( storeDir, config, databaseInfo, dependencies )
{
@Override
protected FileSystemAbstraction createFileSystemAbstraction()
{
return new EphemeralFileSystemAbstraction();
}
};
}
catch ( RuntimeException ex )
}

private static class EphemeralGraphDatabaseFactory extends GraphDatabaseFactory
{
private final EphemeralCommunityFacadeFactory factory;

EphemeralGraphDatabaseFactory( EphemeralCommunityFacadeFactory factory )
{
this.factory = factory;
}

@Override
protected GraphDatabaseFacadeFactory getGraphDatabaseFacadeFactory()
{
// then
assertTrue( ex.getCause() instanceof LifecycleException );
assertTrue( ex.getCause().getCause() instanceof StoreUpgrader.UnexpectedUpgradingStoreVersionException );
return factory;
}
}
}
Expand Up @@ -59,10 +59,11 @@ protected GraphDatabaseService newEmbeddedDatabase( File dir, Config config, Dep
@Override
protected PlatformModule createPlatform( File storeDir, Config config, Dependencies dependencies )
{
File databasesRoot = storeDir.getParentFile();
config.augment( GraphDatabaseSettings.active_database, storeDir.getName() );
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
config.augment( GraphDatabaseSettings.active_database, absoluteStoreDir.getName() );
config.augment( GraphDatabaseSettings.databases_root_path, databasesRoot.getAbsolutePath() );
return new PlatformModule( storeDir, config, databaseInfo, dependencies )
return new PlatformModule( databasesRoot, config, databaseInfo, dependencies )
{
@Override
protected FileSystemAbstraction createFileSystemAbstraction()
Expand Down
Expand Up @@ -82,9 +82,10 @@ public GraphDatabaseService newImpermanentDatabase()

public GraphDatabaseService newImpermanentDatabase( File storeDir )
{
GraphDatabaseBuilder databaseBuilder = newImpermanentDatabaseBuilder( storeDir );
databaseBuilder.setConfig( GraphDatabaseSettings.active_database, storeDir.getName() );
databaseBuilder.setConfig( GraphDatabaseSettings.databases_root_path, storeDir.getParentFile().getAbsolutePath() );
File absoluteDirectory = storeDir.getAbsoluteFile();
GraphDatabaseBuilder databaseBuilder = newImpermanentDatabaseBuilder( absoluteDirectory );
databaseBuilder.setConfig( GraphDatabaseSettings.active_database, absoluteDirectory.getName() );
databaseBuilder.setConfig( GraphDatabaseSettings.databases_root_path, absoluteDirectory.getParentFile().getAbsolutePath() );
return databaseBuilder.newGraphDatabase();
}

Expand Down Expand Up @@ -268,9 +269,10 @@ protected TestGraphDatabaseFacadeFactory( TestGraphDatabaseFactoryState state, b
@Override
protected PlatformModule createPlatform( File storeDir, Config config, Dependencies dependencies )
{
File databasesRoot = storeDir.getParentFile();
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
config.augment( GraphDatabaseSettings.ephemeral, Settings.FALSE );
config.augment( GraphDatabaseSettings.active_database, storeDir.getName() );
config.augment( GraphDatabaseSettings.active_database, absoluteStoreDir.getName() );
config.augment( GraphDatabaseSettings.databases_root_path, databasesRoot.getAbsolutePath() );
if ( impermanent )
{
Expand Down
Expand Up @@ -200,8 +200,9 @@ private class Database extends ImpermanentGraphDatabase
@Override
protected void create( File storeDir, Map<String, String> params, GraphDatabaseFacadeFactory.Dependencies dependencies )
{
File databasesRoot = storeDir.getParentFile();
params.put( GraphDatabaseSettings.active_database.name(), storeDir.getName() );
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
params.put( GraphDatabaseSettings.active_database.name(), absoluteStoreDir.getName() );
params.put( GraphDatabaseSettings.databases_root_path.name(), databasesRoot.getAbsolutePath() );
new GraphDatabaseFacadeFactory( DatabaseInfo.COMMUNITY, CommunityEditionModule::new )
{
Expand Down
Expand Up @@ -102,17 +102,9 @@ protected GraphDatabaseBuilder createGraphDatabaseBuilder( GraphDatabaseBuilder.
return new GraphDatabaseBuilder( creator );
}

protected GraphDatabaseBuilder.DatabaseCreator createDatabaseCreator(
final File storeDir, final GraphDatabaseFactoryState state )
protected GraphDatabaseBuilder.DatabaseCreator createDatabaseCreator( final File storeDir, final GraphDatabaseFactoryState state )
{
return new GraphDatabaseBuilder.DatabaseCreator()
{
@Override
public GraphDatabaseService newDatabase( @Nonnull Config config )
{
return GraphDatabaseFactory.this.newEmbeddedDatabase( storeDir, config, state.databaseDependencies() );
}
};
return new EmbeddedDatabaseCreator( storeDir, state );
}

protected void configure( GraphDatabaseBuilder builder )
Expand All @@ -139,12 +131,17 @@ protected GraphDatabaseService newEmbeddedDatabase( File storeDir, Config config
protected GraphDatabaseService newDatabase( File storeDir, Config config,
GraphDatabaseFacadeFactory.Dependencies dependencies )
{
File databasesRoot = storeDir.getParentFile();
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
config.augment( GraphDatabaseSettings.ephemeral, Settings.FALSE );
config.augment( GraphDatabaseSettings.active_database, storeDir.getName() );
config.augment( GraphDatabaseSettings.active_database, absoluteStoreDir.getName() );
config.augment( GraphDatabaseSettings.databases_root_path, databasesRoot.getAbsolutePath() );
return new GraphDatabaseFacadeFactory( DatabaseInfo.COMMUNITY, CommunityEditionModule::new )
.newFacade( databasesRoot, config, dependencies );
return getGraphDatabaseFacadeFactory().newFacade( databasesRoot, config, dependencies );
}

protected GraphDatabaseFacadeFactory getGraphDatabaseFacadeFactory()
{
return new GraphDatabaseFacadeFactory( DatabaseInfo.COMMUNITY, CommunityEditionModule::new );
}

public GraphDatabaseFactory addURLAccessRule( String protocol, URLAccessRule rule )
Expand All @@ -169,4 +166,22 @@ public String getEdition()
{
return Edition.community.toString();
}

private class EmbeddedDatabaseCreator implements GraphDatabaseBuilder.DatabaseCreator
{
private final File storeDir;
private final GraphDatabaseFactoryState state;

EmbeddedDatabaseCreator( File storeDir, GraphDatabaseFactoryState state )
{
this.storeDir = storeDir;
this.state = state;
}

@Override
public GraphDatabaseService newDatabase( @Nonnull Config config )
{
return newEmbeddedDatabase( storeDir, config, state.databaseDependencies() );
}
}
}
Expand Up @@ -137,9 +137,10 @@ public static class GraphDatabaseFactoryWithPageCacheFactory extends GraphDataba
protected GraphDatabaseService newDatabase( File storeDir, Config config,
GraphDatabaseFacadeFactory.Dependencies dependencies )
{
File databasesRoot = storeDir.getParentFile();
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
config.augment( GraphDatabaseSettings.ephemeral, Settings.FALSE );
config.augment( GraphDatabaseSettings.active_database, storeDir.getName() );
config.augment( GraphDatabaseSettings.active_database, absoluteStoreDir.getName() );
config.augment( GraphDatabaseSettings.databases_root_path, databasesRoot.getAbsolutePath() );
return new GraphDatabaseFacadeFactory( DatabaseInfo.ENTERPRISE, EnterpriseEditionModule::new )
{
Expand Down
Expand Up @@ -62,9 +62,10 @@ protected GraphDatabaseBuilder.DatabaseCreator createDatabaseCreator(
@Override
public GraphDatabaseService newDatabase( Config config )
{
File databasesRoot = storeDir.getParentFile();
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
config.augment( GraphDatabaseSettings.ephemeral, Settings.FALSE );
config.augment( GraphDatabaseSettings.active_database, storeDir.getName() );
config.augment( GraphDatabaseSettings.active_database, absoluteStoreDir.getName() );
config.augment( GraphDatabaseSettings.databases_root_path, databasesRoot.getAbsolutePath() );
return new HighlyAvailableGraphDatabase( databasesRoot, config, state.databaseDependencies() );
}
Expand Down
Expand Up @@ -46,9 +46,10 @@ protected GraphDatabaseBuilder.DatabaseCreator createDatabaseCreator( final File
@Override
public GraphDatabaseService newDatabase( Config config )
{
File databasesRoot = storeDir.getParentFile();
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
config.augment( GraphDatabaseSettings.ephemeral, Settings.FALSE );
config.augment( GraphDatabaseSettings.active_database, storeDir.getName() );
config.augment( GraphDatabaseSettings.active_database, absoluteStoreDir.getName() );
config.augment( GraphDatabaseSettings.databases_root_path, databasesRoot.getAbsolutePath() );
return new EnterpriseGraphDatabase( databasesRoot, config, state.databaseDependencies() );
}
Expand Down
Expand Up @@ -64,9 +64,10 @@ protected GraphDatabaseBuilder.DatabaseCreator createDatabaseCreator( File store
@Override
public GraphDatabaseService newDatabase( Config config )
{
File databasesRoot = storeDir.getParentFile();
File absoluteStoreDir = storeDir.getAbsoluteFile();
File databasesRoot = absoluteStoreDir.getParentFile();
config.augment( GraphDatabaseSettings.ephemeral, Settings.FALSE );
config.augment( GraphDatabaseSettings.active_database, storeDir.getName() );
config.augment( GraphDatabaseSettings.active_database, absoluteStoreDir.getName() );
config.augment( GraphDatabaseSettings.databases_root_path, databasesRoot.getAbsolutePath() );
return new GraphDatabaseFacadeFactory( DatabaseInfo.ENTERPRISE, EnterpriseEditionModule::new )
{
Expand Down

0 comments on commit 1447a86

Please sign in to comment.