Skip to content

Commit

Permalink
Split UnexpectedVersion exception in two
Browse files Browse the repository at this point in the history
This exception was previously thrown in two cases:

1. When a store could not be opened because it had a version different
from the one neo4j was expecting (tools like ConsistencyChecker would
run into this)
2. Trying to upgrade a store with an unknown version (in many cases,
when users are unwittingly trying to downgrade a store)

This split those two separate use-cases in two, and throws distinct
exceptions in each case.

Before, this was printed

```
/home/jonas/workspace/neo4j/community/kernel/target/test-data/org.neo4j.kernel.impl.storemigration.UpgradableDatabaseTest$UnsupportedVersions/E1F262ADB34943A5536165FFEF6AEC90/graph-db/neostore' has a store version 'v0.A.8' that we cannot upgrade from
```

After, this is printed instead

```
Not possible to upgrade a store with version 'v0.A.8' to current store version `v.0.A.7` (Neo4j 3.0.7).
```

This message is thrown when the version is unknown, e.g. it is
jibberish (not sure if that would ever happen), or more likely, it's a
version that is part of a later version of Neo4j which this version has
no knowledge of. Printing the current version (as well as Neo4j version)
makes it as clear as is possible, that he has screwed up his database versions.
  • Loading branch information
spacecowboy committed Sep 28, 2016
1 parent 2551dc9 commit cf006dd
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 25 deletions.
Expand Up @@ -47,7 +47,6 @@
import org.neo4j.kernel.impl.store.kvstore.DataInitializer; import org.neo4j.kernel.impl.store.kvstore.DataInitializer;
import org.neo4j.kernel.impl.store.record.AbstractBaseRecord; import org.neo4j.kernel.impl.store.record.AbstractBaseRecord;
import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord;
import org.neo4j.kernel.impl.storemigration.StoreUpgrader;
import org.neo4j.kernel.info.DiagnosticsManager; import org.neo4j.kernel.info.DiagnosticsManager;
import org.neo4j.logging.Log; import org.neo4j.logging.Log;
import org.neo4j.logging.LogProvider; import org.neo4j.logging.LogProvider;
Expand Down Expand Up @@ -172,8 +171,7 @@ private void verifyRecordFormat()
String actualStoreVersion = versionLongToString( getRecord( pageCache, neoStoreFileName, STORE_VERSION ) ); String actualStoreVersion = versionLongToString( getRecord( pageCache, neoStoreFileName, STORE_VERSION ) );
if ( !expectedStoreVersion.equals( actualStoreVersion ) ) if ( !expectedStoreVersion.equals( actualStoreVersion ) )
{ {
throw new StoreUpgrader.UnexpectedUpgradingStoreVersionException( neoStoreFileName.getName(), throw new UnexpectedStoreVersionException( actualStoreVersion, expectedStoreVersion );
actualStoreVersion );
} }
} }
catch ( NoSuchFileException e ) catch ( NoSuchFileException e )
Expand Down
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.kernel.impl.store;

public class UnexpectedStoreVersionException extends StoreFailureException
{
private static final String MESSAGE = "Unable to open store with version '%s', expected store version '%s'.";

public UnexpectedStoreVersionException( String actualStoreVersion, String expectedStoreVersion )
{
super( String.format( MESSAGE, actualStoreVersion, expectedStoreVersion ) );
}
}
Expand Up @@ -33,6 +33,7 @@
import org.neo4j.kernel.impl.storemigration.monitoring.MigrationProgressMonitor; import org.neo4j.kernel.impl.storemigration.monitoring.MigrationProgressMonitor;
import org.neo4j.kernel.impl.storemigration.monitoring.MigrationProgressMonitor.Section; import org.neo4j.kernel.impl.storemigration.monitoring.MigrationProgressMonitor.Section;
import org.neo4j.kernel.impl.util.CustomIOConfigValidator; import org.neo4j.kernel.impl.util.CustomIOConfigValidator;
import org.neo4j.kernel.internal.Version;
import org.neo4j.logging.Log; import org.neo4j.logging.Log;
import org.neo4j.logging.LogProvider; import org.neo4j.logging.LogProvider;


