use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class LogManagerImpl method getEntryFromMemory.
protected LogEntry getEntryFromMemory(final long index) {
LogEntry entry = null;
if (!this.logsInMemory.isEmpty()) {
final long firstIndex = this.logsInMemory.peekFirst().getId().getIndex();
final long lastIndex = this.logsInMemory.peekLast().getId().getIndex();
if (lastIndex - firstIndex + 1 != this.logsInMemory.size()) {
throw new IllegalStateException(String.format("lastIndex=%d,firstIndex=%d,logsInMemory=[%s]", lastIndex, firstIndex, descLogsInMemory()));
}
if (index >= firstIndex && index <= lastIndex) {
entry = this.logsInMemory.get((int) (index - firstIndex));
}
}
return entry;
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class LogManagerImpl method checkAndResolveConflict.
@SuppressWarnings("NonAtomicOperationOnVolatileField")
private boolean checkAndResolveConflict(final List<LogEntry> entries, final StableClosure done, final Lock lock) {
final LogEntry firstLogEntry = ArrayDeque.peekFirst(entries);
if (firstLogEntry.getId().getIndex() == 0) {
// to assign indexes to the appending entries
for (int i = 0; i < entries.size(); i++) {
entries.get(i).getId().setIndex(++this.lastLogIndex);
}
return true;
} else {
// |entries|
if (firstLogEntry.getId().getIndex() > this.lastLogIndex + 1) {
Utils.runClosureInThread(done, new Status(RaftError.EINVAL, "There's gap between first_index=%d and last_log_index=%d", firstLogEntry.getId().getIndex(), this.lastLogIndex));
return false;
}
final long appliedIndex = this.appliedId.getIndex();
final LogEntry lastLogEntry = ArrayDeque.peekLast(entries);
if (lastLogEntry.getId().getIndex() <= appliedIndex) {
LOG.warn("Received entries of which the lastLog={} is not greater than appliedIndex={}, return immediately with nothing changed.", lastLogEntry.getId().getIndex(), appliedIndex);
// Replicate old logs before appliedIndex should be considered successfully, response OK.
Utils.runClosureInThread(done);
return false;
}
if (firstLogEntry.getId().getIndex() == this.lastLogIndex + 1) {
// fast path
this.lastLogIndex = lastLogEntry.getId().getIndex();
} else {
// Appending entries overlap the local ones. We should find if there
// is a conflicting index from which we should truncate the local
// ones.
int conflictingIndex = 0;
for (; conflictingIndex < entries.size(); conflictingIndex++) {
if (unsafeGetTerm(entries.get(conflictingIndex).getId().getIndex()) != entries.get(conflictingIndex).getId().getTerm()) {
break;
}
}
if (conflictingIndex != entries.size()) {
if (entries.get(conflictingIndex).getId().getIndex() <= this.lastLogIndex) {
// Truncate all the conflicting entries to make local logs
// consensus with the leader.
unsafeTruncateSuffix(entries.get(conflictingIndex).getId().getIndex() - 1, lock);
}
this.lastLogIndex = lastLogEntry.getId().getIndex();
}
// nothing to do besides releasing all the entries
if (conflictingIndex > 0) {
// Remove duplication
entries.subList(0, conflictingIndex).clear();
}
}
return true;
}
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class LogManagerImpl method descLogsInMemory.
private String descLogsInMemory() {
final StringBuilder sb = new StringBuilder();
boolean wasFirst = true;
for (int i = 0; i < this.logsInMemory.size(); i++) {
LogEntry logEntry = this.logsInMemory.get(i);
if (!wasFirst) {
sb.append(",");
} else {
wasFirst = false;
}
sb.append("<id:(").append(logEntry.getId().getTerm()).append(",").append(logEntry.getId().getIndex()).append("),type:").append(logEntry.getType()).append(">");
}
return sb.toString();
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class LogManagerImpl method getTermFromLogStorage.
private long getTermFromLogStorage(final long index) {
final LogEntry entry = this.logStorage.getEntry(index);
if (entry != null) {
if (this.raftOptions.isEnableLogEntryChecksum() && entry.isCorrupted()) {
// Report error to node and throw exception.
final String msg = String.format("The log entry is corrupted, index=%d, term=%d, expectedChecksum=%d, realChecksum=%d", entry.getId().getIndex(), entry.getId().getTerm(), entry.getChecksum(), entry.checksum());
reportError(RaftError.EIO.getNumber(), msg);
throw new LogEntryCorruptedException(msg);
}
return entry.getId().getTerm();
}
return 0;
}
use of com.alipay.sofa.jraft.entity.LogEntry in project sofa-jraft by sofastack.
the class RocksDBLogStorage method load.
private void load(final ConfigurationManager confManager) {
checkState();
try (final RocksIterator it = this.db.newIterator(this.confHandle, this.totalOrderReadOptions)) {
it.seekToFirst();
while (it.isValid()) {
final byte[] ks = it.key();
final byte[] bs = it.value();
// LogEntry index
if (ks.length == 8) {
final LogEntry entry = this.logEntryDecoder.decode(bs);
if (entry != null) {
if (entry.getType() == EntryType.ENTRY_TYPE_CONFIGURATION) {
final ConfigurationEntry confEntry = new ConfigurationEntry();
confEntry.setId(new LogId(entry.getId().getIndex(), entry.getId().getTerm()));
confEntry.setConf(new Configuration(entry.getPeers(), entry.getLearners()));
if (entry.getOldPeers() != null) {
confEntry.setOldConf(new Configuration(entry.getOldPeers(), entry.getOldLearners()));
}
if (confManager != null) {
confManager.add(confEntry);
}
}
} else {
LOG.warn("Fail to decode conf entry at index {}, the log data is: {}.", Bits.getLong(ks, 0), BytesUtil.toHex(bs));
}
} else {
if (Arrays.equals(FIRST_LOG_IDX_KEY, ks)) {
setFirstLogIndex(Bits.getLong(bs, 0));
truncatePrefixInBackground(0L, this.firstLogIndex);
} else {
LOG.warn("Unknown entry in configuration storage key={}, value={}.", BytesUtil.toHex(ks), BytesUtil.toHex(bs));
}
}
it.next();
}
}
}
Aggregations