use of org.neo4j.io.fs.StoreChannel in project neo4j by neo4j.
the class SegmentedRaftLogPartialEntryRecoveryTest method truncateAndRecover.
/**
* Truncates and recovers the log file provided, one byte at a time until it reaches the header.
* The reason the header is not truncated (and instead has its own test) is that if the log consists of
* only one file (Segment) and the header is incomplete, that is correctly an exceptional circumstance and
* is tested elsewhere.
*/
private void truncateAndRecover(File logFile, long truncateDownToSize) throws IOException, DamagedLogStorageException, DisposedException {
StoreChannel lastFile = fsRule.get().open(logFile, "rw");
long currentSize = lastFile.size();
lastFile.close();
RecoveryProtocol recovery;
while (currentSize-- > truncateDownToSize) {
lastFile = fsRule.get().open(logFile, "rw");
lastFile.truncate(currentSize);
lastFile.close();
recovery = createRecoveryProtocol();
recovery.run();
}
}
use of org.neo4j.io.fs.StoreChannel in project neo4j by neo4j.
the class RecoveryProtocolTest method createEmptyLogFile.
private void createEmptyLogFile(EphemeralFileSystemAbstraction fsa, long fileNameVersion) throws IOException {
StoreChannel channel = fsa.open(fileNames.getForVersion(fileNameVersion), "w");
channel.close();
}
use of org.neo4j.io.fs.StoreChannel in project neo4j by neo4j.
the class SegmentedRaftLogPartialEntryRecoveryTest method shouldNotAppendAtTheEndOfLogFileWithIncompleteEntries.
@Test
public void shouldNotAppendAtTheEndOfLogFileWithIncompleteEntries() throws Throwable {
// Given
// we use a RaftLog to create a raft log file and then we will chop some bits off the end
SegmentedRaftLog raftLog = createRaftLog(100_000);
raftLog.start();
raftLog.append(new RaftLogEntry(4, new NewLeaderBarrier()));
raftLog.stop();
// We use a temporary RecoveryProtocol to get the file to chop
RecoveryProtocol recovery = createRecoveryProtocol();
State recoveryState = recovery.run();
String logFilename = recoveryState.segments.last().getFilename();
File logFile = new File(logDirectory, logFilename);
StoreChannel lastFile = fsRule.get().open(logFile, "rw");
long currentSize = lastFile.size();
lastFile.close();
// When
// We induce an incomplete entry at the end of the last file
lastFile = fsRule.get().open(logFile, "rw");
lastFile.truncate(currentSize - 1);
lastFile.close();
// We start the raft log again, on the previous log file with truncated last entry.
raftLog = createRaftLog(100_000);
// Recovery will run here
raftLog.start();
// Append an entry
raftLog.append(new RaftLogEntry(4, new NewLeaderBarrier()));
// The log should report as containing only the last entry we've appended
try (RaftLogCursor entryCursor = raftLog.getEntryCursor(0)) {
// There should be exactly one entry, of type NewLeaderBarrier
assertTrue(entryCursor.next());
RaftLogEntry raftLogEntry = entryCursor.get();
assertEquals(NewLeaderBarrier.class, raftLogEntry.content().getClass());
assertFalse(entryCursor.next());
}
}
use of org.neo4j.io.fs.StoreChannel in project neo4j by neo4j.
the class PhysicalFlushableChannel method prepareForFlush.
/**
* External synchronization between this method and close is required so that they aren't called concurrently.
* Currently that's done by acquiring the PhysicalLogFile monitor.
*/
@Override
public Flushable prepareForFlush() throws IOException {
buffer.flip();
StoreChannel channel = this.channel;
try {
channel.writeAll(buffer);
} catch (ClosedChannelException e) {
handleClosedChannelException(e);
}
buffer.clear();
return channel;
}
use of org.neo4j.io.fs.StoreChannel in project neo4j by neo4j.
the class PhysicalLogFile method createLogChannelForVersion.
/**
* Creates a new channel for the specified version, creating the backing file if it doesn't already exist.
* If the file exists then the header is verified to be of correct version. Having an existing file there
* could happen after a previous crash in the middle of rotation, where the new file was created,
* but the incremented log version changed hadn't made it to persistent storage.
*
* @param forVersion log version for the file/channel to create.
* @return {@link PhysicalLogVersionedStoreChannel} for newly created/opened log file.
* @throws IOException if there's any I/O related error.
*/
private PhysicalLogVersionedStoreChannel createLogChannelForVersion(long forVersion) throws IOException {
File toOpen = logFiles.getLogFileForVersion(forVersion);
StoreChannel storeChannel = fileSystem.open(toOpen, "rw");
LogHeader header = readLogHeader(headerBuffer, storeChannel, false, toOpen);
if (header == null) {
// Either the header is not there in full or the file was new. Don't care
long lastTxId = lastCommittedId.get();
writeLogHeader(headerBuffer, forVersion, lastTxId);
logHeaderCache.putHeader(forVersion, lastTxId);
storeChannel.writeAll(headerBuffer);
monitor.opened(toOpen, forVersion, lastTxId, true);
}
byte formatVersion = header == null ? CURRENT_LOG_VERSION : header.logFormatVersion;
return new PhysicalLogVersionedStoreChannel(storeChannel, forVersion, formatVersion);
}
Aggregations