Expand Down Expand Up @@ -318,11 +319,22 @@ public UpgradingStoreVersionNotFoundException( String filenameWithoutStoreVersio


public static class UnexpectedUpgradingStoreVersionException extends UnableToUpgradeException public static class UnexpectedUpgradingStoreVersionException extends UnableToUpgradeException
{ {
protected static final String MESSAGE = "'%s' has a store version '%s' that we cannot upgrade from."; protected static final String MESSAGE =
"Not possible to upgrade a store with version '%s' to current store version `%s` (Neo4j %s).";

public UnexpectedUpgradingStoreVersionException( String fileVersion, String currentVersion )
{
super( String.format( MESSAGE, fileVersion, currentVersion, Version.getNeo4jVersion() ) );
}
}

public static class AttemptedDowngradeException extends UnableToUpgradeException
{
protected static final String MESSAGE = "Downgrading stores are not supported.";


public UnexpectedUpgradingStoreVersionException( String filename, String actualVersion ) public AttemptedDowngradeException()
{ {
super( String.format( MESSAGE, filename, actualVersion ) ); super( MESSAGE );
} }
} }


Expand Down
Expand Up @@ -60,7 +60,7 @@ record = MetaDataStore.getRecord( pageCache, neostoreFile, STORE_VERSION );
String storeVersion = MetaDataStore.versionLongToString( record ); String storeVersion = MetaDataStore.versionLongToString( record );
if ( !expectedVersion.equals( storeVersion ) ) if ( !expectedVersion.equals( storeVersion ) )
{ {
return new Result( Outcome.unexpectedUpgradingStoreVersion, storeVersion, neostoreFile.getName() ); return new Result( Outcome.unexpectedStoreVersion, storeVersion, neostoreFile.getName() );
} }


return new Result( Outcome.ok, null, neostoreFile.getName() ); return new Result( Outcome.ok, null, neostoreFile.getName() );
Expand All @@ -84,7 +84,8 @@ public enum Outcome
ok( true ), ok( true ),
missingStoreFile( false ), missingStoreFile( false ),
storeVersionNotFound( false ), storeVersionNotFound( false ),
unexpectedUpgradingStoreVersion( false ), unexpectedStoreVersion( false ),
attemptedStoreDowngrade( false ),
storeNotCleanlyShutDown( false ); storeNotCleanlyShutDown( false );


private final boolean success; private final boolean success;
Expand Down
Expand Up @@ -103,7 +103,7 @@ public RecordFormats checkUpgradeable( File storeDirectory )
if ( fromFormat.generation() > format.generation() ) if ( fromFormat.generation() > format.generation() )
{ {
// Tried to downgrade, that isn't supported // Tried to downgrade, that isn't supported
result = new Result( Outcome.unexpectedUpgradingStoreVersion, fromFormat.storeVersion(), result = new Result( Outcome.attemptedStoreDowngrade, fromFormat.storeVersion(),
new File( storeDirectory, MetaDataStore.DEFAULT_NAME ).getAbsolutePath() ); new File( storeDirectory, MetaDataStore.DEFAULT_NAME ).getAbsolutePath() );
} }
else else
Expand All @@ -119,7 +119,7 @@ public RecordFormats checkUpgradeable( File storeDirectory )
} }
catch ( IllegalArgumentException e ) catch ( IllegalArgumentException e )
{ {
result = new Result( Outcome.unexpectedUpgradingStoreVersion, result.actualVersion, result.storeFilename ); result = new Result( Outcome.unexpectedStoreVersion, result.actualVersion, result.storeFilename );
} }


