in ratis-server/src/main/java/org/apache/ratis/server/impl/RaftServerImpl.java [1470:1517]
private RequestVoteReplyProto requestVote(Phase phase,
RaftPeerId candidateId, RaftGroupId candidateGroupId,
long candidateTerm, TermIndex candidateLastEntry) throws IOException {
CodeInjectionForTesting.execute(REQUEST_VOTE, getId(),
candidateId, candidateTerm, candidateLastEntry);
LOG.info("{}: receive requestVote({}, {}, {}, {}, {})",
getMemberId(), phase, candidateId, candidateGroupId, candidateTerm, candidateLastEntry);
assertLifeCycleState(LifeCycle.States.RUNNING);
assertGroup(getMemberId(), candidateId, candidateGroupId);
boolean shouldShutdown = false;
final RequestVoteReplyProto reply;
CompletableFuture<Void> future = null;
synchronized (this) {
// Check life cycle state again to avoid the PAUSING/PAUSED state.
assertLifeCycleState(LifeCycle.States.RUNNING);
final VoteContext context = new VoteContext(this, phase, candidateId);
final RaftPeer candidate = context.recognizeCandidate(candidateTerm);
final boolean voteGranted = context.decideVote(candidate, candidateLastEntry);
if (candidate != null && phase == Phase.ELECTION) {
// change server state in the ELECTION phase
final AtomicBoolean termUpdated = new AtomicBoolean();
future = changeToFollower(candidateTerm, true, false, "candidate:" + candidateId, termUpdated);
if (voteGranted) {
state.grantVote(candidate.getId());
}
if (termUpdated.get() || voteGranted) {
state.persistMetadata(); // sync metafile
}
}
if (voteGranted) {
role.getFollowerState().ifPresent(fs -> fs.updateLastRpcTime(FollowerState.UpdateType.REQUEST_VOTE));
} else if(shouldSendShutdown(candidateId, candidateLastEntry)) {
shouldShutdown = true;
}
reply = toRequestVoteReplyProto(candidateId, getMemberId(),
voteGranted, state.getCurrentTerm(), shouldShutdown);
if (LOG.isInfoEnabled()) {
LOG.info("{} replies to {} vote request: {}. Peer's state: {}",
getMemberId(), phase, toRequestVoteReplyString(reply), state);
}
}
if (future != null) {
future.join();
}
return reply;
}