GEODE-3204: txApplyInvalidate in AbstractRegionMap on farside does not update on a region entry with removed token.
Project: http://git-wip-us.apache.org/repos/asf/geode/repo Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/0bce1eaf Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/0bce1eaf Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/0bce1eaf Branch: refs/heads/feature/GEM-1483 Commit: 0bce1eaffd1b8c0f482519ec47ea43231e8f40f1 Parents: a1ee957 Author: eshu <e...@pivotal.io> Authored: Mon Jul 17 09:14:36 2017 -0700 Committer: eshu <e...@pivotal.io> Committed: Mon Jul 17 09:14:36 2017 -0700 ---------------------------------------------------------------------- .../geode/internal/cache/AbstractRegionMap.java | 13 +++--- .../internal/cache/AbstractRegionMapTest.java | 48 ++++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/geode/blob/0bce1eaf/geode-core/src/main/java/org/apache/geode/internal/cache/AbstractRegionMap.java ---------------------------------------------------------------------- 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 7f12eab..f958f94 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 @@ -2513,9 +2513,9 @@ public abstract class AbstractRegionMap implements RegionMap { RegionEntry re = getEntry(key); if (re != null) { synchronized (re) { - { + // Fix GEODE-3204, do not invalidate the region entry if it is a removed token + if (!Token.isRemoved(re.getValueAsToken())) { final int oldSize = owner.calculateRegionEntryValueSize(re); - boolean wasTombstone = re.isTombstone(); Object oldValue = re.getValueInVM(owner); // OFFHEAP eei // Create an entry event only if the calling context is // a receipt of a TXCommitMessage AND there are callbacks @@ -2543,9 +2543,6 @@ public abstract class AbstractRegionMap implements RegionMap { try { re.setValue(owner, re.prepareValueForCache(owner, newValue, true)); EntryLogger.logTXInvalidate(_getOwnerObject(), key); - if (wasTombstone) { - owner.unscheduleTombstone(re); - } owner.updateSizeOnPut(key, oldSize, 0); } catch (RegionClearedException rce) { clearOccured = true; @@ -2572,9 +2569,11 @@ public abstract class AbstractRegionMap implements RegionMap { if (!cbEventInPending) cbEvent.release(); } + return; } } - } else { // re == null + } + { // re == null or region entry is removed token. // Fix bug#43594 // In cases where bucket region is re-created, it may so happen // that the invalidate is already applied on the Initial image @@ -3107,7 +3106,7 @@ public abstract class AbstractRegionMap implements RegionMap { final boolean hasRemoteOrigin = !((TXId) txId).getMemberId().equals(owner.getMyId()); final boolean isTXHost = txEntryState != null; - final boolean isClientTXOriginator = owner.cache.isClient() && !hasRemoteOrigin; + final boolean isClientTXOriginator = owner.getCache().isClient() && !hasRemoteOrigin; final boolean isRegionReady = owner.isInitialized(); @Released EntryEventImpl cbEvent = null; http://git-wip-us.apache.org/repos/asf/geode/blob/0bce1eaf/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java ---------------------------------------------------------------------- diff --git a/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java index 60b93a9..893d842 100644 --- a/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java +++ b/geode-core/src/test/java/org/apache/geode/internal/cache/AbstractRegionMapTest.java @@ -15,7 +15,9 @@ package org.apache.geode.internal.cache; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Mockito.any; @@ -31,6 +33,7 @@ import static org.mockito.Mockito.when; import org.apache.geode.cache.DataPolicy; import org.apache.geode.cache.EntryNotFoundException; import org.apache.geode.cache.Operation; +import org.apache.geode.distributed.internal.membership.InternalDistributedMember; import org.apache.geode.internal.cache.versions.VersionHolder; import org.apache.geode.test.junit.categories.UnitTest; import org.junit.Test; @@ -187,4 +190,49 @@ public class AbstractRegionMapTest { initialize(owner, new Attributes(), null, false); } } + + private static class TxTestableAbstractRegionMap extends AbstractRegionMap { + + public LocalRegion owner; + + protected TxTestableAbstractRegionMap() { + super(null); + this.owner = mock(LocalRegion.class); + when(this.owner.getCache()).thenReturn(mock(InternalCache.class)); + when(this.owner.isAllEvents()).thenReturn(true); + when(this.owner.isInitialized()).thenReturn(true); + initialize(owner, new Attributes(), null, false); + } + } + + @Test + public void txApplyInvalidateDoesNotInvalidateRemovedToken() throws RegionClearedException { + TxTestableAbstractRegionMap arm = new TxTestableAbstractRegionMap(); + + Object key = "key"; + Object newValue = "value"; + arm.txApplyPut(Operation.CREATE, key, newValue, false, + new TXId(mock(InternalDistributedMember.class), 1), mock(TXRmtEvent.class), + mock(EventID.class), null, null, null, null, null, null, 1); + RegionEntry re = arm.getEntry(key); + assertNotNull(re); + + Token[] removedTokens = + {Token.REMOVED_PHASE2, Token.REMOVED_PHASE1, Token.DESTROYED, Token.TOMBSTONE}; + + for (Token token : removedTokens) { + verifyTxApplyInvalidate(arm, key, re, token); + } + + } + + private void verifyTxApplyInvalidate(TxTestableAbstractRegionMap arm, Object key, RegionEntry re, + Token token) throws RegionClearedException { + re.setValue(arm.owner, token); + arm.txApplyInvalidate(key, Token.INVALID, false, + new TXId(mock(InternalDistributedMember.class), 1), mock(TXRmtEvent.class), false, + mock(EventID.class), null, null, null, null, null, null, 1); + assertEquals(re.getValueAsToken(), token); + } + }