switch ( result.outcome ) switch ( result.outcome )
Expand All @@ -129,9 +129,10 @@ public RecordFormats checkUpgradeable( File storeDirectory )
case storeVersionNotFound: case storeVersionNotFound:
throw new StoreUpgrader.UpgradingStoreVersionNotFoundException( throw new StoreUpgrader.UpgradingStoreVersionNotFoundException(
getPathToStoreFile( storeDirectory, result ) ); getPathToStoreFile( storeDirectory, result ) );
case unexpectedUpgradingStoreVersion: case attemptedStoreDowngrade:
throw new StoreUpgrader.UnexpectedUpgradingStoreVersionException( throw new StoreUpgrader.AttemptedDowngradeException();
getPathToStoreFile( storeDirectory, result ), result.actualVersion ); case unexpectedStoreVersion:
throw new StoreUpgrader.UnexpectedUpgradingStoreVersionException( result.actualVersion, format.storeVersion() );
case storeNotCleanlyShutDown: case storeNotCleanlyShutDown:
throw new StoreUpgrader.DatabaseNotCleanlyShutDownException(); throw new StoreUpgrader.DatabaseNotCleanlyShutDownException();
default: default:
Expand Down Expand Up @@ -193,7 +194,8 @@ public boolean hasCurrentVersion( File storeDir )
case missingStoreFile: // let's assume the db is empty case missingStoreFile: // let's assume the db is empty
return true; return true;
case storeVersionNotFound: case storeVersionNotFound:
case unexpectedUpgradingStoreVersion: case unexpectedStoreVersion:
case attemptedStoreDowngrade:
return false; return false;
default: default:
throw new IllegalArgumentException( "Unknown outcome: " + result.outcome.name() ); throw new IllegalArgumentException( "Unknown outcome: " + result.outcome.name() );
Expand Down
Expand Up @@ -64,7 +64,7 @@ public Result hasVersion( File storeFile, String expectedVersion, boolean option
String actualVersion = readVersion( fileChannel, expectedVersionBytes.length ); String actualVersion = readVersion( fileChannel, expectedVersionBytes.length );
if ( !expectedVersion.equals( actualVersion ) ) if ( !expectedVersion.equals( actualVersion ) )
{ {
return new Result( Outcome.unexpectedUpgradingStoreVersion, actualVersion, storeFilename ); return new Result( Outcome.unexpectedStoreVersion, actualVersion, storeFilename );
} }
} }
catch ( IOException e ) catch ( IOException e )
Expand Down
Expand Up @@ -222,7 +222,7 @@ public static boolean allStoreFilesHaveNoTrailer( FileSystemAbstraction fs, File
File file = new File( dir, storeFile.storeFileName() ); File file = new File( dir, storeFile.storeFileName() );
StoreVersionCheck.Result result = StoreVersionCheck.Result result =
legacyStoreVersionCheck.hasVersion( file, StandardV3_0.STORE_VERSION, storeFile.isOptional() ); legacyStoreVersionCheck.hasVersion( file, StandardV3_0.STORE_VERSION, storeFile.isOptional() );
success &= result.outcome == Outcome.unexpectedUpgradingStoreVersion || success &= result.outcome == Outcome.unexpectedStoreVersion ||
result.outcome == Outcome.storeVersionNotFound; result.outcome == Outcome.storeVersionNotFound;
} }
return success; return success;
Expand Down
Expand Up @@ -96,7 +96,7 @@ public void shouldReportFileWithIncorrectVersion() throws IOException


// then // then
assertFalse( result.outcome.isSuccessful() ); assertFalse( result.outcome.isSuccessful() );
assertEquals( StoreVersionCheck.Result.Outcome.unexpectedUpgradingStoreVersion, result.outcome ); assertEquals( StoreVersionCheck.Result.Outcome.unexpectedStoreVersion, result.outcome );
assertEquals( "V1", result.actualVersion ); assertEquals( "V1", result.actualVersion );
} }


