use of org.neo4j.storageengine.api.TransactionIdStore in project neo4j by neo4j.
the class InternalTransactionCommitProcessTest method shouldCloseTransactionRegardlessOfWhetherOrNotItAppliedCorrectly.
@Test
void shouldCloseTransactionRegardlessOfWhetherOrNotItAppliedCorrectly() throws Exception {
// GIVEN
TransactionIdStore transactionIdStore = mock(TransactionIdStore.class);
TransactionAppender appender = new TestableTransactionAppender(transactionIdStore);
long txId = 11;
when(transactionIdStore.nextCommittingTransactionId()).thenReturn(txId);
IOException rootCause = new IOException("Mock exception");
StorageEngine storageEngine = mock(StorageEngine.class);
doThrow(new IOException(rootCause)).when(storageEngine).apply(any(TransactionToApply.class), any(TransactionApplicationMode.class));
TransactionCommitProcess commitProcess = new InternalTransactionCommitProcess(appender, storageEngine);
TransactionToApply transaction = mockedTransaction();
// WHEN
TransactionFailureException exception = assertThrows(TransactionFailureException.class, () -> commitProcess.commit(transaction, commitEvent, INTERNAL));
assertThat(exception.getMessage()).contains("Could not apply the transaction to the store");
assertTrue(contains(exception, rootCause.getMessage(), rootCause.getClass()));
// THEN
// we can't verify transactionCommitted since that's part of the TransactionAppender, which we have mocked
verify(transactionIdStore).transactionClosed(eq(txId), anyLong(), anyLong(), any(CursorContext.class));
}
use of org.neo4j.storageengine.api.TransactionIdStore in project neo4j by neo4j.
the class RecoveryCorruptedTransactionLogIT method recoverNotAFirstCorruptedTransactionSingleFileNoCheckpoint.
@ParameterizedTest(name = "[{index}] ({0})")
@MethodSource("corruptedLogEntryWriters")
void recoverNotAFirstCorruptedTransactionSingleFileNoCheckpoint(String testName, LogEntryWriterWrapper logEntryWriterWrapper) throws IOException {
DatabaseManagementService managementService = databaseFactory.build();
GraphDatabaseAPI database = (GraphDatabaseAPI) managementService.database(DEFAULT_DATABASE_NAME);
logFiles = buildDefaultLogFiles(getStoreId(database));
TransactionIdStore transactionIdStore = getTransactionIdStore(database);
long lastClosedTransactionBeforeStart = transactionIdStore.getLastClosedTransactionId();
for (int i = 0; i < 10; i++) {
generateTransaction(database);
}
long numberOfTransactions = transactionIdStore.getLastClosedTransactionId() - lastClosedTransactionBeforeStart;
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 0.", "Recovery required from position LogPosition{logVersion=0, byteOffset=" + txOffsetAfterStart + "}", "Fail to recover all transactions.", "Any later transaction after LogPosition{logVersion=0, byteOffset=" + (6117 + txOffsetAfterStart) + "} are unreadable and will be truncated.");
assertEquals(0, logFiles.getLogFile().getHighestLogVersion());
assertEquals(numberOfTransactions, recoveryMonitor.getNumberOfRecoveredTransactions());
assertEquals(originalFileLength, fileSystem.getFileSize(highestLogFile));
// 2 shutdowns will create a checkpoint and recovery that will be triggered by removing tx logs for default db
// during the setup and starting db as part of the test
assertEquals(CURRENT_FORMAT_LOG_HEADER_SIZE + 3 * 192, Files.size(logFiles.getCheckpointFile().getCurrentFile()));
}
use of org.neo4j.storageengine.api.TransactionIdStore in project neo4j by neo4j.
the class Runner method call.
@Override
public Long call() throws Exception {
long lastCommittedTransactionId;
try (FileSystemAbstraction fileSystem = new DefaultFileSystemAbstraction();
Lifespan life = new Lifespan()) {
TransactionIdStore transactionIdStore = new SimpleTransactionIdStore();
TransactionMetadataCache transactionMetadataCache = new TransactionMetadataCache();
LogFiles logFiles = life.add(createLogFiles(transactionIdStore, fileSystem));
TransactionAppender transactionAppender = life.add(createBatchingTransactionAppender(transactionIdStore, transactionMetadataCache, logFiles));
ExecutorService executorService = Executors.newFixedThreadPool(threads);
try {
List<Future<?>> handlers = new ArrayList<>(threads);
for (int i = 0; i < threads; i++) {
TransactionRepresentationFactory factory = new TransactionRepresentationFactory();
Worker task = new Worker(transactionAppender, factory, condition);
handlers.add(executorService.submit(task));
}
// wait for all the workers to complete
Futures.getAll(handlers);
} finally {
executorService.shutdown();
}
lastCommittedTransactionId = transactionIdStore.getLastCommittedTransactionId();
}
return lastCommittedTransactionId;
}
use of org.neo4j.storageengine.api.TransactionIdStore in project neo4j by neo4j.
the class RecoveryCorruptedTransactionLogIT method truncateNewerTransactionLogFileWhenForced.
@Test
void truncateNewerTransactionLogFileWhenForced() throws IOException {
DatabaseManagementService managementService = databaseFactory.build();
GraphDatabaseAPI database = (GraphDatabaseAPI) managementService.database(DEFAULT_DATABASE_NAME);
TransactionIdStore transactionIdStore = getTransactionIdStore(database);
long numberOfClosedTransactionsAfterStartup = transactionIdStore.getLastClosedTransactionId();
logFiles = buildDefaultLogFiles(getStoreId(database));
for (int i = 0; i < 10; i++) {
generateTransaction(database);
}
long numberOfTransactionsToRecover = transactionIdStore.getLastClosedTransactionId() - numberOfClosedTransactionsAfterStartup;
managementService.shutdown();
removeLastCheckpointRecordFromLastLogFile();
Supplier<Byte> randomBytesSupplier = this::randomInvalidVersionsBytes;
BytesCaptureSupplier capturingSupplier = new BytesCaptureSupplier(randomBytesSupplier);
addRandomBytesToLastLogFile(capturingSupplier);
assertFalse(recoveryMonitor.wasRecoveryRequired());
startStopDbRecoveryOfCorruptedLogs();
try {
assertEquals(numberOfTransactionsToRecover, recoveryMonitor.getNumberOfRecoveredTransactions());
assertTrue(recoveryMonitor.wasRecoveryRequired());
assertThat(logProvider).containsMessages("Fail to read transaction log version 0.", "Fail to read transaction log version 0. Last valid transaction start offset is: " + (5548 + txOffsetAfterStart) + ".");
} catch (Throwable t) {
throw new RuntimeException("Generated random bytes: " + capturingSupplier.getCapturedBytes(), t);
}
}
use of org.neo4j.storageengine.api.TransactionIdStore in project neo4j by neo4j.
the class RecoveryCorruptedTransactionLogIT method recoverNotAFirstCorruptedTransactionMultipleFilesNoCheckpoints.
@ParameterizedTest(name = "[{index}] ({0})")
@MethodSource("corruptedLogEntryWriters")
void recoverNotAFirstCorruptedTransactionMultipleFilesNoCheckpoints(String testName, LogEntryWriterWrapper logEntryWriterWrapper) throws IOException {
DatabaseManagementService managementService = databaseFactory.build();
GraphDatabaseAPI database = (GraphDatabaseAPI) managementService.database(DEFAULT_DATABASE_NAME);
logFiles = buildDefaultLogFiles(getStoreId(database));
TransactionIdStore transactionIdStore = getTransactionIdStore(database);
long lastClosedTransactionBeforeStart = transactionIdStore.getLastClosedTransactionId();
generateTransactionsAndRotate(database, 3);
for (int i = 0; i < 7; i++) {
generateTransaction(database);
}
long numberOfTransactions = transactionIdStore.getLastClosedTransactionId() - lastClosedTransactionBeforeStart;
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=0, byteOffset=" + txOffsetAfterStart + "}", "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(numberOfTransactions, recoveryMonitor.getNumberOfRecoveredTransactions());
assertEquals(originalFileLength, fileSystem.getFileSize(highestLogFile));
// 2 shutdowns will create a checkpoint and recovery that will be triggered by removing tx logs for default db
// during the setup and starting db as part of the test
assertEquals(CURRENT_FORMAT_LOG_HEADER_SIZE + 3 * 192, Files.size(logFiles.getCheckpointFile().getCurrentFile()));
}
Aggregations