One use case of this feature is that if the original contact point is defined by hostname
+ * and its IP address changes then setting this to {@code true} allows trying reconnecting to the
+ * new IP if all connection was lost.
+ */
+ public QueryOptions setAddOriginalContactsToReconnectionPlan(boolean enabled) {
+ this.addOriginalContactsToReconnectionPlan = enabled;
+ return this;
+ }
+
+ public boolean shouldAddOriginalContactsToReconnectionPlan() {
+ return this.addOriginalContactsToReconnectionPlan;
+ }
+
@Override
public boolean equals(Object that) {
if (that == null || !(that instanceof QueryOptions)) {
diff --git a/driver-core/src/test/java/com/datastax/driver/core/CCMBridge.java b/driver-core/src/test/java/com/datastax/driver/core/CCMBridge.java
index 4c9ba61fc57..dc9b807c023 100644
--- a/driver-core/src/test/java/com/datastax/driver/core/CCMBridge.java
+++ b/driver-core/src/test/java/com/datastax/driver/core/CCMBridge.java
@@ -949,6 +949,7 @@ public static class Builder {
private static final Pattern RANDOM_PORT_PATTERN = Pattern.compile(RANDOM_PORT);
private String ipPrefix = TestUtils.IP_PREFIX;
+ private String providedClusterName = null;
int[] nodes = {1};
private int[] jmxPorts = {};
private boolean start = true;
@@ -991,6 +992,15 @@ public Builder withSniProxy() {
return this;
}
+ /**
+ * Builder takes care of naming and numbering clusters on its own. Use if you really need a
+ * specific name
+ */
+ public Builder withClusterName(String clusterName) {
+ this.providedClusterName = clusterName;
+ return this;
+ }
+
/** Enables SSL encryption. */
public Builder withSSL() {
cassandraConfiguration.put("client_encryption_options.enabled", "true");
@@ -1115,6 +1125,8 @@ public CCMBridge build() {
// be careful NOT to alter internal state (hashCode/equals) during build!
String clusterName = TestUtils.generateIdentifier("ccm_");
+ if (providedClusterName != null) clusterName = providedClusterName;
+
VersionNumber dseVersion;
VersionNumber cassandraVersion;
boolean versionConfigured = this.version != null;
diff --git a/driver-core/src/test/java/com/datastax/driver/core/DnsEndpointTests.java b/driver-core/src/test/java/com/datastax/driver/core/DnsEndpointTests.java
new file mode 100644
index 00000000000..150f7a3a2dc
--- /dev/null
+++ b/driver-core/src/test/java/com/datastax/driver/core/DnsEndpointTests.java
@@ -0,0 +1,105 @@
+package com.datastax.driver.core;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.testng.Assert.assertTrue;
+
+import java.net.InetSocketAddress;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.Test;
+
+public class DnsEndpointTests {
+
+ private static final Logger logger = LoggerFactory.getLogger(DnsEndpointTests.class);
+
+ @Test(groups = "long")
+ public void replace_cluster_test() {
+ // Configure host resolution
+ MappedHostResolverProvider.addResolverEntry("control.reconnect.test", "127.1.1.1");
+
+ Cluster cluster = null;
+ Session session = null;
+ CCMBridge bridgeA = null;
+ try {
+ bridgeA =
+ CCMBridge.builder()
+ .withNodes(1)
+ .withIpPrefix("127.1.1.")
+ .withBinaryPort(9042)
+ .withClusterName("same_name")
+ .build();
+ bridgeA.start();
+
+ cluster =
+ Cluster.builder()
+ .addContactPointsWithPorts(
+ InetSocketAddress.createUnresolved("control.reconnect.test", 9042))
+ .withPort(9042)
+ .withoutAdvancedShardAwareness()
+ .withQueryOptions(new QueryOptions().setAddOriginalContactsToReconnectionPlan(true))
+ .build();
+ session = cluster.connect();
+
+ ResultSet rs = session.execute("select * from system.local");
+ Row row = rs.one();
+ String address = row.getInet("broadcast_address").toString();
+ logger.info("Queried node has broadcast_address: {}}", address);
+ System.out.flush();
+ } finally {
+ assert bridgeA != null;
+ bridgeA.close();
+ }
+
+ CCMBridge bridgeB = null;
+ // Overwrite host resolution
+ MappedHostResolverProvider.removeResolverEntry("control.reconnect.test");
+ MappedHostResolverProvider.addResolverEntry("control.reconnect.test", "127.2.2.1");
+ try {
+ bridgeB =
+ CCMBridge.builder()
+ .withNodes(1)
+ .withIpPrefix("127.2.2.")
+ .withBinaryPort(9042)
+ .withClusterName("same_name")
+ .build();
+ bridgeB.start();
+ Thread.sleep(1000 * 92);
+ ResultSet rs = session.execute("select * from system.local");
+ Row row = rs.one();
+ String address = row.getInet("broadcast_address").toString();
+ logger.info("Queried node has broadcast_address: {}}", address);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ } finally {
+ assert bridgeB != null;
+ bridgeB.close();
+ }
+ }
+
+ @Test(groups = "long")
+ public void should_connect_with_mocked_hostname() {
+ MappedHostResolverProvider.addResolverEntry("mocked.hostname.test", "127.0.1.1");
+ try (CCMBridge ccmBridge =
+ CCMBridge.builder().withNodes(1).withIpPrefix("127.0.1.").withBinaryPort(9042).build();
+ Cluster cluster =
+ Cluster.builder()
+ .addContactPointsWithPorts(
+ InetSocketAddress.createUnresolved("mocked.hostname.test", 9042))
+ .withPort(9042)
+ .withoutAdvancedShardAwareness()
+ .build()) {
+ ccmBridge.start();
+ Session session = cluster.connect();
+ ResultSet rs = session.execute("SELECT * FROM system.local");
+ List