use of org.neo4j.io.fs.PositionableChannel 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.io.fs.PositionableChannel in project neo4j by neo4j.
the class VersionAwareLogEntryReader method resetChannelPosition.
private void resetChannelPosition(ReadableClosablePositionAwareChecksumChannel channel) throws IOException {
// take current position
channel.getCurrentPosition(positionMarker);
PositionableChannel positionableChannel = (PositionableChannel) channel;
positionableChannel.setCurrentPosition(positionMarker.getByteOffset() - 1);
// refresh with reset position
channel.getCurrentPosition(positionMarker);
}
use of org.neo4j.io.fs.PositionableChannel in project neo4j by neo4j.
the class VersionAwareLogEntryReader method readLogEntry.
@Override
public LogEntry readLogEntry(ReadableClosablePositionAwareChecksumChannel channel) throws IOException {
try {
while (true) {
channel.getCurrentPosition(positionMarker);
byte versionCode = channel.get();
if (versionCode == 0) {
// and we report that we reach end of record stream from our point of view
if (channel instanceof PositionableChannel) {
resetChannelPosition(channel);
} else {
throw new IllegalStateException("Log reader expects positionable channel to be able to reset offset. Current channel: " + channel);
}
return null;
}
if (parserSet == null || parserSet.getIntroductionVersion().version() != versionCode) {
try {
parserSet = LogEntryParserSets.parserSet(KernelVersion.getForVersion(versionCode));
} catch (IllegalArgumentException e) {
throw new UnsupportedLogVersionException(String.format("Log file contains entries with prefix %d, and the lowest supported prefix is %s. This " + "indicates that the log files originates from an older version of neo4j, which we don't support " + "migrations from.", versionCode, KernelVersion.V2_3));
}
// a new checksum segment if we change version parser.
if (channel instanceof PositionableChannel) {
resetChannelPosition(channel);
channel.beginChecksum();
channel.get();
}
}
byte typeCode = channel.get();
LogEntryParser entryReader;
LogEntry entry;
try {
entryReader = parserSet.select(typeCode);
entry = entryReader.parse(parserSet.getIntroductionVersion(), channel, positionMarker, commandReaderFactory);
} catch (ReadPastEndException e) {
// Make these exceptions slip by straight out to the outer handler
throw e;
} catch (Exception e) {
// Tag all other exceptions with log position and other useful information
LogPosition position = positionMarker.newPosition();
withMessage(e, e.getMessage() + ". At position " + position + " and entry version " + versionCode);
throwIfInstanceOf(e, UnsupportedLogVersionException.class);
throw new IOException(e);
}
verifyChecksumChain(entry);
return entry;
}
} catch (ReadPastEndException e) {
return null;
}
}
Aggregations