use of org.neo4j.kernel.impl.transaction.log.PhysicalLogFiles in project neo4j by neo4j.
the class StoreMigrator method extractTransactionLogPosition.
private LogPosition extractTransactionLogPosition(File neoStore, File storeDir, long lastTxId) throws IOException {
long lastClosedTxLogVersion = MetaDataStore.getRecord(pageCache, neoStore, Position.LAST_CLOSED_TRANSACTION_LOG_VERSION);
long lastClosedTxLogByteOffset = MetaDataStore.getRecord(pageCache, neoStore, Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET);
if (lastClosedTxLogVersion != MetaDataRecordFormat.FIELD_NOT_PRESENT && lastClosedTxLogByteOffset != MetaDataRecordFormat.FIELD_NOT_PRESENT) {
return new LogPosition(lastClosedTxLogVersion, lastClosedTxLogByteOffset);
}
// The legacy store we're migrating doesn't have this record in neostore so try to extract it from tx log
if (lastTxId == TransactionIdStore.BASE_TX_ID) {
return new LogPosition(BASE_TX_LOG_VERSION, BASE_TX_LOG_BYTE_OFFSET);
}
PhysicalLogFiles logFiles = new PhysicalLogFiles(storeDir, fileSystem);
long logVersion = logFiles.getHighestLogVersion();
if (logVersion == -1) {
return new LogPosition(BASE_TX_LOG_VERSION, BASE_TX_LOG_BYTE_OFFSET);
}
long offset = fileSystem.getFileSize(logFiles.getLogFileForVersion(logVersion));
return new LogPosition(logVersion, offset);
}
use of org.neo4j.kernel.impl.transaction.log.PhysicalLogFiles 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.PhysicalLogFiles in project neo4j by neo4j.
the class RecoveryTest method shouldTellTransactionIdStoreAfterSuccessfullRecovery.
@Test
public void shouldTellTransactionIdStoreAfterSuccessfullRecovery() throws Exception {
// GIVEN
final PhysicalLogFiles logFiles = new PhysicalLogFiles(directory.directory(), "log", fileSystemRule.get());
File file = logFiles.getLogFileForVersion(logVersion);
final LogPositionMarker marker = new LogPositionMarker();
final byte[] additionalHeaderData = new byte[0];
final int masterId = 0;
final int authorId = 1;
final long transactionId = 4;
final long commitTimestamp = 5;
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();
// last committed tx
writer.writeStartEntry(masterId, authorId, 2L, 3L, additionalHeaderData);
writer.writeCommitEntry(transactionId, commitTimestamp);
consumer.accept(marker);
return true;
}
});
// WHEN
boolean recoveryRequired = recover(logFiles);
// THEN
assertTrue(recoveryRequired);
long[] lastClosedTransaction = transactionIdStore.getLastClosedTransaction();
assertEquals(transactionId, lastClosedTransaction[0]);
assertEquals(LogEntryStart.checksum(additionalHeaderData, masterId, authorId), transactionIdStore.getLastCommittedTransaction().checksum());
assertEquals(commitTimestamp, transactionIdStore.getLastCommittedTransaction().commitTimestamp());
assertEquals(logVersion, lastClosedTransaction[1]);
assertEquals(marker.getByteOffset(), lastClosedTransaction[2]);
}
use of org.neo4j.kernel.impl.transaction.log.PhysicalLogFiles in project neo4j by neo4j.
the class RecoveryTest method shouldTruncateLogAfterSinglePartialTransaction.
@Test
public void shouldTruncateLogAfterSinglePartialTransaction() throws Exception {
// GIVEN
final PhysicalLogFiles logFiles = new PhysicalLogFiles(directory.directory(), "log", fileSystemRule.get());
File file = logFiles.getLogFileForVersion(logVersion);
final LogPositionMarker marker = new LogPositionMarker();
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();
// incomplete tx
// <-- marker has the last good position
consumer.accept(marker);
writer.writeStartEntry(0, 1, 5L, 4L, new byte[0]);
return true;
}
});
// WHEN
boolean recoveryRequired = recover(logFiles);
// THEN
assertTrue(recoveryRequired);
assertEquals(marker.getByteOffset(), file.length());
}
use of org.neo4j.kernel.impl.transaction.log.PhysicalLogFiles in project neo4j by neo4j.
the class RecoveryTest method shouldTruncateLogAfterLastCompleteTransactionAfterSuccessfullRecovery.
@Test
public void shouldTruncateLogAfterLastCompleteTransactionAfterSuccessfullRecovery() throws Exception {
// GIVEN
final PhysicalLogFiles logFiles = new PhysicalLogFiles(directory.directory(), "log", fileSystemRule.get());
File file = logFiles.getLogFileForVersion(logVersion);
final LogPositionMarker marker = new LogPositionMarker();
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();
// last committed tx
writer.writeStartEntry(0, 1, 2L, 3L, new byte[0]);
writer.writeCommitEntry(4L, 5L);
// incomplete tx
// <-- marker has the last good position
consumer.accept(marker);
writer.writeStartEntry(0, 1, 5L, 4L, new byte[0]);
return true;
}
});
// WHEN
boolean recoveryRequired = recover(logFiles);
// THEN
assertTrue(recoveryRequired);
assertEquals(marker.getByteOffset(), file.length());
}
Aggregations