use of org.neo4j.kernel.impl.transaction.log.LogPosition in project neo4j by neo4j.
the class Recovery method init.
@Override
public void init() throws Throwable {
LogPosition recoveryFromPosition = spi.getPositionToRecoverFrom();
if (LogPosition.UNSPECIFIED.equals(recoveryFromPosition)) {
return;
}
monitor.recoveryRequired(recoveryFromPosition);
LogPosition recoveryToPosition;
CommittedTransactionRepresentation lastTransaction = null;
Visitor<CommittedTransactionRepresentation, Exception> recoveryVisitor = spi.startRecovery();
try (TransactionCursor transactionsToRecover = spi.getTransactions(recoveryFromPosition)) {
while (transactionsToRecover.next()) {
lastTransaction = transactionsToRecover.get();
long txId = lastTransaction.getCommitEntry().getTxId();
recoveryVisitor.visit(lastTransaction);
monitor.transactionRecovered(txId);
numberOfRecoveredTransactions++;
}
recoveryToPosition = transactionsToRecover.position();
}
if (recoveryToPosition.equals(LogPosition.UNSPECIFIED)) {
recoveryToPosition = recoveryFromPosition;
}
spi.allTransactionsRecovered(lastTransaction, recoveryToPosition);
recoveredLog = true;
spi.forceEverything();
}
use of org.neo4j.kernel.impl.transaction.log.LogPosition 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.LogPosition in project neo4j by neo4j.
the class VersionAwareLogEntryReaderTest method shouldParseOldStartEntry.
@Test
public void shouldParseOldStartEntry() throws IOException {
// given
LogEntryVersion version = LogEntryVersion.V2_1;
final InMemoryClosableChannel channel = new InMemoryClosableChannel();
final LogEntryStart start = new LogEntryStart(1, 2, 3, 4, new byte[] {}, new LogPosition(0, 37));
channel.put(version.byteCode());
channel.put(LogEntryByteCodes.TX_START);
// ignored data
// globalId length
channel.put((byte) 1);
// branchId length
channel.put((byte) 0);
// globalId
channel.put(new byte[] { 7 }, 1);
// branchId
channel.put(new byte[] {}, 0);
// identifier
channel.putInt(123);
// formatId
channel.putInt(456);
// actually used data
channel.putInt(start.getMasterId());
channel.putInt(start.getLocalId());
channel.putLong(start.getTimeWritten());
channel.putLong(start.getLastCommittedTxWhenTransactionStarted());
// when
final LogEntry logEntry = logEntryReader.readLogEntry(channel);
// then
assertTrue(logEntry instanceof IdentifiableLogEntry);
assertEquals(start, ((IdentifiableLogEntry) logEntry).getEntry());
}
use of org.neo4j.kernel.impl.transaction.log.LogPosition in project neo4j by neo4j.
the class LatestCheckPointFinderTest method logFile.
private LogCreator logFile(Entry... entries) {
return (logVersion, positions) -> {
try {
AtomicLong lastTxId = new AtomicLong();
Supplier<Long> lastTxIdSupplier = () -> lastTxId.get();
LogVersionRepository logVersionRepository = new DeadSimpleLogVersionRepository(logVersion);
LifeSupport life = new LifeSupport();
life.start();
PhysicalLogFile logFile = life.add(new PhysicalLogFile(fsRule.get(), logFiles, mebiBytes(1), lastTxIdSupplier, logVersionRepository, NO_MONITOR, new LogHeaderCache(10)));
try {
FlushablePositionAwareChannel writeChannel = logFile.getWriter();
LogPositionMarker positionMarker = new LogPositionMarker();
LogEntryWriter writer = new LogEntryWriter(writeChannel);
for (Entry entry : entries) {
LogPosition currentPosition = writeChannel.getCurrentPosition(positionMarker).newPosition();
positions.put(entry, currentPosition);
if (entry instanceof StartEntry) {
writer.writeStartEntry(0, 0, 0, 0, new byte[0]);
} else if (entry instanceof CommitEntry) {
CommitEntry commitEntry = (CommitEntry) entry;
writer.writeCommitEntry(commitEntry.txId, 0);
lastTxId.set(commitEntry.txId);
} else if (entry instanceof CheckPointEntry) {
CheckPointEntry checkPointEntry = (CheckPointEntry) entry;
Entry target = checkPointEntry.withPositionOfEntry;
LogPosition logPosition = target != null ? positions.get(target) : currentPosition;
assert logPosition != null : "No registered log position for " + target;
writer.writeCheckPointEntry(logPosition);
} else if (entry instanceof PositionEntry) {
// Don't write anything, this entry is just for registering a position so that
// another CheckPointEntry can refer to it
} else {
throw new IllegalArgumentException("Unknown entry " + entry);
}
}
} finally {
life.shutdown();
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
};
}
use of org.neo4j.kernel.impl.transaction.log.LogPosition in project neo4j by neo4j.
the class PositionToRecoverFromTest method shouldReturnUnspecifiedIfThereIsNoNeedForRecovery.
@Test
public void shouldReturnUnspecifiedIfThereIsNoNeedForRecovery() throws Throwable {
// given
when(finder.find(logVersion)).thenReturn(new LatestCheckPoint(null, false, NO_TRANSACTION_ID, logVersion));
// when
LogPosition logPosition = new PositionToRecoverFrom(finder, monitor).apply(logVersion);
// then
verify(monitor).noCommitsAfterLastCheckPoint(null);
assertEquals(LogPosition.UNSPECIFIED, logPosition);
}
Aggregations