package com.datastax.oss.driver.internal.core.loadbalancing.helper;
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
import com.datastax.oss.driver.api.core.config.DriverExecutionProfile;
import com.datastax.oss.driver.api.core.metadata.Node;
import com.datastax.oss.driver.internal.core.context.InternalDriverContext;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.UUID;
import net.jcip.annotations.ThreadSafe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ThreadSafe
public class OptionalLocalDcHelper implements LocalDcHelper {
private static final Logger LOG = LoggerFactory.getLogger(OptionalLocalDcHelper.class);
@NonNull protected final InternalDriverContext context;
@NonNull protected final DriverExecutionProfile profile;
@NonNull protected final String logPrefix;
public OptionalLocalDcHelper(
@NonNull InternalDriverContext context,
@NonNull DriverExecutionProfile profile,
@NonNull String logPrefix) {
this.context = context;
this.profile = profile;
this.logPrefix = logPrefix;
}
@Override
@NonNull
public Optional<String> discoverLocalDc(@NonNull Map<UUID, Node> nodes) {
String localDc = context.getLocalDatacenter(profile.getName());
if (localDc != null) {
LOG.debug("[{}] Local DC set programmatically: {}", logPrefix, localDc);
checkLocalDatacenterCompatibility(localDc, context.getMetadataManager().getContactPoints());
return Optional.of(localDc);
} else if (profile.isDefined(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER)) {
localDc = profile.getString(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER);
LOG.debug("[{}] Local DC set from configuration: {}", logPrefix, localDc);
checkLocalDatacenterCompatibility(localDc, context.getMetadataManager().getContactPoints());
return Optional.of(localDc);
} else {
return Optional.empty();
}
}
protected void checkLocalDatacenterCompatibility(
@NonNull String localDc, Set<? extends Node> contactPoints) {
Set<Node> badContactPoints = new LinkedHashSet<>();
for (Node node : contactPoints) {
if (!Objects.equals(localDc, node.getDatacenter())) {
badContactPoints.add(node);
}
}
if (!badContactPoints.isEmpty()) {
LOG.warn(
"[{}] You specified {} as the local DC, but some contact points are from a different DC: {}; "
+ "please provide the correct local DC, or check your contact points",
logPrefix,
localDc,
formatNodesAndDcs(badContactPoints));
}
}
@NonNull
protected String formatNodesAndDcs(Iterable<? extends Node> nodes) {
List<String> l = new ArrayList<>();
for (Node node : nodes) {
l.add(node + "=" + node.getDatacenter());
}
return String.join(", ", l);
}
@NonNull
protected String formatDcs(Iterable<? extends Node> nodes) {
List<String> l = new ArrayList<>();
for (Node node : nodes) {
if (node.getDatacenter() != null) {
l.add(node.getDatacenter());
}
}
return String.join(", ", new TreeSet<>(l));
}
}