Skip to content

Commit

Permalink
Fail database startup in incompatible situations.
Browse files Browse the repository at this point in the history
Custom IO configurations are now supported in single instance mode.
Store copy operations are not supported, and that therefore excludes
using custom IO configurations in HA, online backup, and store migration.
Determining if you violate these restrictions is most easily done by
inspecting config options. This restriction is expected to be short lived and
can be removed once store copy is supported with custom IO configurations.
  • Loading branch information
Max Sumrall committed Apr 12, 2016
1 parent eb83262 commit 1757945
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 71 deletions.
Expand Up @@ -338,7 +338,7 @@ public NeoStoreDataSource(
RecordFormats formats )
{
this.storeDir = storeDir;
this.config = validateSettingsForPageSwapper( config );
this.config = config;
this.tokenNameLookup = tokenNameLookup;
this.dependencyResolver = dependencyResolver;
this.scheduler = scheduler;
Expand Down Expand Up @@ -398,36 +398,6 @@ public Iterable<IndexImplementation> all()
this.pageCache = pageCache;
}

/**
* Custom IO integrations are partially supported, but the features below are not functional yet.
* When those features are available, this check can be removed entirely.
* This will allow us to ship the custom IO integration for experimental use, and protect users from
* using it with the currently unsupported features. i.e using custom IO integration in HA mode.
*/
private Config validateSettingsForPageSwapper( Config config )
{
if ( config.get( GraphDatabaseSettings.pagecache_swapper ) != null )
{
if ( config.get( GraphDatabaseSettings.allow_store_upgrade ) )
{
throw new IllegalArgumentException( "Store upgrade not allowed with custom IO integrations" );
}
String onlineBackup = config.getParams().get( "dbms.backup.enabled" );
if ( onlineBackup != null && !onlineBackup.equals( "false" ) )
{
throw new IllegalArgumentException( "Online Backup not allowed with custom IO integration" );
}
for ( String configKey : config.getParams().keySet() )
{
if ( configKey.contains( "ha." ) )
{
throw new IllegalArgumentException( "HA mode not allowed with custom IO integrations" );
}
}
}
return config;
}

@Override
public void init()
{ // We do our own internal life management:
Expand Down
Expand Up @@ -22,6 +22,7 @@
import java.io.File;

import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.factory.DatabaseInfo;
import org.neo4j.kernel.impl.util.DependencySatisfier;

Expand All @@ -34,4 +35,6 @@ public interface KernelContext
DatabaseInfo databaseInfo();

DependencySatisfier dependencySatisfier();

boolean customIOConfigurationUsed( Config config );
}
Expand Up @@ -21,7 +21,9 @@

import java.io.File;

import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.impl.factory.DatabaseInfo;
import org.neo4j.kernel.impl.util.DependencySatisfier;

Expand Down Expand Up @@ -64,4 +66,10 @@ public DependencySatisfier dependencySatisfier()
{
return satisfier;
}

@Override
public boolean customIOConfigurationUsed( Config config )
{
return config.get( GraphDatabaseSettings.pagecache_swapper ) != null;
}
}
Expand Up @@ -65,6 +65,7 @@ public class StoreUpgrader
public static final String MIGRATION_DIRECTORY = "upgrade";
public static final String MIGRATION_LEFT_OVERS_DIRECTORY = "upgrade_backup";
private static final String MIGRATION_STATUS_FILE = "_status";
public static final String CUSTOM_IO_EXCEPTION_MESSAGE = "Store upgrade not allowed with custom IO integrations";

private final UpgradableDatabase upgradableDatabase;
private final MigrationProgressMonitor progressMonitor;
Expand Down Expand Up @@ -113,6 +114,11 @@ public void migrateIfNeeded( File storeDirectory)
throw new UpgradeNotAllowedByConfigurationException();
}

if( customIOConfigurationUsed( config ) )
{
throw new IllegalArgumentException( CUSTOM_IO_EXCEPTION_MESSAGE );
}

// One or more participants would like to do migration
progressMonitor.started();

Expand Down Expand Up @@ -151,6 +157,11 @@ public void migrateIfNeeded( File storeDirectory)
progressMonitor.completed();
}

private boolean customIOConfigurationUsed( Config config )
{
return config.get( GraphDatabaseSettings.pagecache_swapper ) != null;
}

