use of org.neo4j.dbms.api.DatabaseManagementService in project neo4j by neo4j.
the class DatabaseRecoveryIT method shouldSeeTheSameRecordsAtCheckpointAsAfterReverseRecovery.
@Test
void shouldSeeTheSameRecordsAtCheckpointAsAfterReverseRecovery() throws Exception {
// given
EphemeralFileSystemAbstraction fs = new EphemeralFileSystemAbstraction();
managementService = new TestDatabaseManagementServiceBuilder(directory.homePath()).setFileSystem(fs).impermanent().build();
GraphDatabaseService db = managementService.database(DEFAULT_DATABASE_NAME);
produceRandomGraphUpdates(db, 100);
checkPoint(db);
EphemeralFileSystemAbstraction checkPointFs = fs.snapshot();
// when
produceRandomGraphUpdates(db, 100);
flush(db);
EphemeralFileSystemAbstraction crashedFs = fs.snapshot();
managementService.shutdown();
fs.close();
Dependencies dependencies = new Dependencies();
Monitors monitors;
AtomicReference<EphemeralFileSystemAbstraction> reversedFs;
try (PageCache pageCache = pageCacheExtension.getPageCache(crashedFs)) {
dependencies.satisfyDependencies(pageCache);
monitors = new Monitors();
reversedFs = new AtomicReference<>();
monitors.addMonitorListener(new RecoveryMonitor() {
@Override
public void reverseStoreRecoveryCompleted(long checkpointTxId) {
try {
// Flush the page cache which will fished out of the GlobalModule at the point of constructing the database
pageCache.flushAndForce();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
// The stores should now be equal in content to the db as it was right after the checkpoint.
// Grab a snapshot so that we can compare later.
reversedFs.set(crashedFs.snapshot());
}
});
DatabaseManagementService managementService = new TestDatabaseManagementServiceBuilder(directory.homePath()).setFileSystem(crashedFs).setExternalDependencies(dependencies).setMonitors(monitors).impermanent().build();
managementService.shutdown();
}
// then
fs.close();
try {
// Here we verify that the neostore contents, record by record are exactly the same when comparing
// the store as it was right after the checkpoint with the store as it was right after reverse recovery completed.
assertSameStoreContents(checkPointFs, reversedFs.get(), databaseLayout);
} finally {
IOUtils.closeAll(checkPointFs, reversedFs.get());
}
}
use of org.neo4j.dbms.api.DatabaseManagementService in project neo4j by neo4j.
the class DatabaseRecoveryIT method reportProgressOnRecovery.
@Test
void reportProgressOnRecovery() throws IOException {
GraphDatabaseService database = startDatabase(directory.homePath());
for (int i = 0; i < 10; i++) {
try (Transaction transaction = database.beginTx()) {
transaction.createNode();
transaction.commit();
}
}
var restoreDbLayout = copyStore();
DatabaseManagementService recoveredService = getManagementService(restoreDbLayout.getNeo4jLayout().homeDirectory());
GraphDatabaseService recoveredDatabase = recoveredService.database(DEFAULT_DATABASE_NAME);
try (Transaction tx = recoveredDatabase.beginTx()) {
assertEquals(10, count(tx.getAllNodes()));
}
assertThat(logProvider).containsMessages("10% completed", "100% completed");
recoveredService.shutdown();
}
use of org.neo4j.dbms.api.DatabaseManagementService in project neo4j by neo4j.
the class DatabaseRecoveryIT method recoveryShouldFixPartiallyAppliedSchemaIndexUpdates.
@Test
void recoveryShouldFixPartiallyAppliedSchemaIndexUpdates() {
Label label = Label.label("Foo");
String property = "Bar";
// cause failure during 'relationship.delete()' command application
ClassGuardedAdversary adversary = new ClassGuardedAdversary(new CountingAdversary(1, true), Command.RelationshipCommand.class);
adversary.disable();
Path storeDir = directory.homePath();
DatabaseManagementService managementService = AdversarialPageCacheGraphDatabaseFactory.create(storeDir, fileSystem, adversary).build();
GraphDatabaseService db = managementService.database(DEFAULT_DATABASE_NAME);
try {
try (Transaction tx = db.beginTx()) {
tx.schema().constraintFor(label).assertPropertyIsUnique(property).create();
tx.commit();
}
long relationshipId = createRelationship(db);
TransactionFailureException txFailure = null;
try (Transaction tx = db.beginTx()) {
Node node = tx.createNode(label);
node.setProperty(property, "B");
// this should fail because of the adversary
tx.getRelationshipById(relationshipId).delete();
adversary.enable();
tx.commit();
} catch (TransactionFailureException e) {
txFailure = e;
}
assertNotNull(txFailure);
adversary.disable();
// heal the db so it is possible to inspect the data
healthOf(db).healed();
// now we can observe partially committed state: node is in the index and relationship still present
try (Transaction tx = db.beginTx()) {
assertNotNull(findNode(label, property, "B", tx));
assertNotNull(tx.getRelationshipById(relationshipId));
tx.commit();
}
// panic the db again to force recovery on the next startup
healthOf(db).panic(txFailure.getCause());
// restart the database, now with regular page cache
managementService.shutdown();
db = startDatabase(storeDir);
// now we observe correct state: node is in the index and relationship is removed
try (Transaction tx = db.beginTx()) {
assertNotNull(findNode(label, property, "B", tx));
assertRelationshipNotExist(tx, relationshipId);
tx.commit();
}
} finally {
managementService.shutdown();
}
}
use of org.neo4j.dbms.api.DatabaseManagementService in project neo4j by neo4j.
the class RecoveryCorruptedTransactionLogIT method startWithoutProblemsIfRotationForcedBeforeFileEnd.
@Test
void startWithoutProblemsIfRotationForcedBeforeFileEnd() throws IOException {
DatabaseManagementService managementService = databaseFactory.build();
GraphDatabaseAPI database = (GraphDatabaseAPI) managementService.database(DEFAULT_DATABASE_NAME);
logFiles = buildDefaultLogFiles(getStoreId(database));
generateTransaction(database);
managementService.shutdown();
try (Lifespan lifespan = new Lifespan(logFiles)) {
Path originalFile = logFiles.getLogFile().getHighestLogFile();
// in it its current position.
try (StoreFileChannel writeChannel = fileSystem.write(originalFile)) {
writeChannel.position(writeChannel.size());
for (int i = 0; i < 10; i++) {
writeChannel.writeAll(ByteBuffer.wrap(new byte[] { 0, 0, 0, 0, 0 }));
}
}
logFiles.getLogFile().rotate();
}
startStopDatabase();
assertThat(logProvider).doesNotContainMessage("Fail to read transaction log version 0.");
}
use of org.neo4j.dbms.api.DatabaseManagementService in project neo4j by neo4j.
the class RecoveryCorruptedTransactionLogIT method recoverNotAFirstCorruptedTransactionMultipleFilesMultipleCheckpoints.
@ParameterizedTest(name = "[{index}] ({0})")
@MethodSource("corruptedLogEntryWriters")
void recoverNotAFirstCorruptedTransactionMultipleFilesMultipleCheckpoints(String testName, LogEntryWriterWrapper logEntryWriterWrapper) throws IOException {
DatabaseManagementService managementService = databaseFactory.build();
GraphDatabaseAPI database = (GraphDatabaseAPI) managementService.database(DEFAULT_DATABASE_NAME);
logFiles = buildDefaultLogFiles(getStoreId(database));
long transactionsToRecover = 7;
generateTransactionsAndRotateWithCheckpoint(database, 3);
for (int i = 0; i < transactionsToRecover; i++) {
generateTransaction(database);
}
managementService.shutdown();
Path highestLogFile = logFiles.getLogFile().getHighestLogFile();
long originalFileLength = getLastReadablePosition(highestLogFile).getByteOffset();
removeLastCheckpointRecordFromLastLogFile();
addCorruptedCommandsToLastLogFile(logEntryWriterWrapper);
long modifiedFileLength = fileSystem.getFileSize(highestLogFile);
assertThat(modifiedFileLength).isGreaterThan(originalFileLength);
startStopDbRecoveryOfCorruptedLogs();
assertThat(logProvider).containsMessages("Fail to read transaction log version 3.", "Recovery required from position LogPosition{logVersion=3, byteOffset=" + (569 + HEADER_OFFSET) + "}", "Fail to recover all transactions.", "Any later transaction after LogPosition{logVersion=3, byteOffset=" + (4552 + HEADER_OFFSET) + "} are unreadable and will be truncated.");
assertEquals(3, logFiles.getLogFile().getHighestLogVersion());
assertEquals(transactionsToRecover, recoveryMonitor.getNumberOfRecoveredTransactions());
assertEquals(originalFileLength, fileSystem.getFileSize(highestLogFile));
assertEquals(CURRENT_FORMAT_LOG_HEADER_SIZE + 6 * 192, Files.size(logFiles.getCheckpointFile().getCurrentFile()));
}
Aggregations