use of org.apache.ratis.util.AutoCloseableLock in project incubator-ratis by apache.
the class SegmentedRaftLog method loadLogSegments.
private void loadLogSegments(long lastIndexInSnapshot, Consumer<LogEntryProto> logConsumer) throws IOException {
try (AutoCloseableLock writeLock = writeLock()) {
final List<LogSegmentPath> paths = LogSegmentPath.getLogSegmentPaths(storage);
int i = 0;
for (LogSegmentPath pi : paths) {
// During the initial loading, we can only confirm the committed
// index based on the snapshot. This means if a log segment is not kept
// in cache after the initial loading, later we have to load its content
// again for updating the state machine.
// TODO we should let raft peer persist its committed index periodically
// so that during the initial loading we can apply part of the log
// entries to the state machine
boolean keepEntryInCache = (paths.size() - i++) <= cache.getMaxCachedSegments();
final Timer.Context loadSegmentContext = getRaftLogMetrics().getRaftLogLoadSegmentTimer().time();
cache.loadSegment(pi, keepEntryInCache, logConsumer);
loadSegmentContext.stop();
}
// committing the log and taking snapshot)
if (!cache.isEmpty() && cache.getEndIndex() < lastIndexInSnapshot) {
LOG.warn("End log index {} is smaller than last index in snapshot {}", cache.getEndIndex(), lastIndexInSnapshot);
purgeImpl(lastIndexInSnapshot);
}
}
}
use of org.apache.ratis.util.AutoCloseableLock in project incubator-ratis by apache.
the class SegmentedRaftLog method appendImpl.
@Override
public List<CompletableFuture<Long>> appendImpl(LogEntryProto... entries) {
checkLogState();
if (entries == null || entries.length == 0) {
return Collections.emptyList();
}
try (AutoCloseableLock writeLock = writeLock()) {
final TruncateIndices ti = cache.computeTruncateIndices(server::notifyTruncatedLogEntry, entries);
final long truncateIndex = ti.getTruncateIndex();
final int index = ti.getArrayIndex();
LOG.debug("truncateIndex={}, arrayIndex={}", truncateIndex, index);
final List<CompletableFuture<Long>> futures;
if (truncateIndex != -1) {
futures = new ArrayList<>(entries.length - index + 1);
futures.add(truncate(truncateIndex));
} else {
futures = new ArrayList<>(entries.length - index);
}
for (int i = index; i < entries.length; i++) {
futures.add(appendEntry(entries[i]));
}
return futures;
}
}
use of org.apache.ratis.util.AutoCloseableLock in project incubator-ratis by apache.
the class SegmentedRaftLog method appendEntryImpl.
@Override
protected CompletableFuture<Long> appendEntryImpl(LogEntryProto entry) {
final Timer.Context context = getRaftLogMetrics().getRaftLogAppendEntryTimer().time();
checkLogState();
if (LOG.isTraceEnabled()) {
LOG.trace("{}: appendEntry {}", getName(), LogProtoUtils.toLogEntryString(entry));
}
try (AutoCloseableLock writeLock = writeLock()) {
validateLogEntry(entry);
final LogSegment currentOpenSegment = cache.getOpenSegment();
if (currentOpenSegment == null) {
cache.addOpenSegment(entry.getIndex());
fileLogWorker.startLogSegment(entry.getIndex());
} else if (isSegmentFull(currentOpenSegment, entry)) {
cache.rollOpenSegment(true);
fileLogWorker.rollLogSegment(currentOpenSegment);
} else if (currentOpenSegment.numOfEntries() > 0 && currentOpenSegment.getLastTermIndex().getTerm() != entry.getTerm()) {
// the term changes
final long currentTerm = currentOpenSegment.getLastTermIndex().getTerm();
Preconditions.assertTrue(currentTerm < entry.getTerm(), "open segment's term %s is larger than the new entry's term %s", currentTerm, entry.getTerm());
cache.rollOpenSegment(true);
fileLogWorker.rollLogSegment(currentOpenSegment);
}
// TODO(runzhiwang): If there is performance problem, start a daemon thread to checkAndEvictCache
checkAndEvictCache();
// If the entry has state machine data, then the entry should be inserted
// to statemachine first and then to the cache. Not following the order
// will leave a spurious entry in the cache.
CompletableFuture<Long> writeFuture = fileLogWorker.writeLogEntry(entry).getFuture();
if (stateMachineCachingEnabled) {
// The stateMachineData will be cached inside the StateMachine itself.
cache.appendEntry(LogProtoUtils.removeStateMachineData(entry), LogSegment.Op.WRITE_CACHE_WITH_STATE_MACHINE_CACHE);
} else {
cache.appendEntry(entry, LogSegment.Op.WRITE_CACHE_WITHOUT_STATE_MACHINE_CACHE);
}
return writeFuture;
} catch (Exception e) {
LOG.error("{}: Failed to append {}", getName(), LogProtoUtils.toLogEntryString(entry), e);
throw e;
} finally {
context.stop();
}
}
use of org.apache.ratis.util.AutoCloseableLock in project incubator-ratis by apache.
the class SegmentedRaftLog method purgeImpl.
@Override
protected CompletableFuture<Long> purgeImpl(long index) {
try (AutoCloseableLock writeLock = writeLock()) {
SegmentedRaftLogCache.TruncationSegments ts = cache.purge(index);
updateSnapshotIndexFromStateMachine();
LOG.debug("purging segments:{}", ts);
if (ts != null) {
Task task = fileLogWorker.purge(ts);
return task.getFuture();
}
}
return CompletableFuture.completedFuture(index);
}
use of org.apache.ratis.util.AutoCloseableLock in project incubator-ratis by apache.
the class MemoryRaftLog method appendImpl.
@Override
public List<CompletableFuture<Long>> appendImpl(LogEntryProto... logEntryProtos) {
checkLogState();
if (logEntryProtos == null || logEntryProtos.length == 0) {
return Collections.emptyList();
}
try (AutoCloseableLock writeLock = writeLock()) {
// Before truncating the entries, we first need to check if some
// entries are duplicated. If the leader sends entry 6, entry 7, then
// entry 6 again, without this check the follower may truncate entry 7
// when receiving entry 6 again. Then before the leader detects this
// truncation in the next appendEntries RPC, leader may think entry 7 has
// been committed but in the system the entry has not been committed to
// the quorum of peers' disks.
boolean toTruncate = false;
int truncateIndex = (int) logEntryProtos[0].getIndex();
int index = 0;
for (; truncateIndex < getNextIndex() && index < logEntryProtos.length; index++, truncateIndex++) {
if (this.entries.get(truncateIndex).getTerm() != logEntryProtos[index].getTerm()) {
toTruncate = true;
break;
}
}
final List<CompletableFuture<Long>> futures;
if (toTruncate) {
futures = new ArrayList<>(logEntryProtos.length - index + 1);
futures.add(truncate(truncateIndex));
} else {
futures = new ArrayList<>(logEntryProtos.length - index);
}
for (int i = index; i < logEntryProtos.length; i++) {
this.entries.add(logEntryProtos[i]);
futures.add(CompletableFuture.completedFuture(logEntryProtos[i].getIndex()));
}
return futures;
}
}
Aggregations