You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by bs...@apache.org on 2018/08/30 14:34:44 UTC

[geode] branch develop updated: GEODE-5645 Client cache misses invalidate

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

bschuchardt 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 ff56282  GEODE-5645 Client cache misses invalidate
ff56282 is described below

commit ff56282cce85ca7802bf995ec3798c0c5916a140
Author: Bruce Schuchardt <bs...@pivotal.io>
AuthorDate: Thu Aug 30 07:33:37 2018 -0700

    GEODE-5645 Client cache misses invalidate
    
    Notify clients/gateways on an invalidation that is overwriting an
    existing invalidated entry.  This allows them to update their version
    information in case there is an operation that conflicts with this
    invalidation and should be thrown away.
---
 .../tier/sockets/ClientServerMiscDUnitTest.java    | 86 ++++++++++++++++++++++
 .../geode/internal/cache/AbstractRegionMap.java    | 30 ++++----
 .../sockets/ClientServerMiscDUnitTestBase.java     | 13 ++--
 3 files changed, 111 insertions(+), 18 deletions(-)

diff --git a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java
index 5aa5a83..f2fe2a5 100755
--- a/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java
+++ b/geode-core/src/distributedTest/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTest.java
@@ -15,6 +15,92 @@
 
 package org.apache.geode.internal.cache.tier.sockets;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.concurrent.TimeUnit;
+
+import org.awaitility.Awaitility;
+import org.junit.Test;
+
+import org.apache.geode.cache.Operation;
+import org.apache.geode.cache.Region;
+import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.cache.EntryEventImpl;
+import org.apache.geode.internal.cache.EventID;
+import org.apache.geode.internal.cache.LocalRegion;
+import org.apache.geode.internal.cache.RegionEntry;
+import org.apache.geode.internal.cache.versions.VersionTag;
+import org.apache.geode.test.dunit.NetworkUtils;
+import org.apache.geode.test.dunit.VM;
+
 public class ClientServerMiscDUnitTest extends ClientServerMiscDUnitTestBase {
 
+
+  /**
+   * Ensure that an Invalidate event that
+   */
+  @Test
+  public void testInvalidateOnInvalidEntryInServerReachesClient() throws Exception {
+    VM server = VM.getVM(0);
+    String regionPath = Region.SEPARATOR + REGION_NAME2;
+    PORT1 = server.invoke(() -> {
+      int port = createServerCache(true, -1, false);
+      getCache().getRegion(regionPath).put(server_k1, "VALUE1");
+      getCache().getRegion(regionPath).invalidate(server_k1);
+      return port;
+    });
+    createClientCache(NetworkUtils.getServerHostName(), PORT1);
+    registerInterest();
+    Region region = static_cache.getRegion(regionPath);
+    assertThat(region.containsKey(server_k1)).isTrue();
+    assertThat(region.get(server_k1)).isNull();
+
+    System.out.println("do it with a forceEntry==false code path");
+    RegionEntry entry = ((LocalRegion) region).getRegionEntry(server_k1);
+    int entryVersion = entry.getVersionStamp().getEntryVersion();
+    server.invoke(() -> {
+      // getCache().getRegion(regionPath).invalidate(server_k1);
+
+      // create a "remote" invalidateion event and invalidate the already-invalid entry
+      LocalRegion localRegion = (LocalRegion) getCache().getRegion(regionPath);
+      VersionTag tag = localRegion.getRegionEntry(server_k1).getVersionStamp().asVersionTag();
+      InternalDistributedMember id = localRegion.getMyId();
+      tag.setMemberID(new InternalDistributedMember(id.getInetAddress(), id.getPort() + 1));
+      tag.setEntryVersion(tag.getEntryVersion() + 1);
+      tag.setEntryVersion(5);
+      tag.setIsRemoteForTesting();
+      EntryEventImpl event =
+          EntryEventImpl.create(localRegion, Operation.INVALIDATE, server_k1, null,
+              null, false, id);
+      EventID eventID = new EventID(new byte[100], 1, 1);
+      event.setVersionTag(tag);
+      event.setEventId(eventID);
+      localRegion.getRegionMap().invalidate(event, false, false, false);
+    });
+    Awaitility.await().atMost(5, TimeUnit.MINUTES)
+        .until(() -> entry.getVersionStamp().getEntryVersion() > entryVersion);
+
+    System.out.println("do it again with a forceEntry==true code path");
+    RegionEntry entry2 = ((LocalRegion) region).getRegionEntry(server_k1);
+    int entryVersion2 = entry.getVersionStamp().getEntryVersion();
+    server.invoke(() -> {
+      // create a "remote" invalidateion event and invalidate the already-invalid entry
+      LocalRegion localRegion = (LocalRegion) getCache().getRegion(regionPath);
+      VersionTag tag = localRegion.getRegionEntry(server_k1).getVersionStamp().asVersionTag();
+      InternalDistributedMember id = localRegion.getMyId();
+      tag.setMemberID(new InternalDistributedMember(id.getInetAddress(), id.getPort() + 1));
+      tag.setEntryVersion(tag.getEntryVersion() + 1);
+      tag.setEntryVersion(6);
+      tag.setIsRemoteForTesting();
+      EntryEventImpl event =
+          EntryEventImpl.create(localRegion, Operation.INVALIDATE, server_k1, null,
+              null, false, id);
+      EventID eventID = new EventID(new byte[100], 1, 2);
+      event.setVersionTag(tag);
+      event.setEventId(eventID);
+      localRegion.getRegionMap().invalidate(event, false, true, false);
+    });
+    Awaitility.await().atMost(5, TimeUnit.MINUTES)
+        .until(() -> entry2.getVersionStamp().getEntryVersion() > entryVersion2);
+  }
 }
