use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class FSMCallerImpl method doCommitted.
private void doCommitted(final long committedIndex) {
if (!this.error.getStatus().isOk()) {
return;
}
final long lastAppliedIndex = this.lastAppliedIndex.get();
// We can tolerate the disorder of committed_index
if (lastAppliedIndex >= committedIndex) {
return;
}
final long startMs = Utils.monotonicMs();
try {
final List<Closure> closures = new ArrayList<>();
final List<TaskClosure> taskClosures = new ArrayList<>();
final long firstClosureIndex = this.closureQueue.popClosureUntil(committedIndex, closures, taskClosures);
// Calls TaskClosure#onCommitted if necessary
onTaskCommitted(taskClosures);
Requires.requireTrue(firstClosureIndex >= 0, "Invalid firstClosureIndex");
final IteratorImpl iterImpl = new IteratorImpl(this.fsm, this.logManager, closures, firstClosureIndex, lastAppliedIndex, committedIndex, this.applyingIndex);
while (iterImpl.isGood()) {
final LogEntry logEntry = iterImpl.entry();
if (logEntry.getType() != EnumOutter.EntryType.ENTRY_TYPE_DATA) {
if (logEntry.getType() == EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION) {
if (logEntry.getOldPeers() != null && !logEntry.getOldPeers().isEmpty()) {
// Joint stage is not supposed to be noticeable by end users.
this.fsm.onConfigurationCommitted(new Configuration(iterImpl.entry().getPeers()));
}
}
if (iterImpl.done() != null) {
// For other entries, we have nothing to do besides flush the
// pending tasks and run this closure to notify the caller that the
// entries before this one were successfully committed and applied.
iterImpl.done().run(Status.OK());
}
iterImpl.next();
continue;
}
// Apply data task to user state machine
doApplyTasks(iterImpl);
}
if (iterImpl.hasError()) {
setError(iterImpl.getError());
iterImpl.runTheRestClosureWithError();
}
final long lastIndex = iterImpl.getIndex() - 1;
final long lastTerm = this.logManager.getTerm(lastIndex);
final LogId lastAppliedId = new LogId(lastIndex, lastTerm);
this.lastAppliedIndex.set(lastIndex);
this.lastAppliedTerm = lastTerm;
this.logManager.setAppliedId(lastAppliedId);
notifyLastAppliedIndexUpdated(lastIndex);
} finally {
this.nodeMetrics.recordLatency("fsm-commit", Utils.monotonicMs() - startMs);
}
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class RocksDBLogStorage method getEntry.
@Override
public LogEntry getEntry(final long index) {
this.readLock.lock();
try {
if (this.hasLoadFirstLogIndex && index < this.firstLogIndex) {
return null;
}
final byte[] keyBytes = getKeyBytes(index);
final byte[] bs = onDataGet(index, getValueFromRocksDB(keyBytes));
if (bs != null) {
final LogEntry entry = this.logEntryDecoder.decode(bs);
if (entry != null) {
return entry;
} else {
LOG.error("Bad log entry format for index={}, the log data is: {}.", index, BytesUtil.toHex(bs));
// invalid data remove? TODO
return null;
}
}
} catch (final RocksDBException | IOException e) {
LOG.error("Fail to get log entry at index {} in data path: {}.", index, this.path, e);
} finally {
this.readLock.unlock();
}
return null;
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class RocksDBLogStorage method reset.
@Override
public boolean reset(final long nextLogIndex) {
if (nextLogIndex <= 0) {
throw new IllegalArgumentException("Invalid next log index.");
}
this.writeLock.lock();
try (final Options opt = new Options()) {
LogEntry entry = getEntry(nextLogIndex);
closeDB();
try {
RocksDB.destroyDB(this.path, opt);
onReset(nextLogIndex);
if (initAndLoad(null)) {
if (entry == null) {
entry = new LogEntry();
entry.setType(EntryType.ENTRY_TYPE_NO_OP);
entry.setId(new LogId(nextLogIndex, 0));
LOG.warn("Entry not found for nextLogIndex {} when reset in data path: {}.", nextLogIndex, this.path);
}
return appendEntry(entry);
} else {
return false;
}
} catch (final RocksDBException e) {
LOG.error("Fail to reset next log index.", e);
return false;
}
} finally {
this.writeLock.unlock();
}
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class LogManagerImpl method appendToStorage.
private LogId appendToStorage(final List<LogEntry> toAppend) {
LogId lastId = null;
if (!this.hasError) {
final long startMs = Utils.monotonicMs();
final int entriesCount = toAppend.size();
this.nodeMetrics.recordSize("append-logs-count", entriesCount);
try {
int writtenSize = 0;
for (int i = 0; i < entriesCount; i++) {
final LogEntry entry = toAppend.get(i);
writtenSize += entry.getData() != null ? entry.getData().remaining() : 0;
}
this.nodeMetrics.recordSize("append-logs-bytes", writtenSize);
final int nAppent = this.logStorage.appendEntries(toAppend);
if (nAppent != entriesCount) {
LOG.error("**Critical error**, fail to appendEntries, nAppent={}, toAppend={}", nAppent, toAppend.size());
reportError(RaftError.EIO.getNumber(), "Fail to append log entries");
}
if (nAppent > 0) {
lastId = toAppend.get(nAppent - 1).getId();
}
toAppend.clear();
} finally {
this.nodeMetrics.recordLatency("append-logs", Utils.monotonicMs() - startMs);
}
}
return lastId;
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class LogManagerImpl method unsafeGetTerm.
private long unsafeGetTerm(final long index) {
if (index == 0) {
return 0;
}
final LogId lss = this.lastSnapshotId;
if (index == lss.getIndex()) {
return lss.getTerm();
}
if (index > this.lastLogIndex || index < this.firstLogIndex) {
return 0;
}
final LogEntry entry = getEntryFromMemory(index);
if (entry != null) {
return entry.getId().getTerm();
}
return getTermFromLogStorage(index);
}
Aggregations