You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ds...@apache.org on 2019/04/03 00:08:02 UTC

[geode] branch develop updated: GEODE-6587: fix race in useFirst (#3396)

This is an automated email from the ASF dual-hosted git repository.

dschneider pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new d989fc9  GEODE-6587: fix race in useFirst (#3396)
d989fc9 is described below

commit d989fc939bf4d6d94e69338b9b77b74d12150ec6
Author: Darrel Schneider <ds...@pivotal.io>
AuthorDate: Tue Apr 2 17:07:51 2019 -0700

    GEODE-6587: fix race in useFirst (#3396)
    
    useFirst had a race condition in which the connection it
    returned might not match the predicate. This is because
    the predicate was only checked while the connection will
    still not active. Now a recheck is done after activating
    the connection. If, after activation it does not match, the
    connection is added back on the end of the deque.
---
 .../pooling/AvailableConnectionManager.java        |  9 +++++++-
 .../pooling/AvailableConnectionManagerTest.java    | 24 ++++++++++++++++++++++
 2 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/geode-core/src/main/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManager.java b/geode-core/src/main/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManager.java
index 6628266..5a32591 100644
--- a/geode-core/src/main/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManager.java
+++ b/geode-core/src/main/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManager.java
@@ -71,7 +71,14 @@ public class AvailableConnectionManager {
     while (connections.removeFirstOccurrence(equalsWithPredicate)) {
       PooledConnection connection = equalsWithPredicate.getConnectionThatMatched();
       if (connection.activate()) {
-        return connection;
+        // Need to recheck the predicate after we have activated.
+        // Until activated load conditioning can change the server
+        // we are connected to.
+        if (predicate.test(connection)) {
+          return connection;
+        } else {
+          addLast(connection, false);
+        }
       }
     }
     return null;
diff --git a/geode-core/src/test/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManagerTest.java b/geode-core/src/test/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManagerTest.java
index 1cc1c98..6ebdc4a 100644
--- a/geode-core/src/test/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManagerTest.java
+++ b/geode-core/src/test/java/org/apache/geode/cache/client/internal/pooling/AvailableConnectionManagerTest.java
@@ -23,6 +23,8 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import java.util.concurrent.atomic.AtomicBoolean;
+
 import org.junit.Test;
 
 public class AvailableConnectionManagerTest {
@@ -117,6 +119,28 @@ public class AvailableConnectionManagerTest {
   }
 
   @Test
+  public void useFirstWithPredicateReturnsNullGivenManagerWithOneItemThatDoesNotMatchAfterBeingActivated() {
+    PooledConnection expected = createConnection();
+    when(expected.activate()).thenReturn(true);
+    instance.getDeque().addFirst(expected);
+    final AtomicBoolean firstTime = new AtomicBoolean(true);
+
+    PooledConnection result = instance.useFirst(c -> {
+      if (firstTime.get()) {
+        firstTime.set(false);
+        return true;
+      } else {
+        return false;
+      }
+    });
+
+    assertThat(result).isNull();
+    assertThat(instance.getDeque()).containsExactly(expected);
+    verify(expected).activate();
+    verify(expected).passivate(false);
+  }
+
+  @Test
   public void removeReturnsFalseGivenConnectionNotInManager() {
     instance.getDeque().clear();