Skip to content

Commit 8a27274

Browse files
committed
Unify behavior around configuration for replica set discovery
And fix handling of wrong set name in single topology JAVA-3623 JAVA-3699
1 parent fb58542 commit 8a27274

File tree

43 files changed

+880
-253
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+880
-253
lines changed

driver-core/src/main/com/mongodb/ConnectionString.java

+61-81
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import java.util.LinkedHashSet;
3232
import java.util.List;
3333
import java.util.Map;
34+
import java.util.Objects;
3435
import java.util.Set;
3536
import java.util.concurrent.TimeUnit;
3637

@@ -226,6 +227,7 @@
226227
* <li>{@code uuidRepresentation=unspecified|standard|javaLegacy|csharpLegacy|pythonLegacy}. See
227228
* {@link MongoClientSettings#getUuidRepresentation()} for documentation of semantics of this parameter. Defaults to "javaLegacy", but
228229
* will change to "unspecified" in the next major release.</li>
230+
* <li>{@code directConnection=true|false}. If true the driver will set the connection to be a direct connection to the host.</li>
229231
* </ul>
230232
*
231233
* @mongodb.driver.manual reference/connection-string Connection String Format
@@ -247,6 +249,7 @@ public class ConnectionString {
247249
private final String collection;
248250
private final String connectionString;
249251

252+
private Boolean directConnection;
250253
private ReadPreference readPreference;
251254
private WriteConcern writeConcern;
252255
private Boolean retryWrites;
@@ -389,6 +392,15 @@ public ConnectionString(final String connectionString) {
389392
combinedOptionsMaps.put("ssl", singletonList("true"));
390393
}
391394
translateOptions(combinedOptionsMaps);
395+
396+
if (directConnection != null && directConnection) {
397+
if (isSrvProtocol) {
398+
throw new IllegalArgumentException("Direct connections are not supported when using mongodb+srv protocol");
399+
} else if (hosts.size() > 1) {
400+
throw new IllegalArgumentException("Direct connections are not supported when using multiple hosts");
401+
}
402+
}
403+
392404
credential = createCredentials(combinedOptionsMaps, userName, password);
393405
warnOnUnsupportedOptions(combinedOptionsMaps);
394406
}
@@ -435,6 +447,8 @@ public ConnectionString(final String connectionString) {
435447

436448
GENERAL_OPTIONS_KEYS.add("uuidrepresentation");
437449

450+
GENERAL_OPTIONS_KEYS.add("directconnection");
451+
438452
COMPRESSOR_KEYS.add("compressors");
439453
COMPRESSOR_KEYS.add("zlibcompressionlevel");
440454

@@ -535,6 +549,8 @@ private void translateOptions(final Map<String, List<String>> optionsMap) {
535549
retryReads = parseBoolean(value, "retryreads");
536550
} else if (key.equals("uuidrepresentation")) {
537551
uuidRepresentation = createUuidRepresentation(value);
552+
} else if (key.equals("directconnection")) {
553+
directConnection = parseBoolean(value, "directconnection");
538554
}
539555
}
540556

@@ -1082,7 +1098,6 @@ public String getDatabase() {
10821098
return database;
10831099
}
10841100

1085-
10861101
/**
10871102
* Gets the collection name
10881103
*
@@ -1093,6 +1108,17 @@ public String getCollection() {
10931108
return collection;
10941109
}
10951110

1111+
/**
1112+
* Indicates if the connection should be a direct connection
1113+
*
1114+
* @return true if a direct connection
1115+
* @since 4.1
1116+
*/
1117+
@Nullable
1118+
public Boolean isDirectConnection() {
1119+
return directConnection;
1120+
}
1121+
10961122
/**
10971123
* Get the unparsed connection string.
10981124
*
@@ -1337,91 +1363,45 @@ public boolean equals(final Object o) {
13371363
if (this == o) {
13381364
return true;
13391365
}
1340-
if (!(o instanceof ConnectionString)) {
1366+
if (o == null || getClass() != o.getClass()) {
13411367
return false;
13421368
}
1343-
1344-
ConnectionString that = (ConnectionString) o;
1345-
1346-
if (collection != null ? !collection.equals(that.collection) : that.collection != null) {
1347-
return false;
1348-
}
1349-
if (connectTimeout != null ? !connectTimeout.equals(that.connectTimeout) : that.connectTimeout != null) {
1350-
return false;
1351-
}
1352-
if (credential != null ? !credential.equals(that.credential) : that.credential != null) {
1353-
return false;
1354-
}
1355-
if (database != null ? !database.equals(that.database) : that.database != null) {
1356-
return false;
1357-
}
1358-
if (!hosts.equals(that.hosts)) {
1359-
return false;
1360-
}
1361-
if (maxConnectionIdleTime != null ? !maxConnectionIdleTime.equals(that.maxConnectionIdleTime)
1362-
: that.maxConnectionIdleTime != null) {
1363-
return false;
1364-
}
1365-
if (maxConnectionLifeTime != null ? !maxConnectionLifeTime.equals(that.maxConnectionLifeTime)
1366-
: that.maxConnectionLifeTime != null) {
1367-
return false;
1368-
}
1369-
if (maxConnectionPoolSize != null ? !maxConnectionPoolSize.equals(that.maxConnectionPoolSize)
1370-
: that.maxConnectionPoolSize != null) {
1371-
return false;
1372-
}
1373-
if (maxWaitTime != null ? !maxWaitTime.equals(that.maxWaitTime) : that.maxWaitTime != null) {
1374-
return false;
1375-
}
1376-
if (minConnectionPoolSize != null ? !minConnectionPoolSize.equals(that.minConnectionPoolSize)
1377-
: that.minConnectionPoolSize != null) {
1378-
return false;
1379-
}
1380-
if (readPreference != null ? !readPreference.equals(that.readPreference) : that.readPreference != null) {
1381-
return false;
1382-
}
1383-
if (requiredReplicaSetName != null ? !requiredReplicaSetName.equals(that.requiredReplicaSetName)
1384-
: that.requiredReplicaSetName != null) {
1385-
return false;
1386-
}
1387-
if (socketTimeout != null ? !socketTimeout.equals(that.socketTimeout) : that.socketTimeout != null) {
1388-
return false;
1389-
}
1390-
if (sslEnabled != null ? !sslEnabled.equals(that.sslEnabled) : that.sslEnabled != null) {
1391-
return false;
1392-
}
1393-
if (writeConcern != null ? !writeConcern.equals(that.writeConcern) : that.writeConcern != null) {
1394-
return false;
1395-
}
1396-
if (applicationName != null ? !applicationName.equals(that.applicationName) : that.applicationName != null) {
1397-
return false;
1398-
}
1399-
if (!compressorList.equals(that.compressorList)) {
1400-
return false;
1401-
}
1402-
1403-
return true;
1369+
final ConnectionString that = (ConnectionString) o;
1370+
return isSrvProtocol == that.isSrvProtocol
1371+
&& Objects.equals(directConnection, that.directConnection)
1372+
&& Objects.equals(credential, that.credential)
1373+
&& Objects.equals(hosts, that.hosts)
1374+
&& Objects.equals(database, that.database)
1375+
&& Objects.equals(collection, that.collection)
1376+
&& Objects.equals(readPreference, that.readPreference)
1377+
&& Objects.equals(writeConcern, that.writeConcern)
1378+
&& Objects.equals(retryWrites, that.retryWrites)
1379+
&& Objects.equals(retryReads, that.retryReads)
1380+
&& Objects.equals(readConcern, that.readConcern)
1381+
&& Objects.equals(minConnectionPoolSize, that.minConnectionPoolSize)
1382+
&& Objects.equals(maxConnectionPoolSize, that.maxConnectionPoolSize)
1383+
&& Objects.equals(maxWaitTime, that.maxWaitTime)
1384+
&& Objects.equals(maxConnectionIdleTime, that.maxConnectionIdleTime)
1385+
&& Objects.equals(maxConnectionLifeTime, that.maxConnectionLifeTime)
1386+
&& Objects.equals(connectTimeout, that.connectTimeout)
1387+
&& Objects.equals(socketTimeout, that.socketTimeout)
1388+
&& Objects.equals(sslEnabled, that.sslEnabled)
1389+
&& Objects.equals(sslInvalidHostnameAllowed, that.sslInvalidHostnameAllowed)
1390+
&& Objects.equals(requiredReplicaSetName, that.requiredReplicaSetName)
1391+
&& Objects.equals(serverSelectionTimeout, that.serverSelectionTimeout)
1392+
&& Objects.equals(localThreshold, that.localThreshold)
1393+
&& Objects.equals(heartbeatFrequency, that.heartbeatFrequency)
1394+
&& Objects.equals(applicationName, that.applicationName)
1395+
&& Objects.equals(compressorList, that.compressorList)
1396+
&& Objects.equals(uuidRepresentation, that.uuidRepresentation);
14041397
}
14051398

14061399
@Override
14071400
public int hashCode() {
1408-
int result = credential != null ? credential.hashCode() : 0;
1409-
result = 31 * result + hosts.hashCode();
1410-
result = 31 * result + (database != null ? database.hashCode() : 0);
1411-
result = 31 * result + (collection != null ? collection.hashCode() : 0);
1412-
result = 31 * result + (readPreference != null ? readPreference.hashCode() : 0);
1413-
result = 31 * result + (writeConcern != null ? writeConcern.hashCode() : 0);
1414-
result = 31 * result + (minConnectionPoolSize != null ? minConnectionPoolSize.hashCode() : 0);
1415-
result = 31 * result + (maxConnectionPoolSize != null ? maxConnectionPoolSize.hashCode() : 0);
1416-
result = 31 * result + (maxWaitTime != null ? maxWaitTime.hashCode() : 0);
1417-
result = 31 * result + (maxConnectionIdleTime != null ? maxConnectionIdleTime.hashCode() : 0);
1418-
result = 31 * result + (maxConnectionLifeTime != null ? maxConnectionLifeTime.hashCode() : 0);
1419-
result = 31 * result + (connectTimeout != null ? connectTimeout.hashCode() : 0);
1420-
result = 31 * result + (socketTimeout != null ? socketTimeout.hashCode() : 0);
1421-
result = 31 * result + (sslEnabled != null ? sslEnabled.hashCode() : 0);
1422-
result = 31 * result + (requiredReplicaSetName != null ? requiredReplicaSetName.hashCode() : 0);
1423-
result = 31 * result + (applicationName != null ? applicationName.hashCode() : 0);
1424-
result = 31 * result + compressorList.hashCode();
1425-
return result;
1401+
return Objects.hash(credential, isSrvProtocol, hosts, database, collection, directConnection, readPreference,
1402+
writeConcern, retryWrites, retryReads, readConcern, minConnectionPoolSize, maxConnectionPoolSize, maxWaitTime,
1403+
maxConnectionIdleTime, maxConnectionLifeTime, connectTimeout, socketTimeout, sslEnabled, sslInvalidHostnameAllowed,
1404+
requiredReplicaSetName, serverSelectionTimeout, localThreshold, heartbeatFrequency, applicationName, compressorList,
1405+
uuidRepresentation);
14261406
}
14271407
}

driver-core/src/main/com/mongodb/connection/ClusterSettings.java

+11-11
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.mongodb.annotations.NotThreadSafe;
2323
import com.mongodb.event.ClusterListener;
2424
import com.mongodb.internal.connection.Cluster;
25+
import com.mongodb.internal.connection.ServerAddressHelper;
2526
import com.mongodb.internal.selector.LatencyMinimizingServerSelector;
2627
import com.mongodb.selector.CompositeServerSelector;
2728
import com.mongodb.selector.ServerSelector;
@@ -31,6 +32,7 @@
3132
import java.util.List;
3233
import java.util.Set;
3334
import java.util.concurrent.TimeUnit;
35+
import java.util.stream.Collectors;
3436

3537
import static com.mongodb.assertions.Assertions.isTrueArgument;
3638
import static com.mongodb.assertions.Assertions.notNull;
@@ -262,25 +264,24 @@ public Builder addClusterListener(final ClusterListener clusterListener) {
262264
* @return this
263265
*/
264266
public Builder applyConnectionString(final ConnectionString connectionString) {
267+
Boolean directConnection = connectionString.isDirectConnection();
268+
265269
if (connectionString.isSrvProtocol()) {
266270
mode(ClusterConnectionMode.MULTIPLE);
267271
srvHost(connectionString.getHosts().get(0));
268-
}
269-
else if (connectionString.getHosts().size() == 1 && connectionString.getRequiredReplicaSetName() == null) {
272+
} else if ((directConnection != null && directConnection)
273+
|| (directConnection == null && connectionString.getHosts().size() == 1
274+
&& connectionString.getRequiredReplicaSetName() == null)) {
270275
mode(ClusterConnectionMode.SINGLE)
271-
.hosts(singletonList(createServerAddress(connectionString.getHosts().get(0))));
276+
.hosts(singletonList(createServerAddress(connectionString.getHosts().get(0))));
272277
} else {
273-
List<ServerAddress> seedList = new ArrayList<ServerAddress>();
274-
for (final String cur : connectionString.getHosts()) {
275-
seedList.add(createServerAddress(cur));
276-
}
278+
List<ServerAddress> seedList = connectionString.getHosts().stream()
279+
.map(ServerAddressHelper::createServerAddress)
280+
.collect(Collectors.toList());
277281
mode(ClusterConnectionMode.MULTIPLE).hosts(seedList);
278282
}
279283
requiredReplicaSetName(connectionString.getRequiredReplicaSetName());
280284

281-
Integer maxConnectionPoolSize = connectionString.getMaxConnectionPoolSize();
282-
int maxSize = maxConnectionPoolSize != null ? maxConnectionPoolSize : 100;
283-
284285
Integer serverSelectionTimeout = connectionString.getServerSelectionTimeout();
285286
if (serverSelectionTimeout != null) {
286287
serverSelectionTimeout(serverSelectionTimeout, MILLISECONDS);
@@ -562,7 +563,6 @@ private ClusterSettings(final Builder builder) {
562563
if (builder.mode == ClusterConnectionMode.SINGLE && builder.hosts.size() > 1) {
563564
throw new IllegalArgumentException("Can not directly connect to more than one server");
564565
}
565-
566566
mode = builder.mode != null ? builder.mode : hosts.size() == 1 ? ClusterConnectionMode.SINGLE : ClusterConnectionMode.MULTIPLE;
567567
}
568568
requiredReplicaSetName = builder.requiredReplicaSetName;

driver-core/src/main/com/mongodb/connection/ServerDescription.java

+38
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,17 @@ public static Builder builder() {
101101
return new Builder();
102102
}
103103

104+
/**
105+
* Creates a Builder for a ServerDescription instance based on a previous serverDescription.
106+
*
107+
* @param serverDescription the ServerDescription to base the builder from
108+
* @return a new Builder for ServerDescription.
109+
* @since 4.1
110+
*/
111+
public static Builder builder(final ServerDescription serverDescription) {
112+
return new Builder(serverDescription);
113+
}
114+
104115
/**
105116
* Gets the string representing the host name and port that this member of a replica set was configured with,
106117
* e.g. {@code "somehost:27019"}. This is typically derived from the "me" field from the "isMaster" command response.
@@ -150,6 +161,33 @@ public static class Builder {
150161

151162
private Throwable exception;
152163

164+
Builder() {
165+
}
166+
167+
Builder(final ServerDescription serverDescription) {
168+
this.address = serverDescription.address;
169+
this.type = serverDescription.type;
170+
this.canonicalAddress = serverDescription.canonicalAddress;
171+
this.hosts = serverDescription.hosts;
172+
this.passives = serverDescription.passives;
173+
this.arbiters = serverDescription.arbiters;
174+
this.primary = serverDescription.primary;
175+
this.maxDocumentSize = serverDescription.maxDocumentSize;
176+
this.tagSet = serverDescription.tagSet;
177+
this.setName = serverDescription.setName;
178+
this.roundTripTimeNanos = serverDescription.roundTripTimeNanos;
179+
this.ok = serverDescription.ok;
180+
this.state = serverDescription.state;
181+
this.minWireVersion = serverDescription.minWireVersion;
182+
this.maxWireVersion = serverDescription.maxWireVersion;
183+
this.electionId = serverDescription.electionId;
184+
this.setVersion = serverDescription.setVersion;
185+
this.lastWriteDate = serverDescription.lastWriteDate;
186+
this.lastUpdateTimeNanos = serverDescription.lastUpdateTimeNanos;
187+
this.logicalSessionTimeoutMinutes = serverDescription.logicalSessionTimeoutMinutes;
188+
this.exception = serverDescription.exception;
189+
}
190+
153191
/**
154192
* Sets the address of the server.
155193
*

driver-core/src/main/com/mongodb/internal/connection/AbstractMultiServerCluster.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ private void onChange(final ServerDescriptionChangedEvent event) {
197197
return;
198198
}
199199

200-
if (event.getNewDescription().isOk()) {
200+
if (newDescription.isOk()) {
201201
if (clusterType == UNKNOWN && newDescription.getType() != REPLICA_SET_GHOST) {
202202
clusterType = newDescription.getClusterType();
203203
if (LOGGER.isInfoEnabled()) {

0 commit comments

Comments
 (0)