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 c6fe1df GEODE-5596 Client ends up with destroyed entry after
invalidate()
c6fe1df is described below
commit c6fe1df8c7273e2122be8505ce0baacccfc1c026
Author: Bruce Schuchardt <[email protected]>
AuthorDate: Thu Aug 30 07:55:14 2018 -0700
GEODE-5596 Client ends up with destroyed entry after invalidate()
Modifying client cache behavior to create an Invalid entry when an
application
invokes invalid() and the entry is currently in Destroyed state on the
client
but not on servers.
I also changed the AttributesFactory javadoc for
concurrencyChecksEnabled to note that the default value is true, not
false, and added a test for this setting.
this closes #2384
---
.../geode/cache30/ClientServerCCEDUnitTest.java | 72 +++++++++++++++++++++-
.../org/apache/geode/cache/AttributesFactory.java | 2 +-
.../geode/internal/cache/AbstractRegionMap.java | 7 +--
.../apache/geode/internal/cache/LocalRegion.java | 4 +-
.../geode/cache/AttributesFactoryJUnitTest.java | 1 +
.../sockets/ClientServerMiscDUnitTestBase.java | 31 ++++------
6 files changed, 87 insertions(+), 30 deletions(-)
diff --git
a/geode-core/src/distributedTest/java/org/apache/geode/cache30/ClientServerCCEDUnitTest.java
b/geode-core/src/distributedTest/java/org/apache/geode/cache30/ClientServerCCEDUnitTest.java
index 1878aa0..08a7edb 100644
---
a/geode-core/src/distributedTest/java/org/apache/geode/cache30/ClientServerCCEDUnitTest.java
+++
b/geode-core/src/distributedTest/java/org/apache/geode/cache30/ClientServerCCEDUnitTest.java
@@ -45,6 +45,7 @@ import org.apache.geode.cache.EntryEvent;
import org.apache.geode.cache.ExpirationAction;
import org.apache.geode.cache.ExpirationAttributes;
import org.apache.geode.cache.InterestResultPolicy;
+import org.apache.geode.cache.Operation;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.Scope;
@@ -63,7 +64,12 @@ import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.cache.CachePerfStats;
import org.apache.geode.internal.cache.DistributedRegion;
import
org.apache.geode.internal.cache.DistributedTombstoneOperation.TombstoneMessage;
+import org.apache.geode.internal.cache.EntryEventImpl;
+import org.apache.geode.internal.cache.EventID;
+import org.apache.geode.internal.cache.KeyInfo;
import org.apache.geode.internal.cache.LocalRegion;
+import org.apache.geode.internal.cache.RegionMap;
+import org.apache.geode.internal.cache.Token;
import org.apache.geode.internal.cache.entries.AbstractRegionEntry;
import org.apache.geode.internal.cache.ha.HARegionQueue;
import org.apache.geode.internal.cache.partitioned.PRTombstoneMessage;
@@ -567,6 +573,69 @@ public class ClientServerCCEDUnitTest extends
JUnit4CacheTestCase {
}
@Test
+ public void testClientInvalidateAfterDestroyLeavesInvalidEntryRR() throws
Exception {
+ clientInvalidateAfterDestroyLeavesInvalidEntryTest(getUniqueName(), true);
+ }
+
+ @Test
+ public void testClientInvalidateAfterDestroyLeavesInvalidEntryPR() throws
Exception {
+ clientInvalidateAfterDestroyLeavesInvalidEntryTest(getUniqueName(), false);
+ }
+
+ private void clientInvalidateAfterDestroyLeavesInvalidEntryTest(String
uniqueName,
+ boolean useReplicateRegion) {
+ Host host = Host.getHost(0);
+ VM serverVM = host.getVM(0);
+ VM clientVM = host.getVM(1);
+ final String name = uniqueName + "Region";
+
+
+ int port = createServerRegion(serverVM, name, useReplicateRegion);
+
+ createClientRegion(clientVM, name, port, true,
ClientRegionShortcut.CACHING_PROXY, false);
+ final String key = "Object0";
+
+ // use the client cache to create and destroy an entry
+ clientVM.invoke(() -> {
+ TestRegion.put(key, "some value"); // v1
+ TestRegion.destroy(key); // v2
+ RegionMap map = TestRegion.getRegionMap();
+ AbstractRegionEntry regionEntry = (AbstractRegionEntry)
map.getEntry(key);
+ assertEquals(Token.TOMBSTONE, regionEntry.getValueAsToken());
+ });
+
+ // use the server cache to recreate the entry, but don't let the client
cache know about it
+ serverVM.invoke(() -> {
+ TestRegion.put(key, "new value"); // v3 - not known by client cache
+ });
+
+ // now invalidate the entry in the client cache and show that it holds an
INVALID entry
+ clientVM.invoke(() -> {
+ RegionMap map = TestRegion.getRegionMap();
+ AbstractRegionEntry regionEntry = (AbstractRegionEntry)
map.getEntry(key);
+
+ EntryEventImpl invalidateEvent = new EntryEventImpl();
+ invalidateEvent.setRegion(TestRegion);
+ invalidateEvent.setKeyInfo(new KeyInfo(key, Token.INVALID, null));
+ invalidateEvent.setOperation(Operation.INVALIDATE);
+ invalidateEvent.setEventId(new
EventID(TestRegion.getCache().getDistributedSystem()));
+
+ // invoke invalidate() with forceNewEntry=true to have it create an
INVALID entry
+ map.invalidate(invalidateEvent, true, true, false);
+
+ assertEquals(Token.INVALID, regionEntry.getValueAsToken());
+ System.out.println("entry=" + regionEntry);
+ assertEquals(4, regionEntry.getVersionStamp().getEntryVersion());
+ });
+
+ serverVM.invoke(() -> {
+ assertTrue(TestRegion.containsKey(key));
+ assertNull(TestRegion.get(key));
+ });
+
+ }
+
+ @Test
public void testClientCacheListenerDoesNotSeeTombstones() throws Exception {
Host host = Host.getHost(0);
VM vm0 = host.getVM(0);
@@ -606,9 +675,7 @@ public class ClientServerCCEDUnitTest extends
JUnit4CacheTestCase {
private void unregisterInterest(VM vm) {
vm.invoke(new SerializableRunnable("unregister interest in all keys") {
public void run() {
- // TestRegion.dumpBackingMap();
TestRegion.unregisterInterestRegex(".*");
- // TestRegion.dumpBackingMap();
}
});
}
@@ -940,6 +1007,7 @@ public class ClientServerCCEDUnitTest extends
JUnit4CacheTestCase {
af.setPartitionAttributes(
(new
PartitionAttributesFactory()).setTotalNumBuckets(2).create());
}
+ af.setConcurrencyChecksEnabled(true);
TestRegion = (LocalRegion) createRootRegion(regionName, af.create());
CacheServer server = getCache().addCacheServer();
diff --git
a/geode-core/src/main/java/org/apache/geode/cache/AttributesFactory.java
b/geode-core/src/main/java/org/apache/geode/cache/AttributesFactory.java
index 2017cf2..93d9a99 100644
--- a/geode-core/src/main/java/org/apache/geode/cache/AttributesFactory.java
+++ b/geode-core/src/main/java/org/apache/geode/cache/AttributesFactory.java
@@ -193,7 +193,7 @@ import org.apache.geode.internal.i18n.LocalizedStrings;
* others will only read. <br>
* {@link #setConcurrencyLevel} {@link
RegionAttributes#getConcurrencyLevel}</dd>
*
- * <dt>ConcurrencyChecksEnabled [<em>default:</em> {@code false}]</dt>
+ * <dt>ConcurrencyChecksEnabled [<em>default:</em> {@code true}]</dt>
* <dd>Enables a distributed versioning algorithm that detects concurrency
conflicts in regions and
* ensures that changes to an entry are not applied in a different order in
other members. This can
* cause operations to be conflated, so that some cache listeners may see an
event while others do
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 76ed86c..bc1ca9b 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
@@ -1331,6 +1331,7 @@ public abstract class AbstractRegionMap
Assert.assertTrue(false, "The owner for RegionMap " + this + " is null
for event " + event);
}
+ logger.debug("ARM.invalidate invoked for key {}", event.getKey());
boolean didInvalidate = false;
RegionEntry invalidatedRe = null;
boolean clearOccured = false;
@@ -1573,12 +1574,6 @@ public abstract class AbstractRegionMap
} else if (tombstone != null) {
processVersionTag(tombstone, event);
try {
- if (!tombstone.isTombstone()) {
- if (isDebugEnabled) {
- logger.debug("tombstone is no longer a
tombstone. {}:event={}",
- tombstone, event);
- }
- }
tombstone.setValue(owner, Token.TOMBSTONE);
} catch (RegionClearedException e) {
// that's okay - when writing a tombstone into a
disk, the
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
index 92c2e3c..b5250f3 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/LocalRegion.java
@@ -4954,7 +4954,9 @@ public class LocalRegion extends AbstractRegion
implements LoaderHelperFactory,
*/
private void basicInvalidate(final EntryEventImpl event, boolean
invokeCallbacks)
throws EntryNotFoundException {
- basicInvalidate(event, invokeCallbacks, false);
+ final boolean forceNewEntryInClientCache = this.serverRegionProxy != null
+ && getConcurrencyChecksEnabled();
+ basicInvalidate(event, invokeCallbacks, forceNewEntryInClientCache);
}
/**
diff --git
a/geode-core/src/test/java/org/apache/geode/cache/AttributesFactoryJUnitTest.java
b/geode-core/src/test/java/org/apache/geode/cache/AttributesFactoryJUnitTest.java
index a1d39e1..9b6ed7d 100644
---
a/geode-core/src/test/java/org/apache/geode/cache/AttributesFactoryJUnitTest.java
+++
b/geode-core/src/test/java/org/apache/geode/cache/AttributesFactoryJUnitTest.java
@@ -265,6 +265,7 @@ public class AttributesFactoryJUnitTest {
assertNotNull(diskSizes);
assertEquals(1, diskSizes.length);
assertEquals(DiskStoreFactory.DEFAULT_DISK_DIR_SIZE, diskSizes[0]);
+ assertTrue(attrs.getConcurrencyChecksEnabled());
}
@Test
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 3a03664..aeb22bf 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
@@ -17,6 +17,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.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -46,6 +47,7 @@ import org.apache.geode.cache.CacheException;
import org.apache.geode.cache.CacheWriterException;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.EntryEvent;
+import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.PartitionAttributesFactory;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionAttributes;
@@ -556,27 +558,16 @@ public class ClientServerMiscDUnitTestBase extends
JUnit4CacheTestCase {
Region region = static_cache.getRegion(REGION_NAME1);
populateCache();
region.put("invalidationKey", "invalidationValue");
+
region.localDestroy("invalidationKey");
- if (region.containsKey("invalidationKey")) {
- fail("region still contains invalidationKey");
- }
+ assertThat(region.containsKey("invalidationKey")).isFalse();
+
region.invalidate("invalidationKey");
- if (region.containsKey("invalidationKey")) {
- fail(
- "this test expects the entry is not created on invalidate() if not
there before the operation");
- }
+ assertThat(region.containsKey("invalidationKey")).isTrue();
+
Object value = region.get("invalidationKey");
- if (value != null) {
- fail("this test expected a null response to get('invalidationKey')");
- }
- if (!region.containsKeyOnServer("invalidationKey")) {
- fail("expected an entry on the server after invalidation");
- }
- // bug 43407 asserts that there should be an entry, but the product does
not
- // do this. This verifies that the product does not behave as asserted in
that bug
- if (region.containsKey("invalidationKey")) {
- fail("expected no entry after invalidation when entry was not in client
but was on server");
- }
+ assertThat(value).isNull();
+ assertThat(region.containsKeyOnServer("invalidationKey")).isTrue();
}
/**
@@ -989,8 +980,8 @@ public class ClientServerMiscDUnitTestBase extends
JUnit4CacheTestCase {
assertNotNull(r1);
Region r2 = cache.getRegion(Region.SEPARATOR + REGION_NAME2);
assertNotNull(r2);
- r1.registerInterest("ALL_KEYS", false, false);
- r2.registerInterest("ALL_KEYS", false, false);
+ r1.registerInterestForAllKeys(InterestResultPolicy.KEYS, false, false);
+ r2.registerInterestForAllKeys(InterestResultPolicy.KEYS, false, false);
} catch (CacheWriterException e) {
e.printStackTrace();
fail("Test failed due to CacheWriterException during
registerInterestnBothRegions" + e);