use of org.apache.ratis.server.protocol.TermIndex in project incubator-ratis by apache.
the class LeaderElection method askForVotes.
/**
* After a peer changes its role to candidate, it invokes this method to
* send out requestVote rpc to all other peers.
*/
private void askForVotes() throws InterruptedException, IOException {
final ServerState state = server.getState();
while (running && server.isCandidate()) {
// one round of requestVotes
final long electionTerm;
synchronized (server) {
electionTerm = state.initElection();
server.getState().persistMetadata();
}
LOG.info(state.getSelfId() + ": begin an election in Term " + electionTerm);
TermIndex lastEntry = state.getLog().getLastEntryTermIndex();
if (lastEntry == null) {
// lastEntry may need to be derived from snapshot
SnapshotInfo snapshot = state.getLatestSnapshot();
if (snapshot != null) {
lastEntry = snapshot.getTermIndex();
}
}
final ResultAndTerm r;
if (others.isEmpty()) {
r = new ResultAndTerm(Result.PASSED, electionTerm);
} else {
try {
initExecutor();
int submitted = submitRequests(electionTerm, lastEntry);
r = waitForResults(electionTerm, submitted);
} finally {
if (executor != null) {
executor.shutdown();
}
}
}
synchronized (server) {
if (electionTerm != state.getCurrentTerm() || !running || !server.isCandidate()) {
// term already passed or no longer a candidate.
return;
}
switch(r.result) {
case PASSED:
server.changeToLeader();
return;
case SHUTDOWN:
LOG.info("{} received shutdown response when requesting votes.", server.getId());
server.getProxy().close();
return;
case REJECTED:
case DISCOVERED_A_NEW_TERM:
final long term = r.term > server.getState().getCurrentTerm() ? r.term : server.getState().getCurrentTerm();
server.changeToFollower(term, true);
return;
case TIMEOUT:
}
}
}
}
use of org.apache.ratis.server.protocol.TermIndex in project incubator-ratis by apache.
the class RaftServerImpl method installSnapshot.
@Override
public InstallSnapshotReplyProto installSnapshot(InstallSnapshotRequestProto request) throws IOException {
final RaftRpcRequestProto r = request.getServerRequest();
final RaftPeerId leaderId = RaftPeerId.valueOf(r.getRequestorId());
final RaftGroupId leaderGroupId = ProtoUtils.toRaftGroupId(r.getRaftGroupId());
CodeInjectionForTesting.execute(INSTALL_SNAPSHOT, getId(), leaderId, request);
LOG.debug("{}: receive installSnapshot({})", getId(), request);
assertLifeCycleState(STARTING, RUNNING);
assertGroup(leaderId, leaderGroupId);
final long currentTerm;
final long leaderTerm = request.getLeaderTerm();
final TermIndex lastTermIndex = ServerProtoUtils.toTermIndex(request.getTermIndex());
final long lastIncludedIndex = lastTermIndex.getIndex();
synchronized (this) {
final boolean recognized = state.recognizeLeader(leaderId, leaderTerm);
currentTerm = state.getCurrentTerm();
if (!recognized) {
final InstallSnapshotReplyProto reply = ServerProtoUtils.toInstallSnapshotReplyProto(leaderId, getId(), groupId, currentTerm, request.getRequestIndex(), InstallSnapshotResult.NOT_LEADER);
LOG.debug("{}: do not recognize leader for installing snapshot." + " Reply: {}", getId(), reply);
return reply;
}
changeToFollower(leaderTerm, true);
state.setLeader(leaderId, "installSnapshot");
if (lifeCycle.getCurrentState() == RUNNING) {
heartbeatMonitor.updateLastRpcTime(true);
}
// Check and append the snapshot chunk. We simply put this in lock
// considering a follower peer requiring a snapshot installation does not
// have a lot of requests
Preconditions.assertTrue(state.getLog().getNextIndex() <= lastIncludedIndex, "%s log's next id is %s, last included index in snapshot is %s", getId(), state.getLog().getNextIndex(), lastIncludedIndex);
// TODO: We should only update State with installed snapshot once the request is done.
state.installSnapshot(request);
// re-load the state machine if this is the last chunk
if (request.getDone()) {
state.reloadStateMachine(lastIncludedIndex, leaderTerm);
}
if (lifeCycle.getCurrentState() == RUNNING) {
heartbeatMonitor.updateLastRpcTime(false);
}
}
if (request.getDone()) {
LOG.info("{}: successfully install the whole snapshot-{}", getId(), lastIncludedIndex);
}
return ServerProtoUtils.toInstallSnapshotReplyProto(leaderId, getId(), groupId, currentTerm, request.getRequestIndex(), InstallSnapshotResult.SUCCESS);
}
use of org.apache.ratis.server.protocol.TermIndex in project incubator-ratis by apache.
the class ServerState method isLogUpToDate.
boolean isLogUpToDate(TermIndex candidateLastEntry) {
TermIndex local = log.getLastEntryTermIndex();
// need to take into account snapshot
SnapshotInfo snapshot = server.getStateMachine().getLatestSnapshot();
if (local == null && snapshot == null) {
return true;
} else if (candidateLastEntry == null) {
return false;
}
if (local == null || (snapshot != null && snapshot.getIndex() > local.getIndex())) {
local = snapshot.getTermIndex();
}
return local.compareTo(candidateLastEntry) <= 0;
}
use of org.apache.ratis.server.protocol.TermIndex in project incubator-ratis by apache.
the class MemoryRaftLog method getEntries.
@Override
public TermIndex[] getEntries(long startIndex, long endIndex) {
checkLogState();
try (AutoCloseableLock readLock = readLock()) {
final int from = (int) startIndex;
if (startIndex >= entries.size()) {
return null;
}
final int to = (int) Math.min(entries.size(), endIndex);
TermIndex[] ti = new TermIndex[to - from];
for (int i = 0; i < ti.length; i++) {
ti[i] = TermIndex.newTermIndex(entries.get(i).getTerm(), entries.get(i).getIndex());
}
return ti;
}
}
use of org.apache.ratis.server.protocol.TermIndex in project incubator-ratis by apache.
the class RaftLog method updateLastCommitted.
/**
* Update the last committed index.
* @param majorityIndex the index that has achieved majority.
* @param currentTerm the current term.
* @return true if update is applied; otherwise, return false, i.e. no update required.
*/
public boolean updateLastCommitted(long majorityIndex, long currentTerm) {
try (AutoCloseableLock writeLock = writeLock()) {
if (lastCommitted.get() < majorityIndex) {
// Only update last committed index for current term. See ยง5.4.2 in
// paper for details.
final TermIndex entry = getTermIndex(majorityIndex);
if (entry != null && entry.getTerm() == currentTerm) {
LOG.debug("{}: Updating lastCommitted to {}", selfId, majorityIndex);
lastCommitted.set(majorityIndex);
return true;
}
}
}
return false;
}
Aggregations