use of org.neo4j.kernel.impl.transaction.log.entry.CheckPoint in project neo4j by neo4j.
the class CheckTxLogs method validateCheckPoints.
boolean validateCheckPoints(PhysicalLogFiles logFiles, InconsistenciesHandler handler) throws IOException {
final long lowestLogVersion = logFiles.getLowestLogVersion();
final long highestLogVersion = logFiles.getHighestLogVersion();
boolean success = true;
try (PrimitiveLongLongMap logFileSizes = Primitive.offHeapLongLongMap()) {
for (long i = lowestLogVersion; i <= highestLogVersion; i++) {
logFileSizes.put(i, fs.getFileSize(logFiles.getLogFileForVersion(i)));
}
LogEntryCursor logEntryCursor = LogTestUtils.openLogs(fs, logFiles);
while (logEntryCursor.next()) {
LogEntry logEntry = logEntryCursor.get();
if (logEntry instanceof CheckPoint) {
LogPosition logPosition = logEntry.<CheckPoint>as().getLogPosition();
// if the file has been pruned we cannot validate the check point
if (logPosition.getLogVersion() >= lowestLogVersion) {
long size = logFileSizes.get(logPosition.getLogVersion());
if (logPosition.getByteOffset() < 0 || size < 0 || logPosition.getByteOffset() > size) {
long currentLogVersion = logEntryCursor.getCurrentLogVersion();
handler.reportInconsistentCheckPoint(currentLogVersion, logPosition, size);
success = false;
}
}
}
}
}
return success;
}
use of org.neo4j.kernel.impl.transaction.log.entry.CheckPoint 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.entry.CheckPoint in project neo4j by neo4j.
the class RecoveryTest method shouldRecoverExistingData.
@Test
public void shouldRecoverExistingData() throws Exception {
final PhysicalLogFiles logFiles = new PhysicalLogFiles(directory.directory(), "log", fileSystemRule.get());
File file = logFiles.getLogFileForVersion(logVersion);
writeSomeData(file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>, IOException>() {
@Override
public boolean visit(Pair<LogEntryWriter, Consumer<LogPositionMarker>> pair) throws IOException {
LogEntryWriter writer = pair.first();
Consumer<LogPositionMarker> consumer = pair.other();
LogPositionMarker marker = new LogPositionMarker();
// last committed tx
consumer.accept(marker);
LogPosition lastCommittedTxPosition = marker.newPosition();
writer.writeStartEntry(0, 1, 2L, 3L, new byte[0]);
lastCommittedTxStartEntry = new LogEntryStart(0, 1, 2L, 3L, new byte[0], lastCommittedTxPosition);
writer.writeCommitEntry(4L, 5L);
lastCommittedTxCommitEntry = new OnePhaseCommit(4L, 5L);
// check point pointing to the previously committed transaction
writer.writeCheckPointEntry(lastCommittedTxPosition);
expectedCheckPointEntry = new CheckPoint(lastCommittedTxPosition);
// tx committed after checkpoint
consumer.accept(marker);
writer.writeStartEntry(0, 1, 6L, 4L, new byte[0]);
expectedStartEntry = new LogEntryStart(0, 1, 6L, 4L, new byte[0], marker.newPosition());
writer.writeCommitEntry(5L, 7L);
expectedCommitEntry = new OnePhaseCommit(5L, 7L);
return true;
}
});
LifeSupport life = new LifeSupport();
Recovery.Monitor monitor = mock(Recovery.Monitor.class);
final AtomicBoolean recoveryRequired = new AtomicBoolean();
try {
StorageEngine storageEngine = mock(StorageEngine.class);
final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
LatestCheckPointFinder finder = new LatestCheckPointFinder(logFiles, fileSystemRule.get(), reader);
LogHeaderCache logHeaderCache = new LogHeaderCache(10);
TransactionMetadataCache metadataCache = new TransactionMetadataCache(100);
LogFile logFile = life.add(new PhysicalLogFile(fileSystemRule.get(), logFiles, 50, () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository, mock(PhysicalLogFile.Monitor.class), logHeaderCache));
LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore(logFile, metadataCache, reader);
life.add(new Recovery(new DefaultRecoverySPI(storageEngine, logFiles, fileSystemRule.get(), logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR) {
private int nr = 0;
@Override
public Visitor<CommittedTransactionRepresentation, Exception> startRecovery() {
recoveryRequired.set(true);
final Visitor<CommittedTransactionRepresentation, Exception> actual = super.startRecovery();
return new Visitor<CommittedTransactionRepresentation, Exception>() {
@Override
public boolean visit(CommittedTransactionRepresentation tx) throws Exception {
actual.visit(tx);
switch(nr++) {
case 0:
assertEquals(lastCommittedTxStartEntry, tx.getStartEntry());
assertEquals(lastCommittedTxCommitEntry, tx.getCommitEntry());
break;
case 1:
assertEquals(expectedStartEntry, tx.getStartEntry());
assertEquals(expectedCommitEntry, tx.getCommitEntry());
break;
default:
fail("Too many recovered transactions");
}
return false;
}
};
}
}, monitor));
life.start();
InOrder order = inOrder(monitor);
order.verify(monitor, times(1)).recoveryRequired(any(LogPosition.class));
order.verify(monitor, times(1)).recoveryCompleted(2);
assertTrue(recoveryRequired.get());
} finally {
life.shutdown();
}
}
use of org.neo4j.kernel.impl.transaction.log.entry.CheckPoint in project neo4j by neo4j.
the class PositionToRecoverFromTest method shouldReturnLogPositionToRecoverFromIfNeeded.
@Test
public void shouldReturnLogPositionToRecoverFromIfNeeded() throws Throwable {
// given
LogPosition checkPointLogPosition = new LogPosition(1L, 4242);
when(finder.find(logVersion)).thenReturn(new LatestCheckPoint(new CheckPoint(checkPointLogPosition), true, 10L, logVersion));
// when
LogPosition logPosition = new PositionToRecoverFrom(finder, monitor).apply(logVersion);
// then
verify(monitor).commitsAfterLastCheckPoint(checkPointLogPosition, 10L);
assertEquals(checkPointLogPosition, logPosition);
}
Aggregations