Expand Down
Expand Up @@ -44,6 +44,7 @@
import org.neo4j.kernel.impl.store.format.standard.StandardV2_3; import org.neo4j.kernel.impl.store.format.standard.StandardV2_3;
import org.neo4j.kernel.impl.store.format.standard.StandardV3_0; import org.neo4j.kernel.impl.store.format.standard.StandardV3_0;
import org.neo4j.kernel.impl.storemigration.legacystore.LegacyStoreVersionCheck; import org.neo4j.kernel.impl.storemigration.legacystore.LegacyStoreVersionCheck;
import org.neo4j.kernel.internal.Version;
import org.neo4j.string.UTF8; import org.neo4j.string.UTF8;
import org.neo4j.test.PageCacheRule; import org.neo4j.test.PageCacheRule;
import org.neo4j.test.TargetDirectory; import org.neo4j.test.TargetDirectory;
Expand Down Expand Up @@ -261,8 +262,8 @@ public void shouldCommunicateWhatCausesInabilityToUpgrade()
{ {
// then // then
assertFalse( StoreVersion.isEnterpriseStoreVersion( version ) ); assertFalse( StoreVersion.isEnterpriseStoreVersion( version ) );
File expectedFile = new File( workingDirectory, neostoreFilename ).getAbsoluteFile(); assertEquals( String.format( MESSAGE, version, upgradableDatabase.currentVersion(),
assertEquals( String.format( MESSAGE, expectedFile, version ), e.getMessage() ); Version.getNeo4jVersion() ), e.getMessage() );
} }
catch ( StoreUpgrader.UnexpectedUpgradingStoreFormatException e ) catch ( StoreUpgrader.UnexpectedUpgradingStoreFormatException e )
{ {
Expand Down
4 changes: 0 additions & 4 deletions community/neo4j/src/test/java/db/DatabaseStartupTest.java
Expand Up @@ -37,9 +37,7 @@
import org.neo4j.test.TargetDirectory; import org.neo4j.test.TargetDirectory;
import org.neo4j.test.TestGraphDatabaseFactory; import org.neo4j.test.TestGraphDatabaseFactory;


import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;


Expand Down Expand Up @@ -120,8 +118,6 @@ public void startTheDatabaseWithWrongVersionShouldFailAlsoWhenUpgradeIsAllowed()
// then // then
assertTrue( ex.getCause() instanceof LifecycleException ); assertTrue( ex.getCause() instanceof LifecycleException );
assertTrue( ex.getCause().getCause() instanceof StoreUpgrader.UnexpectedUpgradingStoreVersionException ); assertTrue( ex.getCause().getCause() instanceof StoreUpgrader.UnexpectedUpgradingStoreVersionException );
assertThat( ex.getCause().getCause().getMessage(),
containsString( "has a store version '" + badStoreVersion + "' that we cannot upgrade from." ) );
} }
} }
} }
Expand Up @@ -26,6 +26,7 @@
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;


import org.neo4j.kernel.internal.Version;
import org.neo4j.shell.Session; import org.neo4j.shell.Session;
import org.neo4j.shell.ShellException; import org.neo4j.shell.ShellException;
import org.neo4j.shell.ShellServer; import org.neo4j.shell.ShellServer;
Expand Down
Expand Up @@ -61,7 +61,6 @@
import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge; import org.neo4j.kernel.impl.core.ThreadToStatementContextBridge;
import org.neo4j.kernel.impl.ha.ClusterManager; import org.neo4j.kernel.impl.ha.ClusterManager;
import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine; import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageEngine;
import org.neo4j.kernel.impl.store.MetaDataStore;
import org.neo4j.kernel.impl.store.format.highlimit.HighLimit; import org.neo4j.kernel.impl.store.format.highlimit.HighLimit;
import org.neo4j.kernel.impl.store.format.standard.StandardV3_0; import org.neo4j.kernel.impl.store.format.standard.StandardV3_0;
import org.neo4j.kernel.impl.storemigration.StoreUpgrader; import org.neo4j.kernel.impl.storemigration.StoreUpgrader;
Expand Down Expand Up @@ -332,7 +331,7 @@ public void migrationShouldFail() throws Throwable
{ {
assertTrue( ex.getCause() instanceof LifecycleException ); assertTrue( ex.getCause() instanceof LifecycleException );
Throwable realException = ex.getCause().getCause(); Throwable realException = ex.getCause().getCause();
assertTrue( Exceptions.contains( realException, MetaDataStore.DEFAULT_NAME, assertTrue( "Unexpected exception", Exceptions.contains( realException,
StoreUpgrader.UnexpectedUpgradingStoreVersionException.class ) ); StoreUpgrader.UnexpectedUpgradingStoreVersionException.class ) );
} }
} }
Expand Down

0 comments on commit cf006dd

Please sign in to comment.