Skip to content

Commit 058d9f4

Browse files
jyeminstIncMale
andauthored
Make reference count check atomic with release (#876)
JAVA-4490 Co-authored-by: Valentin Kovalenko <valentin.kovalenko@mongodb.com>
1 parent dd291c3 commit 058d9f4

25 files changed

+131
-93
lines changed

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

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import com.mongodb.connection.ClusterType;
2424
import com.mongodb.connection.ServerDescription;
2525
import com.mongodb.internal.async.SingleResultCallback;
26+
import com.mongodb.internal.binding.AbstractReferenceCounted;
2627
import com.mongodb.internal.binding.AsyncClusterAwareReadWriteBinding;
2728
import com.mongodb.internal.binding.AsyncConnectionSource;
2829
import com.mongodb.internal.binding.AsyncReadWriteBinding;
@@ -36,15 +37,15 @@
3637
import static com.mongodb.assertions.Assertions.notNull;
3738
import static com.mongodb.connection.ClusterType.LOAD_BALANCED;
3839

39-
public class ClientSessionBinding implements AsyncReadWriteBinding {
40+
public class ClientSessionBinding extends AbstractReferenceCounted implements AsyncReadWriteBinding {
4041
private final AsyncClusterAwareReadWriteBinding wrapped;
4142
private final AsyncClientSession session;
4243
private final boolean ownsSession;
4344
private final ClientSessionContext sessionContext;
4445

4546
public ClientSessionBinding(final AsyncClientSession session, final boolean ownsSession,
4647
final AsyncClusterAwareReadWriteBinding wrapped) {
47-
this.wrapped = notNull("wrapped", (wrapped));
48+
this.wrapped = notNull("wrapped", wrapped).retain();
4849
this.ownsSession = ownsSession;
4950
this.session = notNull("session", session);
5051
this.sessionContext = new AsyncClientSessionContext(session);
@@ -113,14 +114,9 @@ private void getPinnedConnectionSource(final boolean isRead, final SingleResultC
113114
}
114115
}
115116

116-
@Override
117-
public int getCount() {
118-
return wrapped.getCount();
119-
}
120-
121117
@Override
122118
public AsyncReadWriteBinding retain() {
123-
wrapped.retain();
119+
super.retain();
124120
return this;
125121
}
126122

@@ -131,15 +127,15 @@ public void getReadConnectionSource(final int minWireVersion, final ReadPreferen
131127
}
132128

133129
@Override
134-
public void release() {
135-
wrapped.release();
136-
closeSessionIfCountIsZero();
137-
}
138-
139-
private void closeSessionIfCountIsZero() {
140-
if (getCount() == 0 && ownsSession) {
141-
session.close();
130+
public int release() {
131+
int count = super.release();
132+
if (count == 0) {
133+
wrapped.release();
134+
if (ownsSession) {
135+
session.close();
136+
}
142137
}
138+
return count;
143139
}
144140

145141
private boolean isConnectionSourcePinningRequired() {
@@ -152,6 +148,7 @@ private class SessionBindingAsyncConnectionSource implements AsyncConnectionSour
152148

153149
SessionBindingAsyncConnectionSource(final AsyncConnectionSource wrapped) {
154150
this.wrapped = wrapped;
151+
ClientSessionBinding.this.retain();
155152
}
156153

157154
@Override
@@ -214,9 +211,12 @@ public int getCount() {
214211
}
215212

216213
@Override
217-
public void release() {
218-
wrapped.release();
219-
closeSessionIfCountIsZero();
214+
public int release() {
215+
int count = wrapped.release();
216+
if (count == 0) {
217+
ClientSessionBinding.this.release();
218+
}
219+
return count;
220220
}
221221
}
222222

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,11 @@ public ReferenceCounted retain() {
3434
}
3535

3636
@Override
37-
public void release() {
38-
if (referenceCount.decrementAndGet() < 0) {
37+
public int release() {
38+
int decrementedValue = referenceCount.decrementAndGet();
39+
if (decrementedValue < 0) {
3940
throw new IllegalStateException("Attempted to decrement the reference count below 0");
4041
}
42+
return decrementedValue;
4143
}
4244
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,4 +33,7 @@ public interface AsyncClusterAwareReadWriteBinding extends AsyncReadWriteBinding
3333
* @param callback the to be passed the connection source
3434
*/
3535
void getConnectionSource(ServerAddress serverAddress, SingleResultCallback<AsyncConnectionSource> callback);
36+
37+
@Override
38+
AsyncClusterAwareReadWriteBinding retain();
3639
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ public AsyncClusterBinding(final Cluster cluster, final ReadPreference readPrefe
7373
}
7474

7575
@Override
76-
public AsyncReadWriteBinding retain() {
76+
public AsyncClusterAwareReadWriteBinding retain() {
7777
super.retain();
7878
return this;
7979
}
@@ -208,9 +208,10 @@ public AsyncConnectionSource retain() {
208208
}
209209

210210
@Override
211-
public void release() {
212-
super.release();
211+
public int release() {
212+
int count = super.release();
213213
AsyncClusterBinding.this.release();
214+
return count;
214215
}
215216
}
216217
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,10 @@ public ConnectionSource retain() {
182182
}
183183

184184
@Override
185-
public void release() {
186-
super.release();
185+
public int release() {
186+
int count = super.release();
187187
ClusterBinding.this.release();
188+
return count;
188189
}
189190
}
190191
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616

1717
package com.mongodb.internal.binding;
1818

19+
import com.mongodb.internal.VisibleForTesting;
20+
21+
import static com.mongodb.internal.VisibleForTesting.AccessModifier.PRIVATE;
22+
1923
/**
2024
* An interface for reference-counted objects.
2125
* <p>
@@ -39,9 +43,14 @@ public interface ReferenceCounted {
3943
/**
4044
* Gets the current reference count.
4145
*
46+
* <p>
47+
* This method should only be used for testing. Production code should prefer using the count returned from {@link #release()}
48+
* </p>
49+
*
4250
* @return the current count, which must be greater than or equal to 0.
4351
* Returns 1 for a newly created object.
4452
*/
53+
@VisibleForTesting(otherwise = PRIVATE)
4554
int getCount();
4655

4756
/**
@@ -54,6 +63,7 @@ public interface ReferenceCounted {
5463
/**
5564
* Release a reference to this object.
5665
* @throws java.lang.IllegalStateException if the reference count is already 0
66+
* @return the reference count after the release
5767
*/
58-
void release();
68+
int release();
5969
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,12 @@ public ConnectionSource retain() {
146146
}
147147

148148
@Override
149-
public void release() {
150-
super.release();
151-
if (super.getCount() == 0) {
149+
public int release() {
150+
int count = super.release();
151+
if (count == 0) {
152152
SingleServerBinding.this.release();
153153
}
154+
return count;
154155
}
155156
}
156157
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,14 @@ public boolean isConnectionPinningRequired() {
4848
}
4949

5050
@Override
51-
public void release() {
52-
super.release();
53-
if (getCount() == 0) {
51+
public int release() {
52+
int count = super.release();
53+
if (count == 0) {
5454
if (pinnedConnection != null) {
5555
pinnedConnection.release();
5656
}
5757
}
58+
return count;
5859
}
5960

6061
@SuppressWarnings("unchecked")

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ public ReferenceCounted retain() {
3636
}
3737

3838
@Override
39-
public void release() {
40-
if (referenceCount.decrementAndGet() < 0) {
39+
public int release() {
40+
int decrementedValue = referenceCount.decrementAndGet();
41+
if (decrementedValue < 0) {
4142
throw new IllegalStateException("Attempted to decrement the reference count below 0");
4243
}
44+
return decrementedValue;
4345
}
4446
}

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -301,11 +301,12 @@ public int getCount() {
301301
}
302302

303303
@Override
304-
public void release() {
305-
wrapped.release();
306-
if (getCount() == 0) {
304+
public int release() {
305+
int count = wrapped.release();
306+
if (count == 0) {
307307
server.operationEnd();
308308
}
309+
return count;
309310
}
310311

311312
@Override
@@ -401,11 +402,12 @@ public int getCount() {
401402
}
402403

403404
@Override
404-
public void release() {
405-
wrapped.release();
406-
if (getCount() == 0) {
405+
public int release() {
406+
int count = wrapped.release();
407+
if (count == 0) {
407408
server.operationEnd();
408409
}
410+
return count;
409411
}
410412

411413
@Override

0 commit comments

Comments
 (0)