use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.
the class NodeImpl method handlePreVoteRequest.
@Override
public Message handlePreVoteRequest(final RequestVoteRequest request) {
boolean doUnlock = true;
this.writeLock.lock();
try {
if (!this.state.isActive()) {
LOG.warn("Node {} is not in active state, currTerm={}.", getNodeId(), this.currTerm);
return //
RaftRpcFactory.DEFAULT.newResponse(raftOptions.getRaftMessagesFactory(), RaftError.EINVAL, "Node %s is not in active state, state %s.", getNodeId(), this.state.name());
}
final PeerId candidateId = new PeerId();
if (!candidateId.parse(request.serverId())) {
LOG.warn("Node {} received PreVoteRequest from {} serverId bad format.", getNodeId(), request.serverId());
return //
RaftRpcFactory.DEFAULT.newResponse(raftOptions.getRaftMessagesFactory(), RaftError.EINVAL, "Parse candidateId failed: %s.", request.serverId());
}
boolean granted = false;
// noinspection ConstantConditions
do {
if (!this.conf.contains(candidateId)) {
LOG.warn("Node {} ignore PreVoteRequest from {} as it is not in conf <{}>.", getNodeId(), request.serverId(), this.conf);
break;
}
if (this.leaderId != null && !this.leaderId.isEmpty() && isCurrentLeaderValid()) {
LOG.info("Node {} ignore PreVoteRequest from {}, term={}, currTerm={}, because the leader {}'s lease is still valid.", getNodeId(), request.serverId(), request.term(), this.currTerm, this.leaderId);
break;
}
if (request.term() < this.currTerm) {
LOG.info("Node {} ignore PreVoteRequest from {}, term={}, currTerm={}.", getNodeId(), request.serverId(), request.term(), this.currTerm);
// A follower replicator may not be started when this node become leader, so we must check it.
checkReplicator(candidateId);
break;
}
// A follower replicator may not be started when this node become leader, so we must check it.
// check replicator state
checkReplicator(candidateId);
doUnlock = false;
this.writeLock.unlock();
final LogId lastLogId = this.logManager.getLastLogId(true);
doUnlock = true;
this.writeLock.lock();
final LogId requestLastLogId = new LogId(request.lastLogIndex(), request.lastLogTerm());
granted = requestLastLogId.compareTo(lastLogId) >= 0;
LOG.info("Node {} received PreVoteRequest from {}, term={}, currTerm={}, granted={}, requestLastLogId={}, lastLogId={}.", getNodeId(), request.serverId(), request.term(), this.currTerm, granted, requestLastLogId, lastLogId);
} while (false);
return raftOptions.getRaftMessagesFactory().requestVoteResponse().term(this.currTerm).granted(granted).build();
} finally {
if (doUnlock) {
this.writeLock.unlock();
}
}
}
use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.
the class NodeImpl method init.
@Override
public boolean init(final NodeOptions opts) {
Requires.requireNonNull(opts, "Null node options");
Requires.requireNonNull(opts.getRaftOptions(), "Null raft options");
Requires.requireNonNull(opts.getServiceFactory(), "Null jraft service factory");
this.serviceFactory = opts.getServiceFactory();
this.options = opts;
this.raftOptions = opts.getRaftOptions();
this.metrics = new NodeMetrics(opts.isEnableMetrics());
this.serverId.setPriority(opts.getElectionPriority());
this.electionTimeoutCounter = 0;
if (opts.getReplicationStateListeners() != null)
this.replicatorStateListeners.addAll(opts.getReplicationStateListeners());
if (this.serverId.getIp().equals(Utils.IP_ANY)) {
LOG.error("Node can't start from IP_ANY.");
return false;
}
// Init timers.
initTimers(opts);
// Init pools.
initPools(opts);
this.configManager = new ConfigurationManager();
applyDisruptor = opts.getNodeApplyDisruptor();
applyQueue = applyDisruptor.subscribe(groupId, new LogEntryAndClosureHandler());
if (this.metrics.getMetricRegistry() != null) {
this.metrics.getMetricRegistry().register("jraft-node-impl-disruptor", new DisruptorMetricSet(this.applyQueue));
}
this.fsmCaller = new FSMCallerImpl();
if (!initLogStorage()) {
LOG.error("Node {} initLogStorage failed.", getNodeId());
return false;
}
if (!initMetaStorage()) {
LOG.error("Node {} initMetaStorage failed.", getNodeId());
return false;
}
if (!initFSMCaller(new LogId(0, 0))) {
LOG.error("Node {} initFSMCaller failed.", getNodeId());
return false;
}
this.ballotBox = new BallotBox();
final BallotBoxOptions ballotBoxOpts = new BallotBoxOptions();
ballotBoxOpts.setWaiter(this.fsmCaller);
ballotBoxOpts.setClosureQueue(this.closureQueue);
if (!this.ballotBox.init(ballotBoxOpts)) {
LOG.error("Node {} init ballotBox failed.", getNodeId());
return false;
}
if (!initSnapshotStorage()) {
LOG.error("Node {} initSnapshotStorage failed.", getNodeId());
return false;
}
final Status st = this.logManager.checkConsistency();
if (!st.isOk()) {
LOG.error("Node {} is initialized with inconsistent log, status={}.", getNodeId(), st);
return false;
}
this.conf = new ConfigurationEntry();
this.conf.setId(new LogId());
// if have log using conf in log, else using conf in options
if (this.logManager.getLastLogIndex() > 0) {
checkAndSetConfiguration(false);
} else {
this.conf.setConf(this.options.getInitialConf());
// initially set to max(priority of all nodes)
this.targetPriority = getMaxPriorityOfNodes(this.conf.getConf().getPeers());
}
if (!this.conf.isEmpty()) {
Requires.requireTrue(this.conf.isValid(), "Invalid conf: %s", this.conf);
} else {
LOG.info("Init node {} with empty conf.", this.serverId);
}
this.replicatorGroup = new ReplicatorGroupImpl();
this.rpcClientService = new DefaultRaftClientService();
final ReplicatorGroupOptions rgOpts = new ReplicatorGroupOptions();
rgOpts.setHeartbeatTimeoutMs(heartbeatTimeout(this.options.getElectionTimeoutMs()));
rgOpts.setElectionTimeoutMs(this.options.getElectionTimeoutMs());
rgOpts.setLogManager(this.logManager);
rgOpts.setBallotBox(this.ballotBox);
rgOpts.setNode(this);
rgOpts.setRaftRpcClientService(this.rpcClientService);
rgOpts.setSnapshotStorage(this.snapshotExecutor != null ? this.snapshotExecutor.getSnapshotStorage() : null);
rgOpts.setRaftOptions(this.raftOptions);
rgOpts.setTimerManager(this.options.getScheduler());
// Adds metric registry to RPC service.
this.options.setMetricRegistry(this.metrics.getMetricRegistry());
if (!this.rpcClientService.init(this.options)) {
LOG.error("Fail to init rpc service.");
return false;
}
this.replicatorGroup.init(new NodeId(this.groupId, this.serverId), rgOpts);
this.readOnlyService = new ReadOnlyServiceImpl();
final ReadOnlyServiceOptions rosOpts = new ReadOnlyServiceOptions();
rosOpts.setGroupId(groupId);
rosOpts.setFsmCaller(this.fsmCaller);
rosOpts.setNode(this);
rosOpts.setRaftOptions(this.raftOptions);
rosOpts.setReadOnlyServiceDisruptor(opts.getReadOnlyServiceDisruptor());
if (!this.readOnlyService.init(rosOpts)) {
LOG.error("Fail to init readOnlyService.");
return false;
}
// set state to follower
this.state = State.STATE_FOLLOWER;
if (LOG.isInfoEnabled()) {
LOG.info("Node {} init, term={}, lastLogId={}, conf={}, oldConf={}.", getNodeId(), this.currTerm, this.logManager.getLastLogId(false), this.conf.getConf(), this.conf.getOldConf());
}
if (this.snapshotExecutor != null && this.options.getSnapshotIntervalSecs() > 0) {
LOG.debug("Node {} start snapshot timer, term={}.", getNodeId(), this.currTerm);
this.snapshotTimer.start();
}
if (!this.conf.isEmpty()) {
stepDown(this.currTerm, false, new Status());
}
// Now the raft node is started , have to acquire the writeLock to avoid race
// conditions
this.writeLock.lock();
if (this.conf.isStable() && this.conf.getConf().size() == 1 && this.conf.getConf().contains(this.serverId)) {
// The group contains only this server which must be the LEADER, trigger
// the timer immediately.
electSelf();
} else {
this.writeLock.unlock();
}
return true;
}
use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.
the class FSMCallerImpl method doSnapshotLoad.
private void doSnapshotLoad(final LoadSnapshotClosure done) {
Requires.requireNonNull(done, "LoadSnapshotClosure is null");
final SnapshotReader reader = done.start();
if (reader == null) {
done.run(new Status(RaftError.EINVAL, "open SnapshotReader failed"));
return;
}
final RaftOutter.SnapshotMeta meta = reader.load();
if (meta == null) {
done.run(new Status(RaftError.EINVAL, "SnapshotReader load meta failed"));
if (reader.getRaftError() == RaftError.EIO) {
final RaftException err = new RaftException(ErrorType.ERROR_TYPE_SNAPSHOT, RaftError.EIO, "Fail to load snapshot meta");
setError(err);
}
return;
}
final LogId lastAppliedId = new LogId(this.lastAppliedIndex.get(), this.lastAppliedTerm);
final LogId snapshotId = new LogId(meta.lastIncludedIndex(), meta.lastIncludedTerm());
if (lastAppliedId.compareTo(snapshotId) > 0) {
done.run(new Status(RaftError.ESTALE, "Loading a stale snapshot last_applied_index=%d last_applied_term=%d snapshot_index=%d snapshot_term=%d", lastAppliedId.getIndex(), lastAppliedId.getTerm(), snapshotId.getIndex(), snapshotId.getTerm()));
return;
}
if (!this.fsm.onSnapshotLoad(reader)) {
done.run(new Status(-1, "StateMachine onSnapshotLoad failed"));
final RaftException e = new RaftException(ErrorType.ERROR_TYPE_STATE_MACHINE, RaftError.ESTATEMACHINE, "StateMachine onSnapshotLoad failed");
setError(e);
return;
}
if (meta.oldPeersList() == null) {
// Joint stage is not supposed to be noticeable by end users.
final Configuration conf = new Configuration();
if (meta.peersList() != null) {
for (String metaPeer : meta.peersList()) {
final PeerId peer = new PeerId();
Requires.requireTrue(peer.parse(metaPeer), "Parse peer failed");
conf.addPeer(peer);
}
}
this.fsm.onConfigurationCommitted(conf);
}
this.lastAppliedIndex.set(meta.lastIncludedIndex());
this.lastAppliedTerm = meta.lastIncludedTerm();
done.run(Status.OK());
}
use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.
the class NodeImpl method logEntryFromMeta.
private LogEntry logEntryFromMeta(final long index, final ByteBuffer allData, final RaftOutter.EntryMeta entry) {
if (entry.type() != EnumOutter.EntryType.ENTRY_TYPE_UNKNOWN) {
final LogEntry logEntry = new LogEntry();
logEntry.setId(new LogId(index, entry.term()));
logEntry.setType(entry.type());
if (entry.hasChecksum())
// since 1.2.6
logEntry.setChecksum(entry.checksum());
final long dataLen = entry.dataLen();
if (dataLen > 0) {
final byte[] bs = new byte[(int) dataLen];
assert allData != null;
allData.get(bs, 0, bs.length);
logEntry.setData(ByteBuffer.wrap(bs));
}
if (entry.peersList() != null) {
if (entry.type() != EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION) {
throw new IllegalStateException("Invalid log entry that contains peers but is not ENTRY_TYPE_CONFIGURATION type: " + entry.type());
}
fillLogEntryPeers(entry, logEntry);
} else if (entry.type() == EnumOutter.EntryType.ENTRY_TYPE_CONFIGURATION) {
throw new IllegalStateException("Invalid log entry that contains zero peers but is ENTRY_TYPE_CONFIGURATION type");
}
return logEntry;
}
return null;
}
use of org.apache.ignite.raft.jraft.entity.LogId in project ignite-3 by apache.
the class BaseLogEntryCodecFactoryTest method testEncodeDecodeWithData.
@Test
public void testEncodeDecodeWithData() {
ByteBuffer buf = ByteBuffer.wrap("hello".getBytes(UTF_8));
LogEntry entry = new LogEntry(EnumOutter.EntryType.ENTRY_TYPE_NO_OP);
entry.setId(new LogId(100, 3));
entry.setChecksum(123456L);
entry.setData(buf);
entry.setPeers(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
entry.setOldPeers(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
entry.setLearners(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
entry.setOldLearners(Arrays.asList(new PeerId("localhost", 99, 1), new PeerId("localhost", 100, 2)));
assertEquals(buf, entry.getData());
byte[] content = this.encoder.encode(entry);
assertNotNull(content);
assertTrue(content.length > 0);
LogEntry nentry = this.decoder.decode(content);
assertNotNull(nentry);
assertEquals(100, nentry.getId().getIndex());
assertEquals(3, nentry.getId().getTerm());
assertEquals(123456L, nentry.getChecksum());
List<PeerId> peers = nentry.getPeers();
assertEquals(2, peers.size());
assertEquals("localhost:99:1", peers.get(0).toString());
assertEquals("localhost:100:2", peers.get(1).toString());
peers = nentry.getOldPeers();
assertEquals(2, peers.size());
assertEquals("localhost:99:1", peers.get(0).toString());
assertEquals("localhost:100:2", peers.get(1).toString());
peers = nentry.getLearners();
assertEquals(2, peers.size());
assertEquals("localhost:99:1", peers.get(0).toString());
assertEquals("localhost:100:2", peers.get(1).toString());
peers = nentry.getOldLearners();
assertEquals(2, peers.size());
assertEquals("localhost:99:1", peers.get(0).toString());
assertEquals("localhost:100:2", peers.get(1).toString());
assertEquals(buf, nentry.getData());
assertEquals(0, nentry.getData().position());
assertEquals(5, nentry.getData().remaining());
}
Aggregations