// Send vote requests to all nodes. The vote request that is sent
// to this node will be automatically successful.
// First check if the quorum is null. If the quorum isn't null then that
// indicates that another vote is already going on.
final Quorum quorum = new Quorum((int) Math.floor(context.clusterManager().nodes().size() / 2) + 1, (elected) -> {
complete.set(true);
if (elected) {
context.transition(LeaderController.class);
} else {
context.transition(FollowerController.class);
}
}).countSelf();
// First, load the last log entry to get its term. We load the entry
// by its index since the index is required by the protocol.
final long lastIndex = context.log().lastIndex();
CopycatEntry lastEntry = context.log().getEntry(lastIndex);
// Once we got the last log term, iterate through each current member
// of the cluster and poll each member for a vote.
LOGGER.info("{} - Polling members {}", context.clusterManager().localNode(), context.clusterManager().cluster().remoteMembers());
final long lastTerm = lastEntry != null ? lastEntry.term() : 0;
for (RemoteNode<?> node : (Set<RemoteNode<?>>) context.clusterManager().remoteNodes()) {
final ProtocolClient client = node.client();
client.connect().whenComplete((result1, error1) -> {
if (error1 != null) {
quorum.fail();
} else {
LOGGER.debug("{} - Polling {}", context.clusterManager().localNode(), node.member());
client.poll(new PollRequest(context.nextCorrelationId(), context.currentTerm(), context.clusterManager()
.localNode()
.member()
.id(), lastIndex, lastTerm)).whenComplete((result2, error2) -> {
client.close();
if (!complete.get()) {
if (error2 != null) {
LOGGER.warn(context.clusterManager().localNode().toString(), error2);
quorum.fail();
} else if (!result2.voteGranted()) {
LOGGER.info("{} - Received rejected vote from {}", context.clusterManager().localNode(), node.member());
quorum.fail();
} else if (result2.term() != context.currentTerm()) {
LOGGER.info("{} - Received successful vote for a different term from {}", context.clusterManager()
.localNode(), node.member());
quorum.fail();
} else {
LOGGER.info("{} - Received successful vote from {}", context.clusterManager()
.localNode(), node.member());
quorum.succeed();
}
}
});
}
});