use of org.neo4j.kernel.impl.transaction.log.LogEntryCursor in project neo4j by neo4j.
the class LogTestUtils method assertLogContains.
public static void assertLogContains(FileSystemAbstraction fileSystem, String logPath, LogEntry... expectedEntries) throws IOException {
try (LogEntryCursor cursor = openLog(fileSystem, new File(logPath))) {
int entryNo = 0;
while (cursor.next()) {
assertTrue("The log contained more entries than we expected!", entryNo < expectedEntries.length);
LogEntry expectedEntry = expectedEntries[entryNo];
assertEquals("Unexpected entry at entry number " + entryNo, cursor.get(), expectedEntry);
entryNo++;
}
if (entryNo < expectedEntries.length) {
fail("Log ended prematurely. Expected to find '" + expectedEntries[entryNo].toString() + "' as log entry number " + entryNo + ", instead there were no more log entries.");
}
}
}
use of org.neo4j.kernel.impl.transaction.log.LogEntryCursor in project neo4j by neo4j.
the class LogMatchers method logEntries.
public static List<LogEntry> logEntries(FileSystemAbstraction fileSystem, String logPath) throws IOException {
File logFile = new File(logPath);
StoreChannel fileChannel = fileSystem.open(logFile, "r");
// Always a header
LogHeader header = readLogHeader(ByteBuffer.allocateDirect(LOG_HEADER_SIZE), fileChannel, true, logFile);
// Read all log entries
PhysicalLogVersionedStoreChannel versionedStoreChannel = new PhysicalLogVersionedStoreChannel(fileChannel, header.logVersion, header.logFormatVersion);
ReadableLogChannel logChannel = new ReadAheadLogChannel(versionedStoreChannel, NO_MORE_CHANNELS);
LogEntryCursor logEntryCursor = new LogEntryCursor(new VersionAwareLogEntryReader<>(), logChannel);
return Iterables.asList(new IOCursorAsResourceIterable<>(logEntryCursor));
}
use of org.neo4j.kernel.impl.transaction.log.LogEntryCursor in project neo4j by neo4j.
the class LatestCheckPointFinder method find.
public LatestCheckPoint find(long fromVersionBackwards) throws IOException {
long version = fromVersionBackwards;
long versionToSearchForCommits = fromVersionBackwards;
LogEntryStart latestStartEntry = null;
LogEntryStart oldestStartEntry = null;
long oldestVersionFound = -1;
while (version >= INITIAL_LOG_VERSION) {
LogVersionedStoreChannel channel = PhysicalLogFile.tryOpenForVersion(logFiles, fileSystem, version, false);
if (channel == null) {
break;
}
oldestVersionFound = version;
CheckPoint latestCheckPoint = null;
ReadableLogChannel recoveredDataChannel = new ReadAheadLogChannel(channel, NO_MORE_CHANNELS);
boolean firstStartEntry = true;
try (LogEntryCursor cursor = new LogEntryCursor(logEntryReader, recoveredDataChannel)) {
LogEntry entry;
while (cursor.next()) {
entry = cursor.get();
if (entry instanceof CheckPoint) {
latestCheckPoint = entry.as();
}
if (entry instanceof LogEntryStart) {
LogEntryStart startEntry = entry.as();
if (version == versionToSearchForCommits) {
latestStartEntry = startEntry;
}
// Oldest start entry will be the first in the last log version scanned.
if (firstStartEntry) {
oldestStartEntry = startEntry;
firstStartEntry = false;
}
}
}
}
if (latestCheckPoint != null) {
return latestCheckPoint(fromVersionBackwards, version, latestStartEntry, oldestVersionFound, latestCheckPoint);
}
version--;
// if we have found no commits in the latest log, keep searching in the next one
if (latestStartEntry == null) {
versionToSearchForCommits--;
}
}
boolean commitsAfterCheckPoint = oldestStartEntry != null;
long firstTxAfterPosition = commitsAfterCheckPoint ? extractFirstTxIdAfterPosition(oldestStartEntry.getStartPosition(), fromVersionBackwards) : LatestCheckPoint.NO_TRANSACTION_ID;
return new LatestCheckPoint(null, commitsAfterCheckPoint, firstTxAfterPosition, oldestVersionFound);
}
use of org.neo4j.kernel.impl.transaction.log.LogEntryCursor in project neo4j by neo4j.
the class LatestCheckPointFinder 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 txId of closes commit entry to {@code initialPosition}, or {@link LatestCheckPoint#NO_TRANSACTION_ID}
* if not found.
* @throws IOException on I/O error.
*/
private long extractFirstTxIdAfterPosition(LogPosition initialPosition, long maxLogVersion) throws IOException {
LogPosition currentPosition = initialPosition;
while (currentPosition.getLogVersion() <= maxLogVersion) {
LogVersionedStoreChannel storeChannel = PhysicalLogFile.tryOpenForVersion(logFiles, fileSystem, currentPosition.getLogVersion(), false);
if (storeChannel != null) {
try {
storeChannel.position(currentPosition.getByteOffset());
try (ReadAheadLogChannel logChannel = new ReadAheadLogChannel(storeChannel, NO_MORE_CHANNELS);
LogEntryCursor cursor = new LogEntryCursor(logEntryReader, logChannel)) {
while (cursor.next()) {
LogEntry entry = cursor.get();
if (entry instanceof LogEntryCommit) {
return ((LogEntryCommit) entry).getTxId();
}
}
}
} finally {
storeChannel.close();
}
}
currentPosition = LogPosition.start(currentPosition.getLogVersion() + 1);
}
return LatestCheckPoint.NO_TRANSACTION_ID;
}
use of org.neo4j.kernel.impl.transaction.log.LogEntryCursor in project neo4j by neo4j.
the class CheckTxLogs method scan.
private <C extends Command, R extends AbstractBaseRecord> boolean scan(PhysicalLogFiles logFiles, InconsistenciesHandler handler, CheckType<C, R> check, boolean checkTxIds) throws IOException {
out.println("Checking logs for " + check.name() + " inconsistencies");
CommittedRecords<R> state = new CommittedRecords<>(check);
List<CommandAndLogVersion> txCommands = new ArrayList<>();
boolean validLogs = true;
long commandsRead = 0;
long lastSeenTxId = BASE_TX_ID;
try (LogEntryCursor logEntryCursor = LogTestUtils.openLogs(fs, logFiles)) {
while (logEntryCursor.next()) {
LogEntry entry = logEntryCursor.get();
if (entry instanceof LogEntryCommand) {
StorageCommand command = ((LogEntryCommand) entry).getXaCommand();
if (check.commandClass().isInstance(command)) {
long logVersion = logEntryCursor.getCurrentLogVersion();
txCommands.add(new CommandAndLogVersion(command, logVersion));
}
} else if (entry instanceof LogEntryCommit) {
long txId = ((LogEntryCommit) entry).getTxId();
if (checkTxIds) {
validLogs &= checkNoDuplicatedTxsInTheLog(lastSeenTxId, txId, handler);
lastSeenTxId = txId;
}
for (CommandAndLogVersion txCommand : txCommands) {
validLogs &= checkAndHandleInconsistencies(txCommand, check, state, txId, handler);
}
txCommands.clear();
}
commandsRead++;
}
}
out.println("Processed " + commandsRead + " commands");
out.println(state);
if (!txCommands.isEmpty()) {
out.println("Found " + txCommands.size() + " uncommitted commands at the end.");
for (CommandAndLogVersion txCommand : txCommands) {
validLogs &= checkAndHandleInconsistencies(txCommand, check, state, -1, handler);
}
txCommands.clear();
}
return validLogs;
}
Aggregations