// If the requesting candidate is ourself then always vote for ourself. Votes
// for self are done by calling the local node. Note that this obviously
// doesn't make sense for a leader.
else if (request.candidate().equals(context.clusterManager().localNode().member().id())) {
context.lastVotedFor(context.clusterManager().localNode().member().id());
context.events().voteCast().handle(new VoteCastEvent(context.currentTerm(), context.clusterManager().localNode().member()));
logger().debug("{} - Accepted {}: candidate is the local node", context.clusterManager().localNode(), request);
return new PollResponse(request.id(), context.currentTerm(), true);
}
// If the requesting candidate is not a known member of the cluster (to this
// node) then don't vote for it. Only vote for candidates that we know about.
else if (context.clusterManager().node(request.candidate()) == null) {
logger().debug("{} - Rejected {}: candidate is not known do the local node", context.clusterManager().localNode(), request);
return new PollResponse(request.id(), context.currentTerm(), false);
}
// If we've already voted for someone else then don't vote again.
else if (context.lastVotedFor() == null || context.lastVotedFor().equals(request.candidate())) {
// If the log is empty then vote for the candidate.
if (context.log().isEmpty()) {
context.lastVotedFor(request.candidate());
context.events().voteCast().handle(new VoteCastEvent(context.currentTerm(), context.clusterManager().node(request.candidate()).member()));
logger().debug("{} - Accepted {}: candidate's log is up-to-date", context.clusterManager().localNode(), request);
return new PollResponse(request.id(), context.currentTerm(), true);
} else {
// Otherwise, load the last entry in the log. The last entry should be
// at least as up to date as the candidates entry and term.
synchronized (context.log()) {
long lastIndex = context.log().lastIndex();
CopycatEntry entry = context.log().getEntry(lastIndex);
if (entry == null) {
context.lastVotedFor(request.candidate());
context.events()
.voteCast()
.handle(new VoteCastEvent(context.currentTerm(), context.clusterManager()
.node(request.candidate())
.member()));
logger().debug("{} - Accepted {}: candidate's log is up-to-date", context.clusterManager().localNode(), request);
return new PollResponse(request.id(), context.currentTerm(), true);
}
long lastTerm = entry.term();
if (request.lastLogIndex() >= lastIndex) {
if (request.lastLogTerm() >= lastTerm) {
context.lastVotedFor(request.candidate());
context.events()
.voteCast()
.handle(new VoteCastEvent(context.currentTerm(), context.clusterManager()
.node(request.candidate())
.member()));
logger().debug("{} - Accepted {}: candidate's log is up-to-date", context.clusterManager().localNode(), request);
return new PollResponse(request.id(), context.currentTerm(), true);
} else {