private boolean isUpgradeAllowed()
{
return config.get( GraphDatabaseSettings.allow_store_upgrade );
Expand Down
Expand Up @@ -19,40 +19,62 @@
*/
package upgrade;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import java.io.File;
import java.io.IOException;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.kernel.configuration.Settings;
import org.neo4j.io.fs.DefaultFileSystemAbstraction;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.impl.store.format.lowlimit.LowLimitV2_2;
import org.neo4j.kernel.impl.storemigration.StoreUpgrader;
import org.neo4j.test.TargetDirectory;
import org.neo4j.test.TestGraphDatabaseFactory;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static org.neo4j.kernel.impl.storemigration.MigrationTestUtils.prepareSampleLegacyDatabase;

public class PlatformConstraintStoreUpgradeTest
{
@Rule
public TargetDirectory.TestDirectory storeDir = TargetDirectory.testDirForTest( getClass() );

private FileSystemAbstraction fileSystem;
private File prepareDir;
private File workingDir;

@Before
public void setup()
{
fileSystem = new DefaultFileSystemAbstraction();
prepareDir = storeDir.directory( "prepare" );
workingDir = storeDir.directory( "working" );
}

@Test
public void shouldFailToStartIfConfiguredForCAPIDeviceTest()
public void shouldFailToStartWithCustomIOConfigurationTest() throws IOException
{
GraphDatabaseBuilder gdBuilder =
new TestGraphDatabaseFactory().newEmbeddedDatabaseBuilder( storeDir.graphDbDir() );
gdBuilder.setConfig( GraphDatabaseSettings.allow_store_upgrade, Settings.TRUE )
.setConfig( GraphDatabaseSettings.pagecache_swapper, "custom" );
prepareSampleLegacyDatabase( LowLimitV2_2.STORE_VERSION, fileSystem, workingDir, prepareDir );
try
{
gdBuilder.newGraphDatabase();
createGraphDatabaseService();
fail( "Should not have created database with custom IO configuration and Store Upgrade." );
}
catch ( RuntimeException ex )
{
// good
assertEquals( "Store upgrade not allowed with custom IO integrations", ex.getMessage() );
assertEquals( StoreUpgrader.CUSTOM_IO_EXCEPTION_MESSAGE, ex.getCause().getCause().getMessage() );
}
}

private GraphDatabaseService createGraphDatabaseService()
{
return new TestGraphDatabaseFactory().newEmbeddedDatabaseBuilder( workingDir )
.setConfig( GraphDatabaseSettings.allow_store_upgrade, "true" )
.setConfig( GraphDatabaseSettings.pagecache_swapper, "custom" ).newGraphDatabase();
}
}
Expand Up @@ -23,7 +23,6 @@

import org.neo4j.helpers.Service;
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.NeoStoreDataSource;
import org.neo4j.kernel.configuration.Config;
import org.neo4j.kernel.extension.KernelExtensionFactory;
Expand All @@ -33,13 +32,15 @@
import org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore;
import org.neo4j.kernel.impl.transaction.log.TransactionIdStore;
import org.neo4j.kernel.impl.transaction.log.checkpoint.CheckPointer;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.lifecycle.Lifecycle;
import org.neo4j.kernel.monitoring.Monitors;

@Service.Implementation(KernelExtensionFactory.class)
public class OnlineBackupExtensionFactory extends KernelExtensionFactory<OnlineBackupExtensionFactory.Dependencies>
{
static final String KEY = "online backup";
static final String CUSTOM_IO_EXCEPTION_MESSAGE = "Online Backup not allowed with custom IO integration";

public interface Dependencies
{
Expand Down Expand Up @@ -78,6 +79,11 @@ public Class<OnlineBackupSettings> getSettingsClass()
@Override
public Lifecycle newInstance( KernelContext context, Dependencies dependencies ) throws Throwable
{
if ( context.customIOConfigurationUsed( dependencies.getConfig() ) )
{
throw new IllegalArgumentException( CUSTOM_IO_EXCEPTION_MESSAGE );
}

return new OnlineBackupKernelExtension( dependencies.getConfig(), dependencies.getGraphDatabaseAPI(),
dependencies.logService().getInternalLogProvider(), dependencies.monitors(),
dependencies.neoStoreDataSource(),
Expand Down
Expand Up @@ -19,15 +19,17 @@
*/
package org.neo4j.backup;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import org.neo4j.cluster.ClusterSettings;
import org.neo4j.graphdb.factory.GraphDatabaseBuilder;
import org.neo4j.graphdb.factory.GraphDatabaseFactory;
import java.io.File;

import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.factory.GraphDatabaseSettings;
import org.neo4j.kernel.configuration.Settings;
import org.neo4j.test.TargetDirectory;
import org.neo4j.test.TestGraphDatabaseFactory;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
Expand All @@ -37,22 +39,33 @@ public class PlatformConstraintBackupTest
@Rule
public TargetDirectory.TestDirectory storeDir = TargetDirectory.testDirForTest( getClass() );

private File workingDir;

@Before
public void setup()
{
workingDir = storeDir.directory( "working" );
}

@Test
public void shouldFailToStartIfConfiguredForCAPIDeviceTest()
public void shouldFailToStartWithCustomIOConfigurationTest()
{
GraphDatabaseFactory graphDatabaseFactory = new GraphDatabaseFactory();
GraphDatabaseBuilder gdBuilder = graphDatabaseFactory.newEmbeddedDatabaseBuilder( storeDir.graphDbDir() );
gdBuilder.setConfig( OnlineBackupSettings.online_backup_enabled, Settings.TRUE )
.setConfig( GraphDatabaseSettings.pagecache_swapper, "custom" );
try
{
gdBuilder.newGraphDatabase();
fail( "Should not have created database with custom IO configuration and Online Backup." );
createGraphDatabaseService();
fail( "Should not have created database with custom IO configuration and online backup." );
}
catch ( RuntimeException ex )
{
// good
assertEquals( "Online Backup not allowed with custom IO integration", ex.getMessage() );
assertEquals( OnlineBackupExtensionFactory.CUSTOM_IO_EXCEPTION_MESSAGE,
ex.getCause().getCause().getMessage() );
}
}

private GraphDatabaseService createGraphDatabaseService()
{
return new TestGraphDatabaseFactory().newEmbeddedDatabaseBuilder( workingDir )
.setConfig( OnlineBackupSettings.online_backup_enabled, Settings.TRUE )
.setConfig( GraphDatabaseSettings.pagecache_swapper, "custom" ).newGraphDatabase();
}
}
Expand Up @@ -57,9 +57,6 @@
import org.neo4j.io.fs.FileSystemAbstraction;
import org.neo4j.io.pagecache.PageCache;
import org.neo4j.kernel.AvailabilityGuard;
import org.neo4j.kernel.impl.store.format.highlimit.HighLimit;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.internal.KernelData;
import org.neo4j.kernel.NeoStoreDataSource;
import org.neo4j.kernel.api.KernelAPI;
import org.neo4j.kernel.api.exceptions.InvalidTransactionTypeKernelException;
Expand Down Expand Up @@ -138,6 +135,7 @@
import org.neo4j.kernel.impl.locking.Locks;
import org.neo4j.kernel.impl.logging.LogService;
import org.neo4j.kernel.impl.store.StoreId;
import org.neo4j.kernel.impl.store.format.highlimit.HighLimit;
import org.neo4j.kernel.impl.store.id.IdGeneratorFactory;
import org.neo4j.kernel.impl.store.stats.IdBasedStoreEntityCounters;
import org.neo4j.kernel.impl.transaction.TransactionHeaderInformationFactory;
Expand All @@ -148,6 +146,8 @@
import org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader;
import org.neo4j.kernel.impl.util.Dependencies;
import org.neo4j.kernel.impl.util.JobScheduler;
import org.neo4j.kernel.internal.GraphDatabaseAPI;
import org.neo4j.kernel.internal.KernelData;
import org.neo4j.kernel.lifecycle.LifeSupport;
import org.neo4j.kernel.lifecycle.Lifecycle;
import org.neo4j.kernel.monitoring.ByteCounterMonitor;
Expand All @@ -166,6 +166,8 @@
public class HighlyAvailableEditionModule
extends EditionModule
{
public static final String CUSTOM_IO_EXCEPTION_MESSAGE = "HA mode not allowed with custom IO integrations";

public HighAvailabilityMemberStateMachine memberStateMachine;
public ClusterMembers members;

Expand All @@ -188,6 +190,12 @@ public HighlyAvailableEditionModule( final PlatformModule platformModule )
final LogService logging = platformModule.logging;
final Monitors monitors = platformModule.monitors;

//Temporary check for custom IO
if ( customIOConfigurationUsed( platformModule.config ) )
{
throw new IllegalArgumentException( CUSTOM_IO_EXCEPTION_MESSAGE );
}

// Set Netty logger
InternalLoggerFactory.setDefaultFactory( new NettyLoggerFactory( logging.getInternalLogProvider() ) );

Expand Down Expand Up @@ -512,6 +520,12 @@ public void elected( String role, InstanceId instanceId, URI electedMember )
life.add( paxosLife );
}

private boolean customIOConfigurationUsed( Config config )
{
return config.get( GraphDatabaseSettings.pagecache_swapper ) != null;
}


private void publishServerId( Config config, UsageData sysInfo )
{
sysInfo.set( UsageDataKeys.serverId, config.get( ClusterSettings.server_id ).toString() );
Expand Down

0 comments on commit 1757945

Please sign in to comment.