use of com.alipay.sofa.jraft.entity.LogId 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();
}
}
}
use of com.alipay.sofa.jraft.entity.LogId in project sofa-jraft by sofastack.
the class V1Encoder method encode.
@Override
public byte[] encode(final LogEntry log) {
if (log.hasLearners()) {
throw new IllegalArgumentException("V1 log entry encoder doesn't support learners");
}
EntryType type = log.getType();
LogId id = log.getId();
List<PeerId> peers = log.getPeers();
List<PeerId> oldPeers = log.getOldPeers();
ByteBuffer data = log.getData();
// magic number 1 byte
int totalLen = 1;
final int iType = type.getNumber();
final long index = id.getIndex();
final long term = id.getTerm();
// type(4) + index(8) + term(8)
totalLen += 4 + 8 + 8;
int peerCount = 0;
// peer count
totalLen += 4;
final List<String> peerStrs = new ArrayList<>(peerCount);
if (peers != null) {
peerCount = peers.size();
for (final PeerId peer : peers) {
final String peerStr = peer.toString();
// peer len (short in 2 bytes)
// peer str
totalLen += 2 + peerStr.length();
peerStrs.add(peerStr);
}
}
int oldPeerCount = 0;
// old peer count
totalLen += 4;
final List<String> oldPeerStrs = new ArrayList<>(oldPeerCount);
if (oldPeers != null) {
oldPeerCount = oldPeers.size();
for (final PeerId peer : oldPeers) {
final String peerStr = peer.toString();
// peer len (short in 2 bytes)
// peer str
totalLen += 2 + peerStr.length();
oldPeerStrs.add(peerStr);
}
}
final int bodyLen = data != null ? data.remaining() : 0;
totalLen += bodyLen;
final byte[] content = new byte[totalLen];
// {0} magic
content[0] = LogEntryV1CodecFactory.MAGIC;
// 1-5 type
Bits.putInt(content, 1, iType);
// 5-13 index
Bits.putLong(content, 5, index);
// 13-21 term
Bits.putLong(content, 13, term);
// peers
// 21-25 peer count
Bits.putInt(content, 21, peerCount);
int pos = 25;
for (final String peerStr : peerStrs) {
final byte[] ps = AsciiStringUtil.unsafeEncode(peerStr);
Bits.putShort(content, pos, (short) peerStr.length());
System.arraycopy(ps, 0, content, pos + 2, ps.length);
pos += 2 + ps.length;
}
// old peers
// old peers count
Bits.putInt(content, pos, oldPeerCount);
pos += 4;
for (final String peerStr : oldPeerStrs) {
final byte[] ps = AsciiStringUtil.unsafeEncode(peerStr);
Bits.putShort(content, pos, (short) peerStr.length());
System.arraycopy(ps, 0, content, pos + 2, ps.length);
pos += 2 + ps.length;
}
// data
if (data != null) {
System.arraycopy(data.array(), data.position(), content, pos, data.remaining());
}
return content;
}
use of com.alipay.sofa.jraft.entity.LogId in project sofa-jraft by sofastack.
the class V2Encoder method encode.
@Override
public byte[] encode(final LogEntry log) {
Requires.requireNonNull(log, "Null log");
final LogId logId = log.getId();
final PBLogEntry.Builder builder = //
PBLogEntry.newBuilder().setType(//
log.getType()).setIndex(//
logId.getIndex()).setTerm(logId.getTerm());
final List<PeerId> peers = log.getPeers();
if (hasPeers(peers)) {
encodePeers(builder, peers);
}
final List<PeerId> oldPeers = log.getOldPeers();
if (hasPeers(oldPeers)) {
encodeOldPeers(builder, oldPeers);
}
final List<PeerId> learners = log.getLearners();
if (hasPeers(learners)) {
encodeLearners(builder, learners);
}
final List<PeerId> oldLearners = log.getOldLearners();
if (hasPeers(oldLearners)) {
encodeOldLearners(builder, oldLearners);
}
if (log.hasChecksum()) {
builder.setChecksum(log.getChecksum());
}
builder.setData(log.getData() != null ? ZeroByteStringHelper.wrap(log.getData()) : ByteString.EMPTY);
final PBLogEntry pbLogEntry = builder.build();
final int bodyLen = pbLogEntry.getSerializedSize();
final byte[] ret = new byte[LogEntryV2CodecFactory.HEADER_SIZE + bodyLen];
// write header
int i = 0;
for (; i < LogEntryV2CodecFactory.MAGIC_BYTES.length; i++) {
ret[i] = LogEntryV2CodecFactory.MAGIC_BYTES[i];
}
ret[i++] = LogEntryV2CodecFactory.VERSION;
// avoid memory copy for only 3 bytes
for (; i < LogEntryV2CodecFactory.HEADER_SIZE; i++) {
ret[i] = LogEntryV2CodecFactory.RESERVED[i - LogEntryV2CodecFactory.MAGIC_BYTES.length - 1];
}
// write body
writeToByteArray(pbLogEntry, ret, i, bodyLen);
return ret;
}
use of com.alipay.sofa.jraft.entity.LogId in project sofa-jraft by sofastack.
the class TestUtils method mockEntry.
public static LogEntry mockEntry(final int index, final int term, final int dataSize) {
LogEntry entry = new LogEntry(EnumOutter.EntryType.ENTRY_TYPE_NO_OP);
entry.setId(new LogId(index, term));
if (dataSize > 0) {
byte[] bs = new byte[dataSize];
ThreadLocalRandom.current().nextBytes(bs);
entry.setData(ByteBuffer.wrap(bs));
}
return entry;
}
use of com.alipay.sofa.jraft.entity.LogId in project sofa-jraft by sofastack.
the class NodeImpl method bootstrap.
public boolean bootstrap(final BootstrapOptions opts) throws InterruptedException {
if (opts.getLastLogIndex() > 0 && (opts.getGroupConf().isEmpty() || opts.getFsm() == null)) {
LOG.error("Invalid arguments for bootstrap, groupConf={}, fsm={}, lastLogIndex={}.", opts.getGroupConf(), opts.getFsm(), opts.getLastLogIndex());
return false;
}
if (opts.getGroupConf().isEmpty()) {
LOG.error("Bootstrapping an empty node makes no sense.");
return false;
}
Requires.requireNonNull(opts.getServiceFactory(), "Null jraft service factory");
this.serviceFactory = opts.getServiceFactory();
// Term is not an option since changing it is very dangerous
final long bootstrapLogTerm = opts.getLastLogIndex() > 0 ? 1 : 0;
final LogId bootstrapId = new LogId(opts.getLastLogIndex(), bootstrapLogTerm);
this.options = new NodeOptions();
this.raftOptions = this.options.getRaftOptions();
this.metrics = new NodeMetrics(opts.isEnableMetrics());
this.options.setFsm(opts.getFsm());
this.options.setLogUri(opts.getLogUri());
this.options.setRaftMetaUri(opts.getRaftMetaUri());
this.options.setSnapshotUri(opts.getSnapshotUri());
this.configManager = new ConfigurationManager();
// Create fsmCaller at first as logManager needs it to report error
this.fsmCaller = new FSMCallerImpl();
if (!initLogStorage()) {
LOG.error("Fail to init log storage.");
return false;
}
if (!initMetaStorage()) {
LOG.error("Fail to init meta storage.");
return false;
}
if (this.currTerm == 0) {
this.currTerm = 1;
if (!this.metaStorage.setTermAndVotedFor(1, new PeerId())) {
LOG.error("Fail to set term.");
return false;
}
}
if (opts.getFsm() != null && !initFSMCaller(bootstrapId)) {
LOG.error("Fail to init fsm caller.");
return false;
}
final LogEntry entry = new LogEntry(EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION);
entry.getId().setTerm(this.currTerm);
entry.setPeers(opts.getGroupConf().listPeers());
entry.setLearners(opts.getGroupConf().listLearners());
final List<LogEntry> entries = new ArrayList<>();
entries.add(entry);
final BootstrapStableClosure bootstrapDone = new BootstrapStableClosure();
this.logManager.appendEntries(entries, bootstrapDone);
if (!bootstrapDone.await().isOk()) {
LOG.error("Fail to append configuration.");
return false;
}
if (opts.getLastLogIndex() > 0) {
if (!initSnapshotStorage()) {
LOG.error("Fail to init snapshot storage.");
return false;
}
final SynchronizedClosure snapshotDone = new SynchronizedClosure();
this.snapshotExecutor.doSnapshot(snapshotDone);
if (!snapshotDone.await().isOk()) {
LOG.error("Fail to save snapshot, status={}.", snapshotDone.getStatus());
return false;
}
}
if (this.logManager.getFirstLogIndex() != opts.getLastLogIndex() + 1) {
throw new IllegalStateException("First and last log index mismatch");
}
if (opts.getLastLogIndex() > 0) {
if (this.logManager.getLastLogIndex() != opts.getLastLogIndex()) {
throw new IllegalStateException("Last log index mismatch");
}
} else {
if (this.logManager.getLastLogIndex() != opts.getLastLogIndex() + 1) {
throw new IllegalStateException("Last log index mismatch");
}
}
return true;
}
Aggregations