use of org.neo4j.kernel.impl.transaction.log.TransactionLogWriter in project neo4j by neo4j.
the class StoreMigratorCheckPointer method checkPoint.
/**
* Write a check point in the log file with the given version
* <p>
* It will create the file with header containing the log version and lastCommittedTx given as arguments
*
* @param logVersion the log version to open
* @param lastCommittedTx the last committed tx id
*/
public void checkPoint(long logVersion, long lastCommittedTx) throws IOException {
PhysicalLogFiles logFiles = new PhysicalLogFiles(storeDir, fileSystem);
File logFileForVersion = logFiles.getLogFileForVersion(logVersion);
if (!fileSystem.fileExists(logFileForVersion)) {
try (StoreChannel channel = fileSystem.create(logFileForVersion)) {
writeLogHeader(channel, logVersion, lastCommittedTx);
}
}
try (LogVersionedStoreChannel storeChannel = PhysicalLogFile.openForVersion(logFiles, fileSystem, logVersion, true)) {
long offset = storeChannel.size();
storeChannel.position(offset);
try (PositionAwarePhysicalFlushableChannel channel = new PositionAwarePhysicalFlushableChannel(storeChannel)) {
TransactionLogWriter writer = new TransactionLogWriter(new LogEntryWriter(channel));
writer.checkPoint(new LogPosition(logVersion, offset));
}
}
}
use of org.neo4j.kernel.impl.transaction.log.TransactionLogWriter in project neo4j by neo4j.
the class StoreCopyClient method writeTransactionsToActiveLogFile.
private void writeTransactionsToActiveLogFile(File tempStoreDir, Response<?> response) throws Exception {
LifeSupport life = new LifeSupport();
try {
// Start the log and appender
PhysicalLogFiles logFiles = new PhysicalLogFiles(tempStoreDir, fs);
LogHeaderCache logHeaderCache = new LogHeaderCache(10);
ReadOnlyLogVersionRepository logVersionRepository = new ReadOnlyLogVersionRepository(pageCache, tempStoreDir);
ReadOnlyTransactionIdStore readOnlyTransactionIdStore = new ReadOnlyTransactionIdStore(pageCache, tempStoreDir);
LogFile logFile = life.add(new PhysicalLogFile(fs, logFiles, Long.MAX_VALUE, /*don't rotate*/
readOnlyTransactionIdStore::getLastCommittedTransactionId, logVersionRepository, new Monitors().newMonitor(PhysicalLogFile.Monitor.class), logHeaderCache));
life.start();
// Just write all transactions to the active log version. Remember that this is after a store copy
// where there are no logs, and the transaction stream we're about to write will probably contain
// transactions that goes some time back, before the last committed transaction id. So we cannot
// use a TransactionAppender, since it has checks for which transactions one can append.
FlushableChannel channel = logFile.getWriter();
final TransactionLogWriter writer = new TransactionLogWriter(new LogEntryWriter(channel));
final AtomicLong firstTxId = new AtomicLong(BASE_TX_ID);
response.accept(new Response.Handler() {
@Override
public void obligation(long txId) throws IOException {
throw new UnsupportedOperationException("Shouldn't be called");
}
@Override
public Visitor<CommittedTransactionRepresentation, Exception> transactions() {
return transaction -> {
long txId = transaction.getCommitEntry().getTxId();
if (firstTxId.compareAndSet(BASE_TX_ID, txId)) {
monitor.startReceivingTransactions(txId);
}
writer.append(transaction.getTransactionRepresentation(), txId);
return false;
};
}
});
long endTxId = firstTxId.get();
if (endTxId != BASE_TX_ID) {
monitor.finishReceivingTransactions(endTxId);
}
long currentLogVersion = logVersionRepository.getCurrentLogVersion();
writer.checkPoint(new LogPosition(currentLogVersion, LOG_HEADER_SIZE));
// And since we write this manually we need to set the correct transaction id in the
// header of the log that we just wrote.
File currentLogFile = logFiles.getLogFileForVersion(currentLogVersion);
writeLogHeader(fs, currentLogFile, currentLogVersion, max(BASE_TX_ID, endTxId - 1));
if (!forensics) {
// since we just create new log and put checkpoint into it with offset equals to
// LOG_HEADER_SIZE we need to update last transaction offset to be equal to this newly defined max
// offset otherwise next checkpoint that use last transaction offset will be created for non
// existing offset that is in most of the cases bigger than new log size.
// Recovery will treat that as last checkpoint and will not try to recover store till new
// last closed transaction offset will not overcome old one. Till that happens it will be
// impossible for recovery process to restore the store
File neoStore = new File(tempStoreDir, MetaDataStore.DEFAULT_NAME);
MetaDataStore.setRecord(pageCache, neoStore, MetaDataStore.Position.LAST_CLOSED_TRANSACTION_LOG_BYTE_OFFSET, LOG_HEADER_SIZE);
}
} finally {
life.shutdown();
}
}
use of org.neo4j.kernel.impl.transaction.log.TransactionLogWriter in project neo4j by neo4j.
the class VersionAwareLogEntryReaderIT method correctlyResetPositionOfObservedZeroWhenChannelSwitchOnExactlyCheckedByte.
@Test
void correctlyResetPositionOfObservedZeroWhenChannelSwitchOnExactlyCheckedByte() throws IOException {
LogFiles logFiles = LogFilesBuilder.builder(databaseLayout, fs).withLogEntryReader(entryReader).withLogVersionRepository(new SimpleLogVersionRepository()).withTransactionIdStore(new SimpleTransactionIdStore()).withStoreId(StoreId.UNKNOWN).withKernelVersionProvider(() -> KernelVersion.V4_0).build();
try (Lifespan lifespan = new Lifespan(logFiles)) {
LogPositionMarker positionMarker = new LogPositionMarker();
LogFile logFile = logFiles.getLogFile();
long initialPosition = getLastReadablePosition(logFiles);
long checkpointsEndDataOffset = DEFAULT_READ_AHEAD_SIZE + initialPosition;
TransactionLogWriter logWriter = logFile.getTransactionLogWriter();
do {
logWriter.legacyCheckPoint(new LogPosition(4, 5));
logWriter.getCurrentPosition(positionMarker);
} while (positionMarker.getByteOffset() <= checkpointsEndDataOffset);
logFile.flush();
logFiles.getLogFile().rotate();
fs.truncate(logFiles.getLogFile().getLogFileForVersion(0), checkpointsEndDataOffset);
try (StoreChannel storeChannel = fs.write(logFiles.getLogFile().getLogFileForVersion(1))) {
storeChannel.position(CURRENT_FORMAT_LOG_HEADER_SIZE);
storeChannel.writeAll(ByteBuffer.wrap(new byte[] { 0 }));
}
try (ReadableLogChannel logChannel = logFiles.getLogFile().getReader(new LogPosition(0, initialPosition))) {
LogEntry logEntry = entryReader.readLogEntry(logChannel);
// we reading expected checkpoint records
assertThat(logEntry).isInstanceOf(LogEntryInlinedCheckPoint.class);
LogEntryInlinedCheckPoint checkPoint = (LogEntryInlinedCheckPoint) logEntry;
LogPosition logPosition = checkPoint.getLogPosition();
assertEquals(4, logPosition.getLogVersion());
assertEquals(5, logPosition.getByteOffset());
// set position to the end of the buffer to cause channel switch on next byte read
((PositionableChannel) logChannel).setCurrentPosition(checkpointsEndDataOffset);
while (entryReader.readLogEntry(logChannel) != null) {
// read to the end
}
// channel should be switched now and position should be just after the header
LogPosition position = entryReader.lastPosition();
assertEquals(CURRENT_FORMAT_LOG_HEADER_SIZE, position.getByteOffset());
assertEquals(1, position.getLogVersion());
}
}
}
use of org.neo4j.kernel.impl.transaction.log.TransactionLogWriter in project neo4j by neo4j.
the class TransactionLogInitializer method appendEmptyTransactionAndCheckPoint.
private void appendEmptyTransactionAndCheckPoint(LogFiles logFiles, String reason) throws IOException {
TransactionId committedTx = store.getLastCommittedTransaction();
long timestamp = committedTx.commitTimestamp();
long transactionId = committedTx.transactionId();
LogFile logFile = logFiles.getLogFile();
TransactionLogWriter transactionLogWriter = logFile.getTransactionLogWriter();
PhysicalTransactionRepresentation emptyTx = emptyTransaction(timestamp);
int checksum = transactionLogWriter.append(emptyTx, BASE_TX_ID, BASE_TX_CHECKSUM);
logFile.forceAfterAppend(LogAppendEvent.NULL);
LogPosition position = transactionLogWriter.getCurrentPosition();
appendCheckpoint(logFiles, reason, position);
try (CursorContext cursorContext = new CursorContext(tracer.createPageCursorTracer(LOGS_UPGRADER_TRACER_TAG))) {
store.setLastCommittedAndClosedTransactionId(transactionId, checksum, timestamp, position.getByteOffset(), position.getLogVersion(), cursorContext);
}
}
use of org.neo4j.kernel.impl.transaction.log.TransactionLogWriter in project neo4j by neo4j.
the class ReversedSingleFileTransactionCursorTest method appendCorruptedTransaction.
private void appendCorruptedTransaction() throws IOException {
var channel = logFile.getTransactionLogWriter().getChannel();
TransactionLogWriter writer = new TransactionLogWriter(channel, new CorruptedLogEntryWriterFactory());
writer.append(tx(random.intBetween(100, 1000)), ++txId, BASE_TX_CHECKSUM);
}
Aggregations