use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.
the class InlinedLogTailScanner method findLogTail.
protected LogTailInformation findLogTail() throws IOException {
LogFile logFile = logFiles.getLogFile();
final long highestLogVersion = logFile.getHighestLogVersion();
long version = highestLogVersion;
long versionToSearchForCommits = highestLogVersion;
LogEntryStart latestStartEntry = null;
long oldestStartEntryTransaction = NO_TRANSACTION_ID;
long oldestVersionFound = -1;
byte latestLogEntryVersion = 0;
boolean startRecordAfterCheckpoint = false;
boolean corruptedTransactionLogs = false;
while (version >= logFile.getLowestLogVersion() && version >= INITIAL_LOG_VERSION) {
log.info("Scanning log file with version %d for checkpoint entries", version);
oldestVersionFound = version;
CheckpointInfo latestCheckPoint = null;
StoreId storeId = StoreId.UNKNOWN;
try (LogVersionedStoreChannel channel = logFile.openForVersion(version);
var readAheadChannel = new ReadAheadLogChannel(channel, memoryTracker);
LogEntryCursor cursor = new LogEntryCursor(logEntryReader, readAheadChannel)) {
LogHeader logHeader = logFile.extractHeader(version);
storeId = logHeader.getStoreId();
LogEntry entry;
long position = logHeader.getStartPosition().getByteOffset();
long channelVersion = version;
while (cursor.next()) {
entry = cursor.get();
// Collect data about latest checkpoint
if (entry instanceof LogEntryInlinedCheckPoint) {
latestCheckPoint = new CheckpointInfo((LogEntryInlinedCheckPoint) entry, storeId, new LogPosition(channelVersion, position));
} else if (entry instanceof LogEntryCommit) {
if (oldestStartEntryTransaction == NO_TRANSACTION_ID) {
oldestStartEntryTransaction = ((LogEntryCommit) entry).getTxId();
}
} else if (entry instanceof LogEntryStart) {
LogEntryStart startEntry = (LogEntryStart) entry;
if (version == versionToSearchForCommits) {
latestStartEntry = startEntry;
}
startRecordAfterCheckpoint = true;
}
// Collect data about latest entry version, only in first log file
if (version == versionToSearchForCommits || latestLogEntryVersion == 0) {
latestLogEntryVersion = entry.getVersion().version();
}
position = channel.position();
channelVersion = channel.getVersion();
}
verifyReaderPosition(version, logEntryReader.lastPosition());
} catch (Error | ClosedByInterruptException e) {
// These should not be parsing errors
throw e;
} catch (Throwable t) {
monitor.corruptedLogFile(version, t);
if (failOnCorruptedLogFiles) {
throwUnableToCleanRecover(t);
}
corruptedTransactionLogs = true;
}
if (latestCheckPoint != null) {
return checkpointTailInformation(highestLogVersion, latestStartEntry, oldestVersionFound, latestLogEntryVersion, latestCheckPoint, corruptedTransactionLogs, storeId);
}
version--;
// if we have found no commits in the latest log, keep searching in the next one
if (latestStartEntry == null) {
versionToSearchForCommits--;
}
}
return new LogTailInformation(corruptedTransactionLogs || startRecordAfterCheckpoint, oldestStartEntryTransaction, oldestVersionFound == UNKNOWN, highestLogVersion, latestLogEntryVersion);
}
use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.
the class AbstractLogTailScanner method extractFirstTxIdAfterPosition.
/**
* Extracts txId from first commit entry, when starting reading at the given {@code position}.
* If no commit entry found in the version, the reader will continue into next version(s) up till
* {@code maxLogVersion} until finding one.
*
* @param initialPosition {@link LogPosition} to start scan from.
* @param maxLogVersion max log version to scan.
* @return value object that contains first transaction id of closes commit entry to {@code initialPosition},
* or {@link InlinedLogTailScanner#NO_TRANSACTION_ID} if not found. And failure flag that will be set to true if
* there was some exception during transaction log processing.
* @throws IOException on channel close I/O error.
*/
protected ExtractedTransactionRecord extractFirstTxIdAfterPosition(LogPosition initialPosition, long maxLogVersion) throws IOException {
long initialVersion = initialPosition.getLogVersion();
long logVersion = initialVersion;
var logFile = logFiles.getLogFile();
while (logVersion <= maxLogVersion) {
if (logFile.versionExists(logVersion)) {
LogPosition currentPosition = logVersion != initialVersion ? logFile.extractHeader(logVersion).getStartPosition() : initialPosition;
try (LogVersionedStoreChannel storeChannel = logFile.openForVersion(logVersion)) {
storeChannel.position(currentPosition.getByteOffset());
try (LogEntryCursor cursor = new LogEntryCursor(logEntryReader, new ReadAheadLogChannel(storeChannel, memoryTracker))) {
while (cursor.next()) {
LogEntry entry = cursor.get();
if (entry instanceof LogEntryCommit) {
return new InlinedLogTailScanner.ExtractedTransactionRecord(((LogEntryCommit) entry).getTxId());
}
}
}
} catch (Throwable t) {
monitor.corruptedLogFile(currentPosition.getLogVersion(), t);
return new InlinedLogTailScanner.ExtractedTransactionRecord(true);
}
logVersion = currentPosition.getLogVersion() + 1;
} else {
logVersion += 1;
}
}
return new InlinedLogTailScanner.ExtractedTransactionRecord();
}
use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.
the class ReversedMultiFileTransactionCursorTest method transactions.
private static CommittedTransactionRepresentation[] transactions(int count, AtomicLong txId) {
CommittedTransactionRepresentation[] result = new CommittedTransactionRepresentation[count];
for (int i = 0; i < count; i++) {
CommittedTransactionRepresentation transaction = result[i] = mock(CommittedTransactionRepresentation.class);
LogEntryCommit commitEntry = mock(LogEntryCommit.class);
when(commitEntry.getTxId()).thenReturn(txId.getAndIncrement());
when(transaction.getCommitEntry()).thenReturn(commitEntry);
}
return result;
}
use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.
the class TransactionLogAppendAndRotateIT method assertWholeTransactionsIn.
private static void assertWholeTransactionsIn(LogFile logFile, long logVersion) throws IOException {
try (ReadableLogChannel reader = logFile.getReader(new LogPosition(logVersion, CURRENT_FORMAT_LOG_HEADER_SIZE))) {
LogEntryReader entryReader = logEntryReader();
LogEntry entry;
boolean inTx = false;
int transactions = 0;
while ((entry = entryReader.readLogEntry(reader)) != null) {
if (// Expects start entry
!inTx) {
assertTrue(entry instanceof LogEntryStart);
inTx = true;
} else // Expects command/commit entry
{
assertTrue(entry instanceof LogEntryCommand || entry instanceof LogEntryCommit);
if (entry instanceof LogEntryCommit) {
inTx = false;
transactions++;
}
}
}
assertFalse(inTx);
assertTrue(transactions > 0);
}
}
use of org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit in project neo4j by neo4j.
the class BatchingTransactionAppenderTest method shouldAppendCommittedTransactions.
@Test
void shouldAppendCommittedTransactions() throws Exception {
// GIVEN
when(logFile.getTransactionLogWriter()).thenReturn(new TransactionLogWriter(channel, new DbmsLogEntryWriterFactory(() -> LATEST)));
long nextTxId = 15;
when(transactionIdStore.nextCommittingTransactionId()).thenReturn(nextTxId);
when(transactionIdStore.getLastCommittedTransaction()).thenReturn(new TransactionId(nextTxId, BASE_TX_CHECKSUM, BASE_TX_COMMIT_TIMESTAMP));
TransactionAppender appender = life.add(new BatchingTransactionAppender(logFiles, NO_ROTATION, positionCache, transactionIdStore, databaseHealth));
// WHEN
final byte[] additionalHeader = new byte[] { 1, 2, 5 };
final long timeStarted = 12345;
long latestCommittedTxWhenStarted = nextTxId - 5;
long timeCommitted = timeStarted + 10;
PhysicalTransactionRepresentation transactionRepresentation = new PhysicalTransactionRepresentation(singleTestCommand());
transactionRepresentation.setHeader(additionalHeader, timeStarted, latestCommittedTxWhenStarted, timeCommitted, -1, ANONYMOUS);
LogEntryStart start = new LogEntryStart(0L, latestCommittedTxWhenStarted, 0, null, LogPosition.UNSPECIFIED);
LogEntryCommit commit = new LogEntryCommit(nextTxId, 0L, BASE_TX_CHECKSUM);
CommittedTransactionRepresentation transaction = new CommittedTransactionRepresentation(start, transactionRepresentation, commit);
appender.append(new TransactionToApply(transactionRepresentation, transaction.getCommitEntry().getTxId(), NULL), logAppendEvent);
// THEN
LogEntryReader logEntryReader = logEntryReader();
try (PhysicalTransactionCursor reader = new PhysicalTransactionCursor(channel, logEntryReader)) {
reader.next();
TransactionRepresentation result = reader.get().getTransactionRepresentation();
assertArrayEquals(additionalHeader, result.additionalHeader());
assertEquals(timeStarted, result.getTimeStarted());
assertEquals(timeCommitted, result.getTimeCommitted());
assertEquals(latestCommittedTxWhenStarted, result.getLatestCommittedTxWhenStarted());
}
}
Aggregations