* Pings the replica.
*/
synchronized CompletableFuture<Long> ping(long index) {
if (!open) {
CompletableFuture<Long> future = new CompletableFuture<>();
future.completeExceptionally(new CopycatException("Connection not open"));
return future;
}
if (index > matchIndex) {
return replicate(index);
}
CompletableFuture<Long> future = new CompletableFuture<>();
if (!pingFutures.isEmpty() && pingFutures.lastKey() >= index) {
return pingFutures.lastEntry().getValue();
}
pingFutures.put(index, future);
PingRequest request = new PingRequest(state.nextCorrelationId(), state.currentTerm(), state.cluster().localMember().id(), index, log.containsEntry(index) ? log.<CopycatEntry>getEntry(index).term() : 0, state.commitIndex());
LOGGER.debug("{} - Sent {} to {}", state.clusterManager().localNode(), request, node);
node.client().ping(request).whenComplete((response, error) -> {
if (error != null) {
triggerPingFutures(index, error);
} else {
LOGGER.debug("{} - Received {} from {}", state.clusterManager().localNode(), response, node);
if (response.status().equals(Response.Status.OK)) {
if (response.term() > state.currentTerm()) {
state.currentTerm(response.term());
state.currentLeader(null);
state.transition(FollowerController.class);
triggerPingFutures(index, new CopycatException("Not the leader"));
} else if (!response.succeeded()) {
triggerPingFutures(index, new ProtocolException("Replica not in sync"));
} else {
triggerPingFutures(index);
}