From 66c1408a81bc38d78c28fc1470ffeb02b7d2aafc Mon Sep 17 00:00:00 2001 From: MishaDemianenko Date: Tue, 16 May 2017 17:37:49 +0200 Subject: [PATCH] Force count store rebuild during store migration Count store version was incremented but there was no migration added and as result first DB after start will fail to open old count stores and will rebuild it. That way of doing count store migration is incorrect and produce unexpected exceptions that confuse users. --- .../participant/StoreMigrator.java | 17 +++++++-- .../participant/StoreMigratorTest.java | 36 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java index 0cd5cf36bdd17..ce42153ebb10e 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java @@ -67,12 +67,15 @@ import org.neo4j.kernel.impl.store.format.CapabilityType; import org.neo4j.kernel.impl.store.format.FormatFamily; import org.neo4j.kernel.impl.store.format.RecordFormats; +import org.neo4j.kernel.impl.store.format.StoreVersion; import org.neo4j.kernel.impl.store.format.standard.MetaDataRecordFormat; import org.neo4j.kernel.impl.store.format.standard.NodeRecordFormat; import org.neo4j.kernel.impl.store.format.standard.RelationshipRecordFormat; import org.neo4j.kernel.impl.store.format.standard.StandardV2_0; import org.neo4j.kernel.impl.store.format.standard.StandardV2_1; import org.neo4j.kernel.impl.store.format.standard.StandardV2_2; +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.id.ReadOnlyIdGeneratorFactory; import org.neo4j.kernel.impl.store.record.NodeRecord; import org.neo4j.kernel.impl.store.record.PrimitiveRecord; @@ -766,8 +769,7 @@ public void moveMigratedFiles( File migrationDir, File storeDir, String versionT public void rebuildCounts( File storeDir, String versionToMigrateFrom, String versionToMigrateTo ) throws IOException { - if ( StandardV2_1.STORE_VERSION.equals( versionToMigrateFrom ) || - StandardV2_2.STORE_VERSION.equals( versionToMigrateFrom ) ) + if ( countStoreRebuildRequired( versionToMigrateFrom ) ) { // create counters from scratch Iterable countsStoreFiles = @@ -780,6 +782,17 @@ public void rebuildCounts( File storeDir, String versionToMigrateFrom, String ve } } + boolean countStoreRebuildRequired( String versionToMigrateFrom ) + { + return StandardV2_1.STORE_VERSION.equals( versionToMigrateFrom ) || + StandardV2_2.STORE_VERSION.equals( versionToMigrateFrom ) || + StandardV2_3.STORE_VERSION.equals( versionToMigrateFrom ) || + StandardV3_0.STORE_VERSION.equals( versionToMigrateFrom ) || + StoreVersion.HIGH_LIMIT_V3_0_0.versionString().equals( versionToMigrateFrom ) || + StoreVersion.HIGH_LIMIT_V3_0_6.versionString().equals( versionToMigrateFrom ) || + StoreVersion.HIGH_LIMIT_V3_1_0.versionString().equals( versionToMigrateFrom ); + } + private void updateOrAddNeoStoreFieldsAsPartOfMigration( File migrationDir, File storeDir, String versionToMigrateTo, LogPosition lastClosedTxLogPosition ) throws IOException { diff --git a/enterprise/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java b/enterprise/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java index a3c871995866f..3153bb88f90d5 100644 --- a/enterprise/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java +++ b/enterprise/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java @@ -23,13 +23,16 @@ import org.junit.Test; import java.io.File; +import java.io.IOException; import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.DefaultFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; import org.neo4j.io.pagecache.tracing.cursor.PageCursorTracerSupplier; +import org.neo4j.kernel.api.index.SchemaIndexProvider; import org.neo4j.kernel.configuration.Config; +import org.neo4j.kernel.impl.logging.LogService; import org.neo4j.kernel.impl.logging.NullLogService; import org.neo4j.kernel.impl.pagecache.ConfiguringPageCacheFactory; import org.neo4j.kernel.impl.store.format.StoreVersion; @@ -41,6 +44,7 @@ import org.neo4j.test.TestGraphDatabaseFactory; import org.neo4j.test.rule.TestDirectory; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -92,4 +96,36 @@ public void shouldNotDoActualStoreMigrationBetween3_0_5_and_next() throws Except verifyNoMoreInteractions( monitor ); } } + + @Test + public void detectObsoleteCountStoresToRebuildDuringMigration() throws IOException + { + TestStoreMigrator storeMigrator = new TestStoreMigrator( new DefaultFileSystemAbstraction(), + mock( PageCache.class ), Config.empty(), NullLogService.getInstance(), mock( SchemaIndexProvider.class ) ); + assertTrue( storeMigrator.countStoreRebuildRequired( StoreVersion.STANDARD_V2_1.versionString() ) ); + assertTrue( storeMigrator.countStoreRebuildRequired( StoreVersion.STANDARD_V2_2.versionString() ) ); + assertTrue( storeMigrator.countStoreRebuildRequired( StoreVersion.STANDARD_V2_3.versionString() ) ); + assertTrue( storeMigrator.countStoreRebuildRequired( StoreVersion.STANDARD_V3_0.versionString() ) ); + assertFalse( storeMigrator.countStoreRebuildRequired( StoreVersion.STANDARD_V3_2.versionString() ) ); + assertTrue( storeMigrator.countStoreRebuildRequired( StoreVersion.HIGH_LIMIT_V3_0_0.versionString() ) ); + assertTrue( storeMigrator.countStoreRebuildRequired( StoreVersion.HIGH_LIMIT_V3_0_6.versionString() ) ); + assertTrue( storeMigrator.countStoreRebuildRequired( StoreVersion.HIGH_LIMIT_V3_1_0.versionString() ) ); + assertFalse( storeMigrator.countStoreRebuildRequired( StoreVersion.HIGH_LIMIT_V3_2_0.versionString() ) ); + } + + private class TestStoreMigrator extends StoreMigrator + { + + TestStoreMigrator( FileSystemAbstraction fileSystem, PageCache pageCache, Config config, LogService logService, + SchemaIndexProvider schemaIndexProvider ) + { + super( fileSystem, pageCache, config, logService, schemaIndexProvider ); + } + + @Override + public boolean countStoreRebuildRequired( String versionToMigrateFrom ) + { + return super.countStoreRebuildRequired( versionToMigrateFrom ); + } + } }