blob: 6b1069aeacd97a1b98b5b42fedee3331e103bbd2 [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2002-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
package com.gemstone.gemfire.cache;
import static org.junit.Assert.*;
import com.gemstone.gemfire.cache.query.*;
import com.gemstone.gemfire.cache.util.*;
import com.gemstone.gemfire.distributed.*;
import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
import com.gemstone.gemfire.internal.cache.CachePerfStats;
import com.gemstone.gemfire.internal.cache.LocalRegion;
import com.gemstone.gemfire.internal.cache.tier.sockets.ClientProxyMembershipID;
import com.gemstone.gemfire.internal.util.StopWatch;
import com.gemstone.gemfire.test.junit.categories.IntegrationTest;
import java.util.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;
/**
* Unit test for basic DataPolicy.EMPTY feature.
* NOTE: these tests using a loner DistributedSystem and local scope regions
* @author Darrel Schneider
* @since 5.0
*/
@Category(IntegrationTest.class)
public class ProxyJUnitTest {
private DistributedSystem ds;
private Cache c;
@Before
public void setUp() throws Exception {
Properties p = new Properties();
p.setProperty("mcast-port", "0");
p.setProperty("locators", "");
this.ds = DistributedSystem.connect(p);
this.c = CacheFactory.create(this.ds);
}
@After
public void tearDown() throws Exception {
System.clearProperty(LocalRegion.EXPIRY_MS_PROPERTY);
if (this.c != null) {
this.c.close();
this.c = null;
}
if (this.ds != null) {
this.ds.disconnect();
this.ds = null;
}
}
private CachePerfStats getStats() {
return ((GemFireCacheImpl)this.c).getCachePerfStats();
}
/**
* last event a cache listener saw
*/
private CacheEvent clLastEvent;
/**
* number of cache listener invocations
*/
private int clInvokeCount;
/**
* true if cache listener close called
*/
private boolean clClosed;
/**
* last event a cache writer saw
*/
private CacheEvent cwLastEvent;
/**
* number of cache writer invocations
*/
private int cwInvokeCount;
/**
* true if cache writer close called
*/
private boolean cwClosed;
/**
* last getEvents() a transaction listener saw
*/
private List tlLastEvents;
/**
* number of transaction listener invocations
*/
private int tlInvokeCount;
/**
* true if transaction listener close called
*/
private boolean tlClosed;
/**
* Clears the all the callback state this test has received.
*/
private void clearCallbackState() {
this.clLastEvent = null;
this.clInvokeCount = 0;
this.clClosed = false;
this.cwLastEvent = null;
this.cwInvokeCount = 0;
this.cwClosed = false;
this.tlLastEvents = null;
this.tlInvokeCount = 0;
this.tlClosed = false;
}
/**
* Used to check to see if CacheEvent was what was expected
*/
private abstract class ExpectedCacheEvent implements CacheEvent {
public Region r;
public Operation op;
public Object cbArg;
public boolean queued;
public void check(CacheEvent other) {
if (getRegion() != other.getRegion()) {
fail("wrong region. Expected " + getRegion()
+ " but found " + other.getRegion());
}
assertEquals(getOperation(), other.getOperation());
assertEquals(getCallbackArgument(), other.getCallbackArgument());
assertEquals(isOriginRemote(), other.isOriginRemote());
assertEquals(getDistributedMember(), other.getDistributedMember());
assertEquals(isExpiration(), other.isExpiration());
assertEquals(isDistributed(), other.isDistributed());
}
public Region getRegion() {
return this.r;
}
public Operation getOperation() {
return this.op;
}
public Object getCallbackArgument() {
return this.cbArg;
}
public boolean isCallbackArgumentAvailable() {return true;}
public boolean isOriginRemote() {
return false;
}
public DistributedMember getDistributedMember() {
return c.getDistributedSystem().getDistributedMember();
}
public boolean isExpiration() {
return this.op.isExpiration();
}
public boolean isDistributed() {
return this.op.isDistributed();
}
}
/**
* Used to check to see if EntryEvent was what was expected
*/
private class ExpectedEntryEvent extends ExpectedCacheEvent implements EntryEvent {
public void check(EntryEvent other) {
super.check(other);
assertEquals(getKey(), other.getKey());
assertEquals(getOldValue(), other.getOldValue());
assertEquals(getNewValue(), other.getNewValue());
assertEquals(isLocalLoad(), other.isLocalLoad());
assertEquals(isNetLoad(), other.isNetLoad());
assertEquals(isLoad(), other.isLoad());
assertEquals(isNetSearch(), other.isNetSearch());
assertEquals(getTransactionId(), other.getTransactionId());
}
public Object key;
public Object getKey() {
return this.key;
}
public Object getOldValue() {
return null;
}
public boolean isOldValueAvailable() {return true;}
public Object newValue;
public Object getNewValue() {
return this.newValue;
}
public boolean isLocalLoad() {
return getOperation().isLocalLoad();
}
public boolean isNetLoad() {
return getOperation().isNetLoad();
}
public boolean isLoad() {
return getOperation().isLoad();
}
public boolean isNetSearch() {
return getOperation().isNetSearch();
}
public TransactionId txId;
public TransactionId getTransactionId() {
return this.txId;
}
public boolean isBridgeEvent() {
return hasClientOrigin();
}
public boolean hasClientOrigin() {
return false;
}
public ClientProxyMembershipID getContext() {
// TODO Auto-generated method stub
return null;
}
public SerializedCacheValue getSerializedOldValue() {
return null;
}
public SerializedCacheValue getSerializedNewValue() {
return null;
}
}
/**
* Used to check to see if EntryEvent was what was expected
*/
private class ExpectedRegionEvent extends ExpectedCacheEvent implements RegionEvent {
public void check(RegionEvent other) {
super.check(other);
assertEquals(isReinitializing(), other.isReinitializing());
}
public boolean isReinitializing() {
return false;
}
}
private void checkCWClosed() {
assertEquals(true, this.cwClosed);
}
private void checkCLClosed() {
assertEquals(true, this.clClosed);
}
private void checkTLClosed() {
assertEquals(true, this.tlClosed);
}
private void checkNoCW() {
assertEquals(0, this.cwInvokeCount);
}
private void checkNoCL() {
assertEquals(0, this.clInvokeCount);
}
private void checkNoTL() {
assertEquals(0, this.tlInvokeCount);
}
private void checkTL(ExpectedCacheEvent expected) {
assertEquals(1, this.tlInvokeCount);
assertEquals(1, this.tlLastEvents.size());
{
Object old_CA = expected.cbArg;
//expected.cbArg = null;
try {
expected.check((CacheEvent)this.tlLastEvents.get(0));
} finally {
expected.cbArg = old_CA;
}
}
checkNoCW();
//checkNoCL();
clearCallbackState();
}
private void checkCW(ExpectedCacheEvent expected) {
assertEquals(1, this.cwInvokeCount);
expected.check(this.cwLastEvent);
}
private void checkCL(ExpectedCacheEvent expected){
checkCL(expected, true);
}
private void checkCL(ExpectedCacheEvent expected, boolean clearCallbackState) {
assertEquals(1, this.clInvokeCount);
expected.check(this.clLastEvent);
if(clearCallbackState){
clearCallbackState();
}
}
private void setCallbacks(AttributesFactory af) {
CacheListener cl1 = new CacheListener() {
public void afterUpdate(EntryEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterCreate(EntryEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterInvalidate(EntryEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterDestroy(EntryEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterRegionInvalidate(RegionEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterRegionDestroy(RegionEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterRegionClear(RegionEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterRegionCreate(RegionEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void afterRegionLive(RegionEvent e) {
clLastEvent = e;
clInvokeCount++;
}
public void close() {
clClosed = true;
}
};
CacheWriter cw = new CacheWriter() {
public void beforeUpdate(EntryEvent e) throws CacheWriterException {
cwLastEvent = e;
cwInvokeCount++;
}
public void beforeCreate(EntryEvent e) throws CacheWriterException {
cwLastEvent = e;
cwInvokeCount++;
}
public void beforeDestroy(EntryEvent e) throws CacheWriterException {
cwLastEvent = e;
cwInvokeCount++;
}
public void beforeRegionDestroy(RegionEvent e) throws CacheWriterException {
cwLastEvent = e;
cwInvokeCount++;
}
public void beforeRegionClear(RegionEvent e) throws CacheWriterException {
cwLastEvent = e;
cwInvokeCount++;
}
public void close() {
cwClosed = true;
}
};
af.addCacheListener(cl1);
af.setCacheWriter(cw);
{
TransactionListener tl = new TransactionListenerAdapter() {
public void afterCommit(TransactionEvent e) {
tlLastEvents = e.getEvents();
tlInvokeCount++;
}
public void close() {
tlClosed = true;
};
};
CacheTransactionManager ctm = this.c.getCacheTransactionManager();
ctm.addListener(tl);
}
}
/**
* Confirms region (non-map) methods
*/
@Test
public void testRegionMethods() throws Exception {
Object cbArg = new Object();
AttributesFactory af = new AttributesFactory();
af.setDataPolicy(DataPolicy.EMPTY);
setCallbacks(af);
clearCallbackState();
ExpectedRegionEvent expre = new ExpectedRegionEvent();
assertEquals(0, getStats().getRegions());
Region r = this.c.createRegion("r", af.create());
assertEquals(1, getStats().getRegions());
expre.r = r;
expre.op = Operation.REGION_CREATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
assertEquals("r", r.getName());
assertEquals("/r", r.getFullPath());
assertEquals(null, r.getParentRegion());
assertEquals(DataPolicy.EMPTY, r.getAttributes().getDataPolicy());
r.getAttributesMutator();
try {
r.getStatistics();
fail ("expected StatisticsDisabledException");
} catch (StatisticsDisabledException expected) {
// because they were not enabled in the region attributes
}
r.invalidateRegion();
expre.op = Operation.REGION_INVALIDATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
r.invalidateRegion(cbArg);
expre.cbArg = cbArg;
checkNoCW();
checkCL(expre);
r.localInvalidateRegion();
expre.op = Operation.REGION_LOCAL_INVALIDATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
r.localInvalidateRegion(cbArg);
expre.cbArg = cbArg;
checkNoCW();
checkCL(expre);
r.destroyRegion();
assertEquals(true, r.isDestroyed());
assertEquals(0, getStats().getRegions());
expre.op = Operation.REGION_DESTROY;
expre.cbArg = null;
checkCW(expre);
checkCL(expre);
r = this.c.createRegion("r", af.create());
expre.r = r;
expre.op = Operation.REGION_CREATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
r.destroyRegion(cbArg);
assertEquals(0, getStats().getRegions());
assertEquals(true, r.isDestroyed());
expre.op = Operation.REGION_DESTROY;
expre.cbArg = cbArg;
checkCW(expre);
checkCL(expre);
r = this.c.createRegion("r", af.create());
expre.r = r;
expre.op = Operation.REGION_CREATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
r.localDestroyRegion();
assertEquals(0, getStats().getRegions());
assertEquals(true, r.isDestroyed());
expre.op = Operation.REGION_LOCAL_DESTROY;
expre.cbArg = null;
checkNoCW();
checkCWClosed();
checkCLClosed();
checkCL(expre);
r = this.c.createRegion("r", af.create());
expre.r = r;
expre.op = Operation.REGION_CREATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
r.localDestroyRegion(cbArg);
assertEquals(0, getStats().getRegions());
assertEquals(true, r.isDestroyed());
expre.op = Operation.REGION_LOCAL_DESTROY;
expre.cbArg = cbArg;
checkNoCW();
checkCWClosed();
checkCLClosed();
checkCL(expre);
r = this.c.createRegion("r", af.create());
expre.r = r;
expre.op = Operation.REGION_CREATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
r.close();
assertEquals(0, getStats().getRegions());
assertEquals(true, r.isDestroyed());
expre.op = Operation.REGION_CLOSE;
expre.cbArg = null;
checkNoCW();
checkCWClosed();
checkCLClosed();
checkCL(expre);
r = this.c.createRegion("r", af.create());
assertEquals(1, getStats().getRegions());
expre.r = r;
expre.op = Operation.REGION_CREATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
try {
r.saveSnapshot(System.out);
fail("expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
try {
r.loadSnapshot(System.in);
fail("expected UnsupportedOperationException");
} catch (UnsupportedOperationException expected) {
}
{
Region sr = r.createSubregion("sr", af.create());
assertEquals(2, getStats().getRegions());
expre.r = sr;
expre.op = Operation.REGION_CREATE;
expre.cbArg = null;
checkNoCW();
checkCL(expre);
assertEquals("sr", sr.getName());
assertEquals("/r/sr", sr.getFullPath());
assertEquals(r, sr.getParentRegion());
assertEquals(sr, r.getSubregion("sr"));
assertEquals(Collections.singleton(sr), r.subregions(false));
sr.close();
assertEquals(1, getStats().getRegions());
expre.op = Operation.REGION_CLOSE;
expre.cbArg = null;
checkNoCW();
checkCWClosed();
checkCLClosed();
checkCL(expre);
assertEquals(true, sr.isDestroyed());
assertEquals(null, r.getSubregion("sr"));
assertEquals(Collections.EMPTY_SET, r.subregions(false));
}
ExpectedEntryEvent expee = new ExpectedEntryEvent();
expee.r = r;
expee.key = "key";
int creates = getStats().getCreates();
// int puts = getStats().getPuts();
// int updates = getStats().getUpdates();
int destroys = getStats().getDestroys();
int invalidates = getStats().getInvalidates();
int gets = getStats().getGets();
int misses = getStats().getMisses();
r.put("key", "value", cbArg);
expee.op = Operation.CREATE;
creates++;
assertEquals(creates, getStats().getCreates());
expee.cbArg = cbArg;
expee.newValue = "value";
checkCW(expee);
checkCL(expee);
// note on a non-proxy region create after put fails with EntryExistsException
r.create("key", "value", cbArg);
creates++;
assertEquals(creates, getStats().getCreates());
expee.op = Operation.CREATE;
expee.cbArg = cbArg;
expee.newValue = "value";
checkCW(expee);
checkCL(expee);
assertEquals(null, r.getEntry("key"));
assertEquals(null, r.get("key", cbArg));
gets++;
assertEquals(gets, getStats().getGets());
misses++;
assertEquals(misses, getStats().getMisses());
checkNoCW();
checkNoCL();
r.invalidate("key");
invalidates++;
assertEquals(invalidates, getStats().getInvalidates());
expee.op = Operation.INVALIDATE;
expee.cbArg = null;
expee.newValue = null;
checkNoCW();
checkCL(expee);
r.invalidate("key", cbArg);
invalidates++;
assertEquals(invalidates, getStats().getInvalidates());
expee.op = Operation.INVALIDATE;
expee.cbArg = cbArg;
expee.newValue = null;
checkNoCW();
checkCL(expee);
try {
r.localInvalidate("key");
fail("expected EntryNotFoundException");
} catch (EntryNotFoundException expected) {
}
try {
r.localInvalidate("key", cbArg);
fail("expected EntryNotFoundException");
} catch (EntryNotFoundException expected) {
}
assertEquals(invalidates, getStats().getInvalidates());
checkNoCW();
checkNoCL();
r.destroy("key");
destroys++;
assertEquals(destroys, getStats().getDestroys());
expee.op = Operation.DESTROY;
expee.cbArg = null;
expee.newValue = null;
checkCW(expee);
checkCL(expee);
r.destroy("key", cbArg);
destroys++;
assertEquals(destroys, getStats().getDestroys());
expee.op = Operation.DESTROY;
expee.cbArg = cbArg;
expee.newValue = null;
checkCW(expee);
checkCL(expee);
try {
r.localDestroy("key");
fail("expected EntryNotFoundException");
} catch (EntryNotFoundException expected) {
}
try {
r.localDestroy("key", cbArg);
fail("expected EntryNotFoundException");
} catch (EntryNotFoundException expected) {
}
assertEquals(destroys, getStats().getDestroys());
checkNoCW();
checkNoCL();
assertEquals(Collections.EMPTY_SET, r.keys());
assertEquals(Collections.EMPTY_SET, r.entries(true));
assertEquals(Collections.EMPTY_SET, r.entrySet(true));
assertEquals(this.c, r.getCache());
r.setUserAttribute(cbArg);
assertEquals(cbArg, r.getUserAttribute());
checkNoCW();
checkNoCL();
r.put("key", "value", cbArg);
creates++;
assertEquals(creates, getStats().getCreates());
expee.op = Operation.CREATE;
expee.cbArg = cbArg;
expee.newValue = "value";
checkCW(expee);
checkCL(expee);
assertEquals(false, r.containsValueForKey("key"));
assertEquals(false, r.existsValue("this = 'value'"));
{
SelectResults sr = r.query("this = 'value'");
assertEquals(Collections.EMPTY_SET, sr.asSet());
}
assertEquals(null, r.selectValue("this = 'value'"));
try {
r.getRegionDistributedLock();
fail("expected IllegalStateException");
} catch (IllegalStateException expected) {
// because we are not global
}
try {
r.getDistributedLock("key");
fail("expected IllegalStateException");
} catch (IllegalStateException expected) {
// because we are not global
}
try {
r.becomeLockGrantor();
fail("expected IllegalStateException");
} catch (IllegalStateException expected) {
// because we are not global
}
try {
r.writeToDisk();
fail("expected IllegalStateException");
} catch (IllegalStateException expected) {
// because we are not configured for disk
}
checkNoCW();
checkNoCL();
// check to see if a local loader works
{
CacheLoader cl = new CacheLoader() {
public Object load(LoaderHelper helper)
throws CacheLoaderException
{
return "loadedValue";
}
public void close() {
}
};
r.getAttributesMutator().setCacheLoader(cl);
r.get("key", cbArg);
gets++;
assertEquals(gets, getStats().getGets());
misses++;
assertEquals(misses, getStats().getMisses());
expee.op = Operation.LOCAL_LOAD_CREATE;
expee.newValue = "loadedValue";
checkCW(expee);
checkCL(expee);
r.getAttributesMutator().setCacheLoader(null);
}
}
/**
* Confirms map methods
*/
@Test
public void testMapMethods() throws Exception {
AttributesFactory af = new AttributesFactory();
af.setDataPolicy(DataPolicy.EMPTY);
setCallbacks(af);
clearCallbackState();
ExpectedRegionEvent expre = new ExpectedRegionEvent();
Region r = this.c.createRegion("r", af.create());
expre.r = r;
expre.cbArg = null;
expre.op = Operation.REGION_CREATE;
checkNoCW();
checkCL(expre);
int creates = getStats().getCreates();
// int puts = getStats().getPuts();
// int updates = getStats().getUpdates();
int destroys = getStats().getDestroys();
// int invalidates = getStats().getInvalidates();
int gets = getStats().getGets();
int misses = getStats().getMisses();
ExpectedEntryEvent expee = new ExpectedEntryEvent();
expee.r = r;
expee.key = "key";
expee.cbArg = null;
assertEquals(null, r.put("key", "value"));
creates++;
assertEquals(creates, getStats().getCreates());
expee.op = Operation.CREATE;
expee.newValue = "value";
checkCW(expee);
checkCL(expee);
{
HashMap m = new HashMap();
m.put("k1", "v1");
m.put("k2", "v2");
r.putAll(m);
assertEquals(0, r.size());
// @todo darrel: check events
assertEquals(2, this.cwInvokeCount);
assertEquals(2, this.clInvokeCount);
clearCallbackState();
creates += 2;
assertEquals(creates, getStats().getCreates());
}
assertEquals(false, r.containsKey("key"));
assertEquals(false, r.containsValue("value"));
assertEquals(Collections.EMPTY_SET, r.entrySet());
assertEquals(true, r.isEmpty());
assertEquals(Collections.EMPTY_SET, r.keySet());
assertEquals(0, r.size());
assertEquals(Collections.EMPTY_LIST, new ArrayList(r.values()));
checkNoCW();
checkNoCL();
assertEquals(null, r.get("key"));
gets++;
assertEquals(gets, getStats().getGets());
misses++;
assertEquals(misses, getStats().getMisses());
checkNoCW();
checkNoCL();
assertEquals(null, r.remove("key"));
destroys++;
assertEquals(destroys, getStats().getDestroys());
expee.op = Operation.DESTROY;
expee.key = "key";
expee.newValue = null;
checkCW(expee);
checkCL(expee);
r.localClear();
expre.op = Operation.REGION_LOCAL_CLEAR;
checkNoCW();
checkCL(expre);
r.clear();
expre.op = Operation.REGION_CLEAR;
checkCW(expre);
checkCL(expre);
}
/**
* Check region ops on a proxy region done from a tx.
*/
@Test
public void testAllMethodsWithTX() throws Exception {
Object cbArg = new Object();
AttributesFactory af = new AttributesFactory();
af.setDataPolicy(DataPolicy.EMPTY);
setCallbacks(af);
clearCallbackState();
CacheTransactionManager ctm = this.c.getCacheTransactionManager();
ExpectedRegionEvent expre = new ExpectedRegionEvent();
Region r = this.c.createRegion("r", af.create());
expre.r = r;
expre.cbArg = null;
expre.op = Operation.REGION_CREATE;
checkNoCW();
checkNoTL();
checkCL(expre);
int creates = getStats().getCreates();
// int puts = getStats().getPuts();
// int updates = getStats().getUpdates();
int destroys = getStats().getDestroys();
int invalidates = getStats().getInvalidates();
// int gets = getStats().getGets();
// int misses = getStats().getMisses();
ExpectedEntryEvent expee = new ExpectedEntryEvent();
expee.r = r;
expee.key = "key";
ctm.begin();
try {
r.localInvalidate("key");
fail("expected EntryNotFoundException");
} catch (EntryNotFoundException expected) {
}
try {
r.localDestroy("key");
fail("expected EntryNotFoundException");
} catch (EntryNotFoundException expected) {
}
ctm.rollback();
ctm.begin();
expee.txId = ctm.getTransactionId();
r.put("key", "value", cbArg);
expee.op = Operation.CREATE;
expee.cbArg = cbArg;
expee.newValue = "value";
checkCW(expee);
checkNoTL();
checkNoCL();
clearCallbackState();
ctm.commit();
checkCL(expee, false/*ClearCallbacks*/);
checkTL(expee);
creates++;
assertEquals(creates, getStats().getCreates());
ctm.begin();
expee.txId = ctm.getTransactionId();
r.create("key", "value", cbArg);
expee.op = Operation.CREATE;
expee.cbArg = cbArg;
expee.newValue = "value";
checkCW(expee);
checkNoTL();
checkNoCL();
clearCallbackState();
ctm.commit();
checkCL(expee, false/*ClearCallbacks*/);
checkTL(expee);
creates++;
assertEquals(creates, getStats().getCreates());
ctm.begin();
expee.txId = ctm.getTransactionId();
r.invalidate("key", cbArg);
expee.op = Operation.INVALIDATE;
expee.cbArg = cbArg;
expee.newValue = null;
checkNoCW();
checkNoTL();
checkNoCL();
clearCallbackState();
ctm.commit();
checkCL(expee, false/*ClearCallbacks*/);
invalidates++;
assertEquals(invalidates, getStats().getInvalidates());
checkTL(expee);
ctm.begin();
expee.txId = ctm.getTransactionId();
r.destroy("key", cbArg);
expee.op = Operation.DESTROY;
expee.cbArg = cbArg;
expee.newValue = null;
checkCW(expee);
checkNoTL();
checkNoCL();
clearCallbackState();
ctm.commit();
checkCL(expee, false/*ClearCallbacks*/);
destroys++;
assertEquals(destroys, getStats().getDestroys());
checkTL(expee);
ctm.begin();
expee.txId = ctm.getTransactionId();
r.create("key", "value", cbArg);
r.destroy("key", cbArg);
clearCallbackState();
ctm.commit();
destroys++;
assertEquals(destroys, getStats().getDestroys());
expee.op = Operation.DESTROY;
checkTL(expee);
// the following confirms that bug 37903 is fixed
ctm.begin();
expee.txId = ctm.getTransactionId();
r.invalidate("key");
r.localInvalidate("key");
r.localDestroy("key", cbArg);
// note that the following would fail on a non-proxy with EntryNotFound
// so it should also fail on a proxy
try {
// note if bug 37903 exists then the next line will throw an AssertionError
r.destroy("key", cbArg);
fail("expected EntryNotFoundException");
} catch (EntryNotFoundException expected) {
}
clearCallbackState();
ctm.commit();
destroys++;
assertEquals(destroys, getStats().getDestroys());
expee.op = Operation.LOCAL_DESTROY;
checkTL(expee);
}
/**
* Make sure a proxy region can be lru and that it makes no difference
* since proxies are always empty
*/
@Test
public void testLRU() throws Exception {
AttributesFactory af = new AttributesFactory();
af.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(1));
CacheListener cl1 = new CacheListenerAdapter() {
public void afterDestroy(EntryEvent e) {
clInvokeCount++;
}
};
af.addCacheListener(cl1);
// // first make sure this test is valid by confirming we see evictions
// // on a non-proxy lru
// {
// af.setDataPolicy(DataPolicy.NORMAL);
// Region r = this.c.createRegion("rLRU", af.create());
// clearCallbackState();
// assertTrue(clInvokeCount == 0);
// for (int i=0; i < 10; i++) {
// r.put("key" + i, "value" + i);
// }
// assertTrue(clInvokeCount > 0);
// }
// now try it with a proxy region which should never to do an eviction.
{
af.setDataPolicy(DataPolicy.EMPTY);
try {
af.create();
fail("expected IllegalStateException");
} catch (IllegalStateException expected) {
}
// Region r = this.c.createRegion("rEMPTY", af.create());
// clearCallbackState();
// assertTrue(clInvokeCount == 0);
// for (int i=0; i < 10; i++) {
// r.put("key" + i, "value" + i);
// }
// assertTrue(clInvokeCount == 0);
}
}
/**
* Make sure a proxy region expiration behaves as expected
*/
@Test
public void testExpiration() throws Exception {
System.setProperty(LocalRegion.EXPIRY_MS_PROPERTY, "true");
try {
// now make sure they don't on proxy
{
AttributesFactory af = new AttributesFactory();
af.setStatisticsEnabled(true);
af.setEntryIdleTimeout(new ExpirationAttributes(1, ExpirationAction.LOCAL_INVALIDATE));
af.setEntryTimeToLive(new ExpirationAttributes(2, ExpirationAction.LOCAL_DESTROY));
af.setDataPolicy(DataPolicy.EMPTY);
try {
af.create();
fail("expected IllegalStateException");
} catch (IllegalStateException expected) {
}
}
// make sure regionIdleTimeout works on proxy
{
CacheListener cl1 = new CacheListenerAdapter() {
public void afterRegionDestroy(RegionEvent e) {
clInvokeCount++;
}
public void afterRegionInvalidate(RegionEvent e) {
clInvokeCount++;
}
};
AttributesFactory af = new AttributesFactory();
af.setStatisticsEnabled(true);
final int EXPIRE_MS = 500;
af.setRegionIdleTimeout(new ExpirationAttributes(EXPIRE_MS, ExpirationAction.LOCAL_DESTROY));
af.addCacheListener(cl1);
af.setDataPolicy(DataPolicy.EMPTY);
clearCallbackState();
Region r = this.c.createRegion("rEMPTY", af.create());
assertTrue(clInvokeCount == 0);
r.put("key", "value");
long endTime = System.currentTimeMillis() + (EXPIRE_MS * 2);
do {
r.get("key");
} while (System.currentTimeMillis() < endTime);
assertEquals(0, this.clInvokeCount);
Thread.sleep(EXPIRE_MS * 2);
boolean done = false;
try {
for (StopWatch time = new StopWatch(true); !done && time.elapsedTimeMillis() < 1000; done = (ProxyJUnitTest.this.clInvokeCount == 1)) {
Thread.sleep(200);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
assertTrue("waiting for invocation" , done);
}
// make sure regionTimeToLive works on proxy
{
CacheListener cl1 = new CacheListenerAdapter() {
public void afterRegionDestroy(RegionEvent e) {
clInvokeCount++;
}
public void afterRegionInvalidate(RegionEvent e) {
clInvokeCount++;
}
};
AttributesFactory af = new AttributesFactory();
af.setStatisticsEnabled(true);
final int EXPIRE_MS = 500;
af.setRegionTimeToLive(new ExpirationAttributes(EXPIRE_MS, ExpirationAction.LOCAL_DESTROY));
af.addCacheListener(cl1);
af.setDataPolicy(DataPolicy.EMPTY);
clearCallbackState();
Region r = this.c.createRegion("rEMPTY", af.create());
assertTrue(clInvokeCount == 0);
r.put("key", "value");
long endTime = System.currentTimeMillis() + (EXPIRE_MS * 2);
do {
r.put("key", "value");
} while (System.currentTimeMillis() < endTime);
assertEquals(0, this.clInvokeCount);
Thread.sleep(EXPIRE_MS * 2);
boolean done = false;
try {
for (StopWatch time = new StopWatch(true); !done && time.elapsedTimeMillis() < 1000; done = (ProxyJUnitTest.this.clInvokeCount == 1)) {
Thread.sleep(200);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
assertTrue("waiting for invocation" , done);
}
} finally {
System.clearProperty(LocalRegion.EXPIRY_MS_PROPERTY);
assertEquals(null, System.getProperty(LocalRegion.EXPIRY_MS_PROPERTY));
}
}
/**
* Make sure a disk region and proxy play nice.
*/
@Test
public void testDiskProxy() throws Exception {
AttributesFactory af = new AttributesFactory();
af.setDataPolicy(DataPolicy.EMPTY);
af.setEvictionAttributes(EvictionAttributes.createLRUEntryAttributes(1, EvictionAction.OVERFLOW_TO_DISK));
try {
af.create();
fail ("expected IllegalStateException");
} catch (IllegalStateException expected) {
}
}
/**
* Make sure a CachStatistics work on proxy
*/
@Test
public void testCacheStatisticsOnProxy() throws Exception {
AttributesFactory af = new AttributesFactory();
af.setDataPolicy(DataPolicy.EMPTY);
af.setStatisticsEnabled(true);
Region r = this.c.createRegion("rEMPTY", af.create());
CacheStatistics stats = r.getStatistics();
long lastModifiedTime = stats.getLastModifiedTime();
long lastAccessedTime = stats.getLastAccessedTime();
waitForSystemTimeChange();
r.put("k", "v");
assertTrue(lastModifiedTime != stats.getLastModifiedTime());
assertTrue(lastAccessedTime != stats.getLastAccessedTime());
lastModifiedTime = stats.getLastModifiedTime();
lastAccessedTime = stats.getLastAccessedTime();
waitForSystemTimeChange();
r.create("k", "v");
assertTrue(lastModifiedTime != stats.getLastModifiedTime());
assertTrue(lastAccessedTime != stats.getLastAccessedTime());
lastModifiedTime = stats.getLastModifiedTime();
lastAccessedTime = stats.getLastAccessedTime();
long missCount = stats.getMissCount();
long hitCount = stats.getHitCount();
waitForSystemTimeChange();
r.get("k");
assertEquals(lastModifiedTime, stats.getLastModifiedTime());
assertTrue(lastAccessedTime != stats.getLastAccessedTime());
assertEquals(hitCount, stats.getHitCount());
assertEquals(missCount+1, stats.getMissCount());
}
/**
* Waits (hot) until the system time changes.
*/
private void waitForSystemTimeChange() {
long start = System.currentTimeMillis();
while (System.currentTimeMillis() == start);
}
}