Skip to content

Commit 1152442

Browse files
committed
Fix race condition accessing ServerDescription
This change guarantees that any operation accessing the ServerDescription via ConnectionSource will see a Server Description that is valid (i.e consistent with the state of the server when it was selected), though perhaps stale, depending on how long the ConnectionSource is retained. JAVA-3911
1 parent bf685da commit 1152442

File tree

20 files changed

+136
-218
lines changed

20 files changed

+136
-218
lines changed

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import com.mongodb.annotations.Immutable;
2222
import com.mongodb.annotations.NotThreadSafe;
2323
import com.mongodb.event.ClusterListener;
24-
import com.mongodb.internal.connection.Cluster;
2524
import com.mongodb.internal.connection.ServerAddressHelper;
2625
import com.mongodb.internal.selector.LatencyMinimizingServerSelector;
2726
import com.mongodb.lang.Nullable;
@@ -389,7 +388,6 @@ public String getRequiredReplicaSetName() {
389388
* </ul>
390389
*
391390
* @return the server selector, which may be null
392-
* @see Cluster#selectServer(com.mongodb.selector.ServerSelector)
393391
*/
394392
@Nullable
395393
public ServerSelector getServerSelector() {

driver-core/src/main/com/mongodb/internal/async/client/ClientSessionBinding.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import com.mongodb.internal.binding.AsyncConnectionSource;
2626
import com.mongodb.internal.binding.AsyncReadWriteBinding;
2727
import com.mongodb.internal.connection.AsyncConnection;
28-
import com.mongodb.internal.connection.Server;
28+
import com.mongodb.internal.connection.ServerTuple;
2929
import com.mongodb.internal.selector.ReadPreferenceServerSelector;
3030
import com.mongodb.internal.session.ClientSessionContext;
3131
import com.mongodb.internal.session.SessionContext;
@@ -76,13 +76,13 @@ public SessionContext getSessionContext() {
7676
private void getPinnedConnectionSource(final SingleResultCallback<AsyncConnectionSource> callback) {
7777
if (session.getPinnedServerAddress() == null) {
7878
wrapped.getCluster().selectServerAsync(
79-
new ReadPreferenceServerSelector(wrapped.getReadPreference()), new SingleResultCallback<Server>() {
79+
new ReadPreferenceServerSelector(wrapped.getReadPreference()), new SingleResultCallback<ServerTuple>() {
8080
@Override
81-
public void onResult(final Server server, final Throwable t) {
81+
public void onResult(final ServerTuple serverTuple, final Throwable t) {
8282
if (t != null) {
8383
callback.onResult(null, t);
8484
} else {
85-
session.setPinnedServerAddress(server.getDescription().getAddress());
85+
session.setPinnedServerAddress(serverTuple.getServerDescription().getAddress());
8686
wrapped.getConnectionSource(session.getPinnedServerAddress(), new WrappingCallback(callback));
8787
}
8888
}

driver-core/src/main/com/mongodb/internal/binding/AsyncClusterBinding.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.mongodb.internal.connection.Cluster;
2626
import com.mongodb.internal.connection.ReadConcernAwareNoOpSessionContext;
2727
import com.mongodb.internal.connection.Server;
28+
import com.mongodb.internal.connection.ServerTuple;
2829
import com.mongodb.internal.selector.ReadPreferenceServerSelector;
2930
import com.mongodb.internal.selector.ServerAddressSelector;
3031
import com.mongodb.internal.selector.WritableServerSelector;
@@ -96,29 +97,31 @@ public void getConnectionSource(final ServerAddress serverAddress, final SingleR
9697

9798
private void getAsyncClusterBindingConnectionSource(final ServerSelector serverSelector,
9899
final SingleResultCallback<AsyncConnectionSource> callback) {
99-
cluster.selectServerAsync(serverSelector, new SingleResultCallback<Server>() {
100+
cluster.selectServerAsync(serverSelector, new SingleResultCallback<ServerTuple>() {
100101
@Override
101-
public void onResult(final Server result, final Throwable t) {
102+
public void onResult(final ServerTuple result, final Throwable t) {
102103
if (t != null) {
103104
callback.onResult(null, t);
104105
} else {
105-
callback.onResult(new AsyncClusterBindingConnectionSource(result), null);
106+
callback.onResult(new AsyncClusterBindingConnectionSource(result.getServer(), result.getServerDescription()), null);
106107
}
107108
}
108109
});
109110
}
110111

111112
private final class AsyncClusterBindingConnectionSource extends AbstractReferenceCounted implements AsyncConnectionSource {
112113
private final Server server;
114+
private final ServerDescription serverDescription;
113115

114-
private AsyncClusterBindingConnectionSource(final Server server) {
116+
private AsyncClusterBindingConnectionSource(final Server server, final ServerDescription serverDescription) {
115117
this.server = server;
118+
this.serverDescription = serverDescription;
116119
AsyncClusterBinding.this.retain();
117120
}
118121

119122
@Override
120123
public ServerDescription getServerDescription() {
121-
return server.getDescription();
124+
return serverDescription;
122125
}
123126

124127
@Override

driver-core/src/main/com/mongodb/internal/binding/AsyncSingleServerBinding.java

Lines changed: 0 additions & 140 deletions
This file was deleted.

driver-core/src/main/com/mongodb/internal/binding/ClusterBinding.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.mongodb.internal.connection.Connection;
2525
import com.mongodb.internal.connection.ReadConcernAwareNoOpSessionContext;
2626
import com.mongodb.internal.connection.Server;
27+
import com.mongodb.internal.connection.ServerTuple;
2728
import com.mongodb.internal.selector.ReadPreferenceServerSelector;
2829
import com.mongodb.internal.selector.ServerAddressSelector;
2930
import com.mongodb.internal.selector.WritableServerSelector;
@@ -98,15 +99,18 @@ public ConnectionSource getConnectionSource(final ServerAddress serverAddress) {
9899

99100
private final class ClusterBindingConnectionSource extends AbstractReferenceCounted implements ConnectionSource {
100101
private final Server server;
102+
private final ServerDescription serverDescription;
101103

102104
private ClusterBindingConnectionSource(final ServerSelector serverSelector) {
103-
this.server = cluster.selectServer(serverSelector);
105+
ServerTuple serverTuple = cluster.selectServer(serverSelector);
106+
this.server = serverTuple.getServer();
107+
this.serverDescription = serverTuple.getServerDescription();
104108
ClusterBinding.this.retain();
105109
}
106110

107111
@Override
108112
public ServerDescription getServerDescription() {
109-
return server.getDescription();
113+
return serverDescription;
110114
}
111115

112116
@Override

driver-core/src/main/com/mongodb/internal/binding/SingleServerBinding.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import com.mongodb.internal.connection.Cluster;
2323
import com.mongodb.internal.connection.Connection;
2424
import com.mongodb.internal.connection.NoOpSessionContext;
25-
import com.mongodb.internal.connection.Server;
25+
import com.mongodb.internal.connection.ServerTuple;
2626
import com.mongodb.internal.selector.ServerAddressSelector;
2727
import com.mongodb.internal.session.SessionContext;
2828

@@ -86,16 +86,17 @@ public SingleServerBinding retain() {
8686
}
8787

8888
private final class SingleServerBindingConnectionSource extends AbstractReferenceCounted implements ConnectionSource {
89-
private final Server server;
89+
private final ServerDescription serverDescription;
9090

9191
private SingleServerBindingConnectionSource() {
9292
SingleServerBinding.this.retain();
93-
server = cluster.selectServer(new ServerAddressSelector(serverAddress));
93+
ServerTuple serverTuple = cluster.selectServer(new ServerAddressSelector(serverAddress));
94+
serverDescription = serverTuple.getServerDescription();
9495
}
9596

9697
@Override
9798
public ServerDescription getServerDescription() {
98-
return server.getDescription();
99+
return serverDescription;
99100
}
100101

101102
@Override
@@ -105,7 +106,7 @@ public SessionContext getSessionContext() {
105106

106107
@Override
107108
public Connection getConnection() {
108-
return cluster.selectServer(new ServerAddressSelector(serverAddress)).getConnection();
109+
return cluster.selectServer(new ServerAddressSelector(serverAddress)).getServer().getConnection();
109110
}
110111

111112
@Override

0 commit comments

Comments
 (0)