You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ja...@apache.org on 2016/12/05 17:30:13 UTC

incubator-geode git commit: GEODE-2163: Optimized caching of names in CqService needs to be maintained correctly

Repository: incubator-geode
Updated Branches:
  refs/heads/develop 9e54d915f -> 5ef9f9031


GEODE-2163: Optimized caching of names in CqService needs to be maintained correctly


Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/5ef9f903
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/5ef9f903
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/5ef9f903

Branch: refs/heads/develop
Commit: 5ef9f90316db92284c00d51c8a8dbebed7de43c6
Parents: 9e54d91
Author: Jason Huynh <hu...@gmail.com>
Authored: Thu Dec 1 10:06:02 2016 -0800
Committer: Jason Huynh <hu...@gmail.com>
Committed: Mon Dec 5 09:29:55 2016 -0800

----------------------------------------------------------------------
 .../cache/query/internal/cq/CqServiceImpl.java  | 35 ++++++++-----
 .../query/internal/cq/CqServiceUnitTest.java    | 52 ++++++++++++++++++++
 2 files changed, 76 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ef9f903/geode-cq/src/main/java/org/apache/geode/cache/query/internal/cq/CqServiceImpl.java
----------------------------------------------------------------------
diff --git a/geode-cq/src/main/java/org/apache/geode/cache/query/internal/cq/CqServiceImpl.java b/geode-cq/src/main/java/org/apache/geode/cache/query/internal/cq/CqServiceImpl.java
index 1414e90..f1ca832 100644
--- a/geode-cq/src/main/java/org/apache/geode/cache/query/internal/cq/CqServiceImpl.java
+++ b/geode-cq/src/main/java/org/apache/geode/cache/query/internal/cq/CqServiceImpl.java
@@ -125,6 +125,15 @@ public final class CqServiceImpl implements CqService {
 
 
   /**
+   * Access and modification to the contents of this map do not necessarily need to be lock
+   * protected. This is just used to optimize construction of a server side cq name. Missing values
+   * in this cache will mean a look up for a specific proxy id and cq name will miss and reconstruct
+   * the string before adding it back to the cache
+   */
+  private static final ConcurrentHashMap<String, ConcurrentHashMap<ClientProxyMembershipID, String>> serverCqNameCache =
+      new ConcurrentHashMap<>();
+
+  /**
    * Constructor.
    * 
    * @param c The cache used for the service
@@ -631,6 +640,7 @@ public final class CqServiceImpl implements CqService {
     String serverCqName = cqName;
     if (clientId != null) {
       serverCqName = this.constructServerCqName(cqName, clientId);
+      removeFromCacheForServerToConstructedCQName(cqName, clientId);
     }
 
     ServerCQImpl cQuery = null;
@@ -693,6 +703,7 @@ public final class CqServiceImpl implements CqService {
     String serverCqName = cqName;
     if (clientProxyId != null) {
       serverCqName = this.constructServerCqName(cqName, clientProxyId);
+      removeFromCacheForServerToConstructedCQName(cqName, clientProxyId);
     }
 
     ServerCQImpl cQuery = null;
@@ -1021,21 +1032,12 @@ public final class CqServiceImpl implements CqService {
     this.isRunning = true;
   }
 
-  private static final ConcurrentHashMap<String, ConcurrentHashMap<ClientProxyMembershipID, String>> serverCqNameCache =
-      new ConcurrentHashMap<>();
-
   /**
    * @return Returns the serverCqName.
    */
   public String constructServerCqName(String cqName, ClientProxyMembershipID clientProxyId) {
-    ConcurrentHashMap<ClientProxyMembershipID, String> cache = serverCqNameCache.get(cqName);
-    if (null == cache) {
-      final ConcurrentHashMap<ClientProxyMembershipID, String> old = serverCqNameCache
-          .putIfAbsent(cqName, cache = new ConcurrentHashMap<ClientProxyMembershipID, String>());
-      if (null != old) {
-        cache = old;
-      }
-    }
+    ConcurrentHashMap<ClientProxyMembershipID, String> cache = serverCqNameCache
+        .computeIfAbsent(cqName, key -> new ConcurrentHashMap<ClientProxyMembershipID, String>());
 
     String cName = cache.get(clientProxyId);
     if (null == cName) {
@@ -1052,6 +1054,17 @@ public final class CqServiceImpl implements CqService {
     return cName;
   }
 
+  private void removeFromCacheForServerToConstructedCQName(final String cqName,
+      ClientProxyMembershipID clientProxyMembershipID) {
+    ConcurrentHashMap<ClientProxyMembershipID, String> cache = serverCqNameCache.get(cqName);
+    if (cache != null) {
+      cache.remove(clientProxyMembershipID);
+      if (cache.size() == 0) {
+        serverCqNameCache.remove(cqName);
+      }
+    }
+  }
+
   /*
    * Checks if CQ with the given name already exists.
    * 

http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/5ef9f903/geode-cq/src/test/java/org/apache/geode/cache/query/internal/cq/CqServiceUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-cq/src/test/java/org/apache/geode/cache/query/internal/cq/CqServiceUnitTest.java b/geode-cq/src/test/java/org/apache/geode/cache/query/internal/cq/CqServiceUnitTest.java
new file mode 100644
index 0000000..7dc366e
--- /dev/null
+++ b/geode-cq/src/test/java/org/apache/geode/cache/query/internal/cq/CqServiceUnitTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.geode.cache.query.internal.cq;
+
+
+import static org.junit.Assert.assertEquals;
+
+import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
+import org.apache.geode.test.fake.Fakes;
+import org.apache.geode.test.junit.categories.UnitTest;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category(UnitTest.class)
+public class CqServiceUnitTest {
+
+  @Test
+  public void constructCqServerNameShouldReturnSameResultRegardlessOfOptimizedCacheNames() {
+    CqServiceImpl cqService = new CqServiceImpl(Fakes.cache());
+    ClientProxyMembershipID proxyMembershipID =
+        new ClientProxyMembershipID(Fakes.cache().getDistributedSystem().getDistributedMember());
+    String name1 = cqService.constructServerCqName("myCq", proxyMembershipID);
+    String name2 = cqService.constructServerCqName("myCq", proxyMembershipID);
+    assertEquals(name1, name2);
+  }
+
+  @Test
+  public void constructCqServerNameShouldReturnCorrectResultsEvenAfterCqClosingRemovesValuesFromOptimizedCache()
+      throws Exception {
+    CqServiceImpl cqService = new CqServiceImpl(Fakes.cache());
+    ClientProxyMembershipID proxyMembershipID =
+        new ClientProxyMembershipID(Fakes.cache().getDistributedSystem().getDistributedMember());
+    String name1 = cqService.constructServerCqName("myCq", proxyMembershipID);
+    cqService.closeCq("myCq", proxyMembershipID);
+    String name2 = cqService.constructServerCqName("myCq", proxyMembershipID);
+    assertEquals(name1, name2);
+  }
+
+
+}