use of org.apache.geode.internal.cache.versions.VersionTag in project geode by apache.
the class GIIDeltaDUnitTest method testDeltaGIIWithOnlyUnfinishedOp_GCAtR.
/**
* This is to test a race condition for bug#47616 vm0 and vm1 are peers, each holds a DR. create
* some exception list. Before GII, P's RVV is P6,R6(3-6), R's RVV is P6,R6, RVVGC are both P4,R0
* vm1 becomes offline then restarts. The deltaGII should send delta which only contains
* unfinished opeation R4,R5
*/
@Test
public void testDeltaGIIWithOnlyUnfinishedOp_GCAtR() throws Throwable {
prepareForEachTest();
final DiskStoreID memberP = getMemberID(P);
final DiskStoreID memberR = getMemberID(R);
final long[] exceptionlist = { 4, 5 };
assertEquals(0, DistributedCacheOperation.SLOW_DISTRIBUTION_MS);
prepareCommonTestData(6);
VersionTag expect_tag = getVersionTag(R, "key5");
// force tombstone GC to let RVVGC to become P4:R0
forceGC(P, 2);
// P's rvv=p6, gc=4
waitForToVerifyRVV(P, memberP, 6, null, 4);
// P's rvv=r3, gc=0
waitForToVerifyRVV(P, memberR, 3, null, 0);
createUnfinishedOperationsR4R5();
// P's rvv=r6, gc=0
waitForToVerifyRVV(P, memberR, 6, exceptionlist, 0);
// 2
R.invoke(new SerializableRunnable() {
public void run() {
Mycallback myAfterRequestRVV = new Mycallback(GIITestHookType.AfterRequestRVV, REGION_NAME);
InitialImageOperation.setGIITestHook(myAfterRequestRVV);
}
});
// now P's cache still only has key1, key3, key5
byte[] R_rvv_bytes = getRVVByteArray(R, REGION_NAME);
closeCache(R);
// restart and gii
checkIfFullGII(P, REGION_NAME, R_rvv_bytes, false);
AsyncInvocation async3 = createDistributedRegionAsync(R);
// 2
waitForCallbackStarted(R, GIITestHookType.AfterRequestRVV);
forceGC(R, 1);
R.invoke(() -> InitialImageOperation.resetGIITestHook(GIITestHookType.AfterRequestRVV, true));
async3.join(MAX_WAIT);
// verify unfinished op for key5 is revoked
waitToVerifyKey(R, "key5", generateValue(R));
VersionTag tag = getVersionTag(R, "key5");
assertTrue(expect_tag.equals(tag));
verifyTombstoneExist(R, "key5", false, false);
// If fullGII, the key size in gii chunk is 3, i.e. key1,key3,key5. key2 is GCed.
// If delta GII, the key size should be 1 (key5(T) which is unfinished operation)
verifyDeltaSizeFromStats(R, 3, 0);
}
use of org.apache.geode.internal.cache.versions.VersionTag in project geode by apache.
the class TombstoneCreationJUnitTest method testDestroyCreatesTombstone.
@Test
public void testDestroyCreatesTombstone() throws Exception {
String name = nameRule.getMethodName();
Properties props = new Properties();
props.put(LOCATORS, "");
props.put(MCAST_PORT, "0");
props.put(LOG_LEVEL, "config");
GemFireCacheImpl cache = (GemFireCacheImpl) CacheFactory.create(DistributedSystem.connect(props));
RegionFactory f = cache.createRegionFactory(RegionShortcut.REPLICATE);
DistributedRegion region = (DistributedRegion) f.create(name);
EntryEventImpl ev = EntryEventImpl.create(region, Operation.DESTROY, "myDestroyedKey", null, null, true, new InternalDistributedMember(InetAddress.getLocalHost(), 1234));
VersionTag tag = VersionTag.create((InternalDistributedMember) ev.getDistributedMember());
tag.setIsRemoteForTesting();
tag.setEntryVersion(2);
tag.setRegionVersion(12345);
tag.setVersionTimeStamp(System.currentTimeMillis());
tag.setDistributedSystemId(1);
ev.setVersionTag(tag);
cache.getLogger().info("destroyThread is trying to destroy the entry: " + region.getRegionEntry("myDestroyedKey"));
// expectedOldValue not supported on
region.basicDestroy(ev, false, null);
RegionEntry entry = region.getRegionEntry("myDestroyedKey");
Assert.assertTrue(entry != null, "expected to find a region entry for myDestroyedKey");
Assert.assertTrue(entry.isTombstone(), "expected entry to be found and be a tombstone but it is " + entry);
}
use of org.apache.geode.internal.cache.versions.VersionTag in project geode by apache.
the class TombstoneCreationJUnitTest method testConcurrentCreateAndDestroy.
/**
* In bug #47868 a thread puts a REMOVED_PHASE1 entry in the map but is unable to lock the entry
* before a Destroy thread gets it. The Destroy thread did not apply its operation but threw an
* EntryNotFoundException. It is supposed to create a Tombstone.
*
* @throws Exception
*/
@Test
public void testConcurrentCreateAndDestroy() throws Exception {
String name = nameRule.getMethodName();
Properties props = new Properties();
props.put(LOCATORS, "");
props.put(MCAST_PORT, "0");
props.put(LOG_LEVEL, "config");
final GemFireCacheImpl cache = (GemFireCacheImpl) CacheFactory.create(DistributedSystem.connect(props));
RegionFactory f = cache.createRegionFactory(RegionShortcut.REPLICATE);
final DistributedRegion region = (DistributedRegion) f.create(name);
// simulate a put() getting into AbstractRegionMap.basicPut() and creating an entry
// that has not yet been initialized with values. Then do a destroy that will encounter
// the entry
String key = "destroyedKey1";
VersionedThinRegionEntryHeap entry = new VersionedThinRegionEntryHeapObjectKey(region, key, Token.REMOVED_PHASE1);
((AbstractRegionMap) region.getRegionMap()).putEntryIfAbsentForTest(entry);
cache.getLogger().info("entry inserted into cache: " + entry);
EntryEventImpl ev = EntryEventImpl.create(region, Operation.DESTROY, key, null, null, true, new InternalDistributedMember(InetAddress.getLocalHost(), 1234));
VersionTag tag = VersionTag.create((InternalDistributedMember) ev.getDistributedMember());
tag.setIsRemoteForTesting();
tag.setEntryVersion(2);
tag.setRegionVersion(12345);
tag.setVersionTimeStamp(System.currentTimeMillis());
tag.setDistributedSystemId(1);
ev.setVersionTag(tag);
cache.getLogger().info("destroyThread is trying to destroy the entry: " + region.getRegionEntry(key));
// expectedOldValue not supported on
region.basicDestroy(ev, false, null);
entry = (VersionedThinRegionEntryHeap) region.getRegionEntry(key);
region.dumpBackingMap();
Assert.assertTrue(entry != null, "expected to find a region entry for " + key);
Assert.assertTrue(entry.isTombstone(), "expected entry to be found and be a tombstone but it is " + entry);
Assert.assertTrue(entry.getVersionStamp().getEntryVersion() == tag.getEntryVersion(), "expected " + tag.getEntryVersion() + " but found " + entry.getVersionStamp().getEntryVersion());
RegionMap map = region.getRegionMap();
tag = entry.asVersionTag();
map.removeTombstone(entry, tag, false, true);
// now do an op that has local origin
entry = new VersionedThinRegionEntryHeapObjectKey(region, key, Token.REMOVED_PHASE1);
((AbstractRegionMap) region.getRegionMap()).putEntryIfAbsentForTest(entry);
cache.getLogger().info("entry inserted into cache: " + entry);
ev = EntryEventImpl.create(region, Operation.DESTROY, key, null, null, false, cache.getMyId());
tag = VersionTag.create((InternalDistributedMember) ev.getDistributedMember());
tag.setEntryVersion(2);
tag.setRegionVersion(12345);
tag.setVersionTimeStamp(System.currentTimeMillis());
tag.setDistributedSystemId(1);
ev.setVersionTag(tag);
cache.getLogger().info("destroyThread is trying to destroy the entry: " + region.getRegionEntry(key));
boolean caught = false;
try {
// expectedOldValue not supported on
region.basicDestroy(ev, false, null);
} catch (EntryNotFoundException e) {
caught = true;
}
Assert.assertTrue(caught, "expected an EntryNotFoundException for origin=local destroy operation");
}
use of org.apache.geode.internal.cache.versions.VersionTag in project geode by apache.
the class DistributedAckRegionCCEDUnitTest method testConcurrentOpWithGII.
/**
* test for bug #45564. a create() is received by region creator and then a later destroy() is
* received in initial image and while the version info from the destroy is recorded we keep the
* value from the create event
*/
@Test
public void testConcurrentOpWithGII() {
if (this.getClass() != DistributedAckRegionCCEDUnitTest.class) {
// not really a scope-related thing
return;
}
final String name = this.getUniqueName() + "-CC";
final String key = "mykey";
VM vm1 = Host.getHost(0).getVM(1);
VM vm2 = Host.getHost(0).getVM(2);
// create some destroyed entries so the GC service is populated
SerializableCallable create = new SerializableCallable("create region") {
public Object call() {
RegionFactory f = getCache().createRegionFactory(getRegionAttributes());
CCRegion = (LocalRegion) f.create(name);
return CCRegion.getDistributionManager().getDistributionManagerId();
}
};
// do conflicting update() and destroy() on the region. We want the update() to
// be sent with a message and the destroy() to be transferred in the initial image
// and be the value that we want to keep
InternalDistributedMember vm1ID = (InternalDistributedMember) vm1.invoke(create);
AsyncInvocation partialCreate = vm2.invokeAsync(new SerializableCallable("create region with stall") {
public Object call() throws Exception {
final GemFireCacheImpl cache = (GemFireCacheImpl) getCache();
RegionFactory f = cache.createRegionFactory(getRegionAttributes());
InitialImageOperation.VMOTION_DURING_GII = true;
// this will stall region creation at the point of asking for an initial image
VMotionObserverHolder.setInstance(new VMotionObserver() {
@Override
public void vMotionBeforeCQRegistration() {
}
@Override
public void vMotionBeforeRegisterInterest() {
}
@Override
public void vMotionDuringGII(Set recipientSet, LocalRegion region) {
InitialImageOperation.VMOTION_DURING_GII = false;
int oldLevel = LocalRegion.setThreadInitLevelRequirement(LocalRegion.BEFORE_INITIAL_IMAGE);
LocalRegion ccregion = cache.getRegionByPath("/" + name);
try {
// happen
while (!ccregion.isDestroyed() && ccregion.getRegionEntry(key) == null) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
}
} finally {
LocalRegion.setThreadInitLevelRequirement(oldLevel);
}
}
});
try {
CCRegion = (LocalRegion) f.create(name);
// at this point we should have received the update op and then the GII, which should
// overwrite
// the conflicting update op
assertFalse("expected initial image transfer to destroy entry", CCRegion.containsKey(key));
} finally {
InitialImageOperation.VMOTION_DURING_GII = false;
}
return null;
}
});
vm1.invoke(new SerializableRunnable("create conflicting events") {
public void run() {
// wait for the other to come on line
long waitEnd = System.currentTimeMillis() + 45000;
DistributionAdvisor adv = ((DistributedRegion) CCRegion).getCacheDistributionAdvisor();
while (System.currentTimeMillis() < waitEnd && adv.adviseGeneric().isEmpty()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return;
}
}
if (adv.adviseGeneric().isEmpty()) {
fail("other member never came on line");
}
// inhibit all messaging
DistributedCacheOperation.LOSS_SIMULATION_RATIO = 200.0;
try {
CCRegion.put("mykey", "initialValue");
CCRegion.destroy("mykey");
} finally {
DistributedCacheOperation.LOSS_SIMULATION_RATIO = 0.0;
}
// generate a fake version tag for the message
VersionTag tag = CCRegion.getRegionEntry(key).getVersionStamp().asVersionTag();
// create a fake member ID that will be < mine and lose a concurrency check
NetMember nm = CCRegion.getDistributionManager().getDistributionManagerId().getNetMember();
InternalDistributedMember mbr = null;
try {
mbr = new InternalDistributedMember(nm.getInetAddress().getCanonicalHostName(), nm.getPort() - 1, "fake_id", "fake_id_ustring", DistributionManager.NORMAL_DM_TYPE, null, null);
tag.setMemberID(mbr);
} catch (UnknownHostException e) {
org.apache.geode.test.dunit.Assert.fail("could not create member id", e);
}
// generate an event to distribute that contains the fake version tag
EntryEventImpl event = EntryEventImpl.create(CCRegion, Operation.UPDATE, key, false, mbr, true, false);
event.setNewValue("newValue");
event.setVersionTag(tag);
// this should update the controller's cache with the updated value but leave this cache
// alone
DistributedCacheOperation op = new UpdateOperation(event, tag.getVersionTimeStamp());
op.distribute();
event.release();
}
});
try {
partialCreate.getResult();
} catch (Throwable e) {
org.apache.geode.test.dunit.Assert.fail("async invocation in vm2 failed", e);
}
}
use of org.apache.geode.internal.cache.versions.VersionTag in project geode by apache.
the class DistributedAckRegionCCEDUnitTest method testTombstoneExpirationRace.
/**
* make sure that an operation performed on a new region entry created after a tombstone has been
* reaped is accepted by another member that has yet to reap the tombstone
*/
@Test
public void testTombstoneExpirationRace() {
VM vm0 = Host.getHost(0).getVM(0);
VM vm1 = Host.getHost(0).getVM(1);
// VM vm2 = Host.getHost(0).getVM(2);
final String name = this.getUniqueName() + "-CC";
SerializableRunnable createRegion = new SerializableRunnable("Create Region") {
public void run() {
try {
RegionFactory f = getCache().createRegionFactory(getRegionAttributes());
CCRegion = (LocalRegion) f.create(name);
CCRegion.put("cckey0", "ccvalue");
// version number will end up at 4
CCRegion.put("cckey0", "ccvalue");
} catch (CacheException ex) {
org.apache.geode.test.dunit.Assert.fail("While creating region", ex);
}
}
};
vm0.invoke(createRegion);
vm1.invoke(createRegion);
// vm2.invoke(createRegion);
vm1.invoke(new SerializableRunnable("Create local tombstone and adjust time") {
public void run() {
// make the entry for cckey0 a tombstone in this VM and set its modification time to be
// older
// than the tombstone GC interval. This means it could be in the process of being reaped by
// distributed-GC
RegionEntry entry = CCRegion.getRegionEntry("cckey0");
VersionTag tag = entry.getVersionStamp().asVersionTag();
assertTrue(tag.getEntryVersion() > 1);
tag.setVersionTimeStamp(System.currentTimeMillis() - TombstoneService.REPLICATE_TOMBSTONE_TIMEOUT - 1000);
entry.getVersionStamp().setVersionTimeStamp(tag.getVersionTimeStamp());
try {
entry.makeTombstone(CCRegion, tag);
} catch (RegionClearedException e) {
org.apache.geode.test.dunit.Assert.fail("region was mysteriously cleared during unit testing", e);
}
}
});
// now remove the entry on vm0, simulating that it initiated a GC, and perform a CREATE with a
// new version number
vm0.invoke(new SerializableRunnable("Locally destroy the entry and do a create that will be propagated with v1") {
public void run() {
CCRegion.getRegionMap().removeEntry("cckey0", CCRegion.getRegionEntry("cckey0"), true);
if (CCRegion.getRegionEntry("ckey0") != null) {
fail("expected removEntry to remove the entry from the region's map");
}
CCRegion.put("cckey0", "updateAfterReap");
}
});
vm1.invoke(new SerializableRunnable("Check that the create() was applied") {
public void run() {
RegionEntry entry = CCRegion.getRegionEntry("cckey0");
assertTrue(entry.getVersionStamp().getEntryVersion() == 1);
}
});
disconnectAllFromDS();
}
Aggregations