package com.mongodb;
import com.mongodb.connection.ClusterDescription;
import com.mongodb.connection.ServerDescription;
import org.bson.BsonDocument;
import org.bson.BsonString;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import static java.lang.Float.compare;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
public class FastestPingTimeReadPreference extends ReadPreference {
private static final Logger LOGGER = LoggerFactory.getLogger(FastestPingTimeReadPreference.class);
@Override
public boolean isSlaveOk() {
return true;
}
@Override
public String getName() {
return "nearestNode";
}
@Override
public BsonDocument toDocument() {
return new BsonDocument("mode", new BsonString(getName()));
}
@Override
public List<ServerDescription> choose(ClusterDescription clusterDescription) {
List<ServerDescription> nodes = clusterDescription.getAnyPrimaryOrSecondary();
ServerDescription nearestNode = selectNearestQueryableNode(nodes);
if (nearestNode == null) {
LOGGER.debug("Could not find any mongodb server.");
return emptyList();
}
if (LOGGER.isTraceEnabled()) {
StringBuilder buffer = new StringBuilder();
for (ServerDescription node : nodes) {
if (!node.equals(nearestNode)) {
buffer.append("[");
buffer.append(node.getAddress().getHost());
buffer.append("/");
buffer.append(node.getRoundTripTimeNanos());
buffer.append("] ");
}
}
String choosenNode = nearestNode.getAddress().getHost() + "/" + nearestNode.getRoundTripTimeNanos();
LOGGER.trace("take {} as mongodb host. other {}", choosenNode, buffer.toString());
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("take {} as mongodb host", nearestNode.getAddress().getHost());
}
}
return singletonList(nearestNode);
}
private static ServerDescription selectNearestQueryableNode(final List<ServerDescription> nodeSet) {
ServerDescription nearest = null;
for (ServerDescription node : nodeSet) {
if (node.isOk()) {
nearest = calculateNearest(nearest, node);
}
}
return nearest;
}
private static ServerDescription calculateNearest(final ServerDescription nodeA, final ServerDescription nodeB) {
if (nodeA == null) {
return nodeB;
}
if (compare(nodeA.getRoundTripTimeNanos(), nodeB.getRoundTripTimeNanos()) > 0) {
return nodeB;
}
return nodeA;
}
}