diff --git a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
index eefa190..76ed86c 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java
@@ -1377,11 +1377,7 @@ public abstract class AbstractRegionMap
                       } else if (oldRe.isInvalid()) {
 
                         // was already invalid, do not invoke listeners or increment stat
-                        if (isDebugEnabled) {
-                          logger.debug("mapInvalidate: Entry already invalid: '{}'",
-                              event.getKey());
-                        }
-                        processVersionTag(oldRe, event);
+                        handleAlreadyInvalidEntry(event, owner, oldRe);
                         try {
                           oldRe.setValue(owner, oldRe.getValueInVM(owner)); // OFFHEAP noop setting
                                                                             // an already invalid to
@@ -1622,14 +1618,7 @@ public abstract class AbstractRegionMap
                     if (re.isInvalid()) {
                       // was already invalid, do not invoke listeners or increment
                       // stat
-                      if (isDebugEnabled) {
-                        logger.debug("Invalidate: Entry already invalid: '{}'", event.getKey());
-                      }
-                      if (event.getVersionTag() != null && owner.getVersionVector() != null) {
-                        owner.getVersionVector().recordVersion(
-                            (InternalDistributedMember) event.getDistributedMember(),
-                            event.getVersionTag());
-                      }
+                      handleAlreadyInvalidEntry(event, owner, re);
                     } else { // previous value not invalid
                       event.setRegionEntry(re);
                       owner.serverInvalidate(event);
@@ -1730,6 +1719,21 @@ public abstract class AbstractRegionMap
 
   }
 
+  /**
+   * If an entry is already invalid we still want to perform a conflict check, update
+   * the entry's version stamp and invoke listeners.
+   */
+  private void handleAlreadyInvalidEntry(EntryEventImpl event, LocalRegion owner, RegionEntry re) {
+    if (logger.isDebugEnabled()) {
+      logger.debug("Invalidate: Entry already invalid: '{}'", event.getKey());
+    }
+    processVersionTag(re, event);
+    if (owner.getConcurrencyChecksEnabled() && event.hasValidVersionTag()) {
+      // notify clients so they can update their version stamps
+      event.invokeCallbacks(owner, true, true);
+    }
+  }
+
   private void invalidateNewEntry(EntryEventImpl event, final LocalRegion owner, RegionEntry newRe)
       throws RegionClearedException {
     processVersionTag(newRe, event);
diff --git a/geode-dunit/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTestBase.java b/geode-dunit/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTestBase.java
index 20d10ea..3a03664 100755
--- a/geode-dunit/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTestBase.java
+++ b/geode-dunit/src/main/java/org/apache/geode/internal/cache/tier/sockets/ClientServerMiscDUnitTestBase.java
@@ -15,6 +15,7 @@
 package org.apache.geode.internal.cache.tier.sockets;
 
 import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.distributed.ConfigurationProperties.LOG_LEVEL;
 import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
 import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.junit.Assert.assertEquals;
@@ -84,6 +85,7 @@ import org.apache.geode.test.dunit.NetworkUtils;
 import org.apache.geode.test.dunit.VM;
 import org.apache.geode.test.dunit.Wait;
 import org.apache.geode.test.dunit.cache.internal.JUnit4CacheTestCase;
+import org.apache.geode.test.dunit.standalone.DUnitLauncher;
 import org.apache.geode.test.dunit.standalone.VersionManager;
 import org.apache.geode.test.junit.categories.ClientServerTest;
 
@@ -97,19 +99,19 @@ public class ClientServerMiscDUnitTestBase extends JUnit4CacheTestCase {
 
   protected static Connection conn = null;
 
-  private static Cache static_cache;
+  static Cache static_cache;
 
-  private static int PORT1;
+  static int PORT1;
 
   private static final String k1 = "k1";
 
   private static final String k2 = "k2";
 
-  private static final String server_k1 = "server-k1";
+  static final String server_k1 = "server-k1";
 
-  private static final String server_k2 = "server-k2";
+  static final String server_k2 = "server-k2";
 
-  private static final String REGION_NAME1 = "ClientServerMiscDUnitTest_region1";
+  static final String REGION_NAME1 = "ClientServerMiscDUnitTest_region1";
 
   static final String REGION_NAME2 = "ClientServerMiscDUnitTest_region2";
 
@@ -827,6 +829,7 @@ public class ClientServerMiscDUnitTestBase extends JUnit4CacheTestCase {
     Properties props = new Properties();
     props.setProperty(MCAST_PORT, "0");
     props.setProperty(LOCATORS, "");
+    props.setProperty(LOG_LEVEL, DUnitLauncher.logLevel);
     Cache cache = new ClientServerMiscDUnitTestBase().createCacheV(props);
     ClientServerMiscDUnitTestBase.static_cache = cache;
     System.setProperty(DistributionConfig.GEMFIRE_PREFIX + "bridge.disableShufflingOfEndpoints",