use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class RecoveryIT method recoverySetsCheckpointLogVersionFieldSeveralCheckpointFiles.
@Test
void recoverySetsCheckpointLogVersionFieldSeveralCheckpointFiles() throws Exception {
GraphDatabaseAPI db = createDatabase();
generateSomeData(db);
var checkpointFile = db.getDependencyResolver().resolveDependency(LogFiles.class).getCheckpointFile();
var appender = (DetachedCheckpointAppender) checkpointFile.getCheckpointAppender();
appender.rotate();
appender.checkPoint(LogCheckPointEvent.NULL, new LogPosition(0, BASE_TX_LOG_BYTE_OFFSET), Instant.now(), "test1");
appender.rotate();
appender.checkPoint(LogCheckPointEvent.NULL, new LogPosition(0, BASE_TX_LOG_BYTE_OFFSET), Instant.now(), "test2");
appender.rotate();
appender.checkPoint(LogCheckPointEvent.NULL, new LogPosition(0, BASE_TX_LOG_BYTE_OFFSET), Instant.now(), "test3");
DatabaseLayout layout = db.databaseLayout();
managementService.shutdown();
removeFileWithCheckpoint();
assertTrue(isRecoveryRequired(layout));
MetaDataStore.setRecord(pageCache, layout.metadataStore(), CHECKPOINT_LOG_VERSION, -5, layout.getDatabaseName(), NULL);
recoverDatabase();
assertFalse(isRecoveryRequired(layout));
assertEquals(2, MetaDataStore.getRecord(pageCache, layout.metadataStore(), CHECKPOINT_LOG_VERSION, layout.getDatabaseName(), NULL));
}
use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class RecoveryIT method keepCheckpointVersionOnMissingLogFilesWhenValueIsReasonable.
@Test
void keepCheckpointVersionOnMissingLogFilesWhenValueIsReasonable() throws Exception {
GraphDatabaseAPI db = createDatabase();
generateSomeData(db);
DatabaseLayout layout = db.databaseLayout();
managementService.shutdown();
removeTransactionLogs();
assertTrue(isRecoveryRequired(layout));
MetaDataStore.setRecord(pageCache, layout.metadataStore(), CHECKPOINT_LOG_VERSION, 18, layout.getDatabaseName(), NULL);
recoverDatabase();
assertFalse(isRecoveryRequired(layout));
assertEquals(18, MetaDataStore.getRecord(pageCache, layout.metadataStore(), CHECKPOINT_LOG_VERSION, layout.getDatabaseName(), NULL));
}
use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class RecoveryIT method failToStartDatabaseWithTransactionLogsInLegacyLocation.
@Test
void failToStartDatabaseWithTransactionLogsInLegacyLocation() throws Exception {
GraphDatabaseAPI database = createDatabase();
generateSomeData(database);
managementService.shutdown();
LogFiles logFiles = buildLogFiles();
Path[] txLogFiles = fileSystem.listFiles(logFiles.logFilesDirectory(), path -> path.getFileName().toString().startsWith(DEFAULT_NAME));
txLogFiles = ArrayUtil.concat(txLogFiles, logFiles.getCheckpointFile().getDetachedCheckpointFiles());
Path databasesDirectory = databaseLayout.getNeo4jLayout().databasesDirectory();
DatabaseLayout legacyLayout = Neo4jLayout.ofFlat(databasesDirectory).databaseLayout(databaseLayout.getDatabaseName());
LegacyTransactionLogsLocator logsLocator = new LegacyTransactionLogsLocator(Config.defaults(), legacyLayout);
Path transactionLogsDirectory = logsLocator.getTransactionLogsDirectory();
assertNotNull(txLogFiles);
assertTrue(txLogFiles.length > 0);
for (Path logFile : txLogFiles) {
fileSystem.moveToDirectory(logFile, transactionLogsDirectory);
}
AssertableLogProvider logProvider = new AssertableLogProvider();
builder.setInternalLogProvider(logProvider);
GraphDatabaseAPI restartedDb = createDatabase();
try {
DatabaseStateService dbStateService = restartedDb.getDependencyResolver().resolveDependency(DatabaseStateService.class);
var failure = dbStateService.causeOfFailure(restartedDb.databaseId());
assertTrue(failure.isPresent());
assertThat(failure.get()).hasRootCauseMessage("Transaction logs are missing and recovery is not possible.");
assertThat(logProvider.serialize()).contains(txLogFiles[0].getFileName().toString());
} finally {
managementService.shutdown();
}
}
use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class RecoveryWithTokenIndexesIT method recoverDatabaseWithTokenIndexes.
@ParameterizedTest(name = "{0}")
@MethodSource("arguments")
void recoverDatabaseWithTokenIndexes(String name, boolean checkpointIndexes) throws Throwable {
config = Config.newBuilder().set(neo4j_home, testDirectory.homePath()).build();
EphemeralFileSystemAbstraction fs = new EphemeralFileSystemAbstraction();
GraphDatabaseService db = startDatabase(fs);
IndexingTestUtil.assertOnlyDefaultTokenIndexesExists(db);
if (checkpointIndexes) {
// Checkpoint to not make index creation part of the recovery.
checkPoint(db);
}
int numberOfEntities = 10;
for (int i = 0; i < numberOfEntities; i++) {
createEntities(db);
}
// Don't flush/checkpoint before taking the snapshot, to make the indexes need to recover (clean crash generation)
EphemeralFileSystemAbstraction crashedFs = fs.snapshot();
managementService.shutdown();
fs.close();
try (PageCache cache = pageCacheExtension.getPageCache(crashedFs)) {
DatabaseLayout layout = DatabaseLayout.of(config);
recoverDatabase(layout, crashedFs, cache);
}
db = startDatabase(crashedFs);
// Verify that the default token indexes still exist
IndexingTestUtil.assertOnlyDefaultTokenIndexesExists(db);
awaitIndexesOnline(db);
try (Transaction tx = db.beginTx()) {
assertEquals(numberOfEntities, tx.findNodes(label).stream().count());
assertEquals(numberOfEntities, tx.findRelationships(type).stream().count());
}
}
use of org.neo4j.io.layout.DatabaseLayout in project neo4j by neo4j.
the class RecoveryWithTokenIndexesIT method recoverDatabaseWithInjectedTokenIndex.
@Test
void recoverDatabaseWithInjectedTokenIndex() throws Throwable {
// Starting an existing database on 4.3 or newer binaries should make the old label scan store
// into a token index - but there is no schema rule for it in store until after upgrade transaction has been run
// (there is just an injected indexRule in the cache).
// This tests that recovery on a database with the injected version of the NLI keeps it through recovery.
config = Config.newBuilder().set(allow_single_automatic_upgrade, false).set(allow_upgrade, true).build();
// Database with 10 nodes with label 'label' and 10 relationships with type 'type'.
int numberOfEntities = 10;
GraphDatabaseService database = createDatabaseOfOlderVersion("4-2-data-10-nodes-rels.zip");
DatabaseLayout layout = ((GraphDatabaseAPI) database).databaseLayout();
verifyInjectedNLIExistAndOnline(database);
managementService.shutdown();
// Remove check point from shutdown, store upgrade, and shutdown done when creating the 4.2 store.
RecoveryHelpers.removeLastCheckpointRecordFromLastLogFile(layout, fileSystem);
RecoveryHelpers.removeLastCheckpointRecordFromLastLogFile(layout, fileSystem);
RecoveryHelpers.removeLastCheckpointRecordFromLastLogFile(layout, fileSystem);
try (PageCache pageCache = pageCacheExtension.getPageCache(fileSystem)) {
recoverDatabaseOfOlderVersion(layout, pageCache);
}
GraphDatabaseService recoveredDatabase = startDatabaseOfOlderVersion();
// Verify that the injected NLI still exist
verifyInjectedNLIExistAndOnline(recoveredDatabase);
try (Transaction tx = recoveredDatabase.beginTx()) {
assertEquals(numberOfEntities, tx.findNodes(label).stream().count());
assertEquals(numberOfEntities, tx.findRelationships(type).stream().count());
}
}
Aggregations