001: package com.tctest;
002:
003: import net.sf.ehcache.Cache;
004: import net.sf.ehcache.CacheManager;
005: import net.sf.ehcache.Ehcache;
006: import net.sf.ehcache.Element;
007: import net.sf.ehcache.Status;
008: import EDU.oswego.cs.dl.util.concurrent.BrokenBarrierException;
009: import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
010:
011: import com.tc.object.config.ConfigLockLevel;
012: import com.tc.object.config.ConfigVisitor;
013: import com.tc.object.config.DSOClientConfigHelper;
014: import com.tc.object.config.TransparencyClassSpec;
015: import com.tc.object.config.spec.CyclicBarrierSpec;
016: import com.tc.simulator.app.ApplicationConfig;
017: import com.tc.simulator.listener.ListenerProvider;
018: import com.tc.util.Assert;
019: import com.tc.util.TIMUtil;
020: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
021:
022: import java.util.Iterator;
023:
024: public class EhcacheManagerTestApp extends
025: AbstractErrorCatchingTransparentApp {
026: static final int EXPECTED_THREAD_COUNT = 2;
027:
028: private final CyclicBarrier barrier;
029:
030: private final CacheManager cacheManager;
031:
032: /**
033: * Test that Ehcache's CacheManger and Cache objects can be clustered.
034: *
035: * @param appId
036: * @param cfg
037: * @param listenerProvider
038: */
039: public EhcacheManagerTestApp(final String appId,
040: final ApplicationConfig cfg,
041: final ListenerProvider listenerProvider) {
042: super (appId, cfg, listenerProvider);
043: barrier = new CyclicBarrier(getParticipantCount());
044: cacheManager = CacheManager.getInstance();
045: }
046:
047: /**
048: * Inject Ehcache 1.3 configuration, and instrument this test class
049: *
050: * @param visitor
051: * @param config
052: */
053: public static void visitL1DSOConfig(final ConfigVisitor visitor,
054: final DSOClientConfigHelper config) {
055: config.addModule(TIMUtil.EHCACHE_1_3, TIMUtil
056: .getVersion(TIMUtil.EHCACHE_1_3));
057: config.addAutolock("* *..*.*(..)", ConfigLockLevel.WRITE);
058:
059: final String testClass = EhcacheManagerTestApp.class.getName();
060: final TransparencyClassSpec spec = config
061: .getOrCreateSpec(testClass);
062: spec.addRoot("barrier", "barrier");
063:
064: new CyclicBarrierSpec().visit(visitor, config);
065: }
066:
067: /**
068: * Test that the data written in the clustered CacheManager by one node, becomes available in the other.
069: */
070: protected void runTest() throws Throwable {
071: final int CACHE_POPULATION = 10;
072:
073: if (barrier.barrier() == 0) {
074: // create 2 caches, wait for the other node to verify
075: addCache("CACHE1", true);
076: addCache("CACHE2", false);
077: letOtherNodeProceed();
078:
079: // check that the first cache was removed
080: waitForPermissionToProceed();
081: verifyCacheRemoved("CACHE1");
082: verifyCacheCount(1);
083: letOtherNodeProceed();
084:
085: // check that the second cache was removed
086: waitForPermissionToProceed();
087: verifyCacheRemoved("CACHE2");
088: verifyCacheCount(0);
089:
090: // add a bunch of caches, wait for the other node to verify
091: addManyCaches(CACHE_POPULATION);
092: letOtherNodeProceed();
093:
094: // check that the entire bunch was removed
095: waitForPermissionToProceed();
096: verifyCacheCount(0);
097:
098: // now shutdown the CacheManager, wait for the other node to verify
099: shutdownCacheManager();
100: letOtherNodeProceed();
101: } else {
102: // check that there are 2 caches
103: waitForPermissionToProceed();
104: verifyCacheCount(2);
105: verifyCache("CACHE1");
106: verifyCache("CACHE2");
107:
108: // remove the first cache, wait for the other node to verify
109: removeCache("CACHE1");
110: letOtherNodeProceed();
111:
112: // remove the second cache, wait for the other node to verify
113: waitForPermissionToProceed();
114: removeCache("CACHE2");
115: letOtherNodeProceed();
116:
117: // check that a bunch of caches was created
118: waitForPermissionToProceed();
119: verifyManyCaches(CACHE_POPULATION);
120:
121: // now get rid of all of it, wait for the other node to verify
122: removeAllCaches();
123: letOtherNodeProceed();
124:
125: // check that the CacheManager was shutdown
126: waitForPermissionToProceed();
127: verifyCacheManagerShutdown();
128: }
129: barrier.barrier();
130: }
131:
132: /**
133: * Create many caches.
134: *
135: * @param count The number of caches to create
136: * @throws Throwable
137: */
138: private void addManyCaches(final int count) throws Throwable {
139: for (int i = 0; i < count; i++) {
140: addCache("MANYCACHE" + i, true);
141: }
142: }
143:
144: /**
145: * Remove all the caches.
146: */
147: private void removeAllCaches() {
148: cacheManager.removalAll();
149: }
150:
151: /**
152: * Verify that we have an expected number of caches created.
153: *
154: * @param expected
155: * @throws Exception
156: */
157: private void verifyCacheCount(final int expected) throws Throwable {
158: final String[] cacheNames = cacheManager.getCacheNames();
159: Assert.assertEquals(expected, cacheNames.length);
160: }
161:
162: /**
163: * Verify many caches
164: *
165: * @param count
166: * @throws Throwable
167: */
168: private void verifyManyCaches(final int count) throws Throwable {
169: verifyCacheCount(count);
170: for (int i = 0; i < count; i++) {
171: verifyCache("MANYCACHE" + i);
172: }
173: }
174:
175: /**
176: * Add a cache into the CacheManager.
177: *
178: * @param name The name of the cache to add
179: * @param mustDelegate create Manually create the cache or let the manager handle the details
180: * @throws Throwable
181: */
182: private void addCache(final String name, boolean mustDelegate)
183: throws Throwable {
184: if (mustDelegate) {
185: cacheManager.addCache(name);
186: } else {
187: Ehcache cache = new Cache(name, 2, false, true, 0, 0); // setting both maxIdleTime and maxTTL to 0, so the cache
188: // entries
189: // never expire.
190: cacheManager.addCache(cache);
191: }
192:
193: Ehcache cache = cacheManager.getEhcache(name);
194: cache.put(new Element(name + "key1", "value1"));
195: cache.put(new Element(name + "key2", "value1"));
196: }
197:
198: /**
199: * Verify that the named cache exists and that it's contents can be retrieved.
200: *
201: * @param name The name of the cache to retrieve
202: * @throws Exception
203: */
204: private void verifyCache(final String name) throws Exception {
205: boolean cacheExists = cacheManager.cacheExists(name);
206: Assert.assertEquals(true, cacheExists);
207:
208: Ehcache cache = cacheManager.getEhcache(name);
209: Assert.assertNotNull(cache);
210: Assert.assertEquals(name, cache.getName());
211: Assert.assertEquals(Status.STATUS_ALIVE, cache.getStatus());
212:
213: int sizeFromGetSize = cache.getSize();
214: int sizeFromKeys = cache.getKeys().size();
215: Assert.assertEquals(sizeFromGetSize, sizeFromKeys);
216: Assert.assertEquals(2, cache.getSize());
217:
218: Assert.assertTrue(cache.isKeyInCache(name + "key1"));
219: Assert.assertTrue(cache.isKeyInCache(name + "key2"));
220: }
221:
222: /**
223: * Remove the named cache
224: *
225: * @param name
226: */
227: private void removeCache(final String name) {
228: Ehcache cache = cacheManager.getEhcache(name);
229: for (Iterator i = cache.getKeys().iterator(); i.hasNext();) {
230: String key = (String) i.next();
231: cache.remove(key);
232: Assert.assertFalse(cache.isKeyInCache(key));
233: }
234: cacheManager.removeCache(name);
235: }
236:
237: /**
238: * Verify that the named cache no longer exists.
239: *
240: * @param name
241: * @throws Exception
242: */
243: private void verifyCacheRemoved(final String name) throws Exception {
244: boolean cacheExists = cacheManager.cacheExists(name);
245: Assert.assertEquals(false, cacheExists);
246:
247: Ehcache cache = cacheManager.getEhcache(name);
248: Assert.assertNull(cache);
249: }
250:
251: /**
252: * Shuts down the clustered cache manager.
253: */
254: private void shutdownCacheManager() {
255: cacheManager.shutdown();
256: }
257:
258: /**
259: * Verify that the clustered cache manager has shut down.
260: */
261: private void verifyCacheManagerShutdown() {
262: Assert.assertEquals(Status.STATUS_SHUTDOWN, cacheManager
263: .getStatus());
264: }
265:
266: // This is lame but it makes runTest() slightly more readable
267: private void letOtherNodeProceed() throws InterruptedException,
268: BrokenBarrierException {
269: barrier.barrier();
270: }
271:
272: // This is lame but it makes runTest() slightly more readable
273: private void waitForPermissionToProceed()
274: throws InterruptedException, BrokenBarrierException {
275: barrier.barrier();
276: }
277: }
|