JBoss Cache SVN: r4489 - in pojo/trunk/src: main/java/org/jboss/cache/pojo/impl and 1 other directories.
by jbosscache-commits@lists.jboss.org
Author: jason.greene(a)jboss.com
Date: 2007-09-20 00:28:36 -0400 (Thu, 20 Sep 2007)
New Revision: 4489
Modified:
pojo/trunk/src/main/java/org/jboss/cache/pojo/PojoCache.java
pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
pojo/trunk/src/test/java/org/jboss/cache/pojo/NewLocalTest.java
Log:
PCACHE-2 - Add FQN based versions to API
Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/PojoCache.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/PojoCache.java 2007-09-19 17:05:59 UTC (rev 4488)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/PojoCache.java 2007-09-20 04:28:36 UTC (rev 4489)
@@ -11,6 +11,7 @@
import java.util.regex.Pattern;
import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
import org.jboss.cache.pojo.notification.annotation.PojoCacheListener;
/**
@@ -56,6 +57,35 @@
Object attach(String id, Object pojo) throws PojoCacheException;
/**
+ * <p>Attach a POJO into PojoCache. It will also recursively put any
+ * sub-POJO into the cache system. A POJO can be the following and have the
+ * consqeuences when attached:</p> <p/> <li>it is Replicable, that is, it
+ * has been annotated with {@link @org.jboss.cache.pojo.annotation.Replicable} annotation (or via XML),
+ * and has
+ * been "instrumented" either compile- or load-time. The POJO will be mapped
+ * recursively to the system and fine-grained replication will be
+ * performed.</li> <li>It is Serializable. The POJO will still be stored in
+ * the cache system. However, it is treated as an "opaque" object per se.
+ * That is, the POJO will neither be intercepted
+ * (for fine-grained operation) or object relantionship will be
+ * maintained.</li>
+ * <li>Neither of above. In this case, a user can specify whether it wants
+ * this POJO to be stored (e.g., replicated or persistent). If not, a
+ * PojoCacheException will be thrown.</li>
+ *
+ * @param id An id String to identify the object in the cache. To promote
+ * concurrency, we recommend the use of hierarchical String separating by a
+ * designated separator. Default is "/" but it can be set differently via a
+ * System property, jbosscache.separator in the future release. E.g., "ben",
+ * or "student/joe", etc.
+ * @param pojo object to be inerted into the cache. If null, it will nullify
+ * the fqn node.
+ * @return Existing POJO or null if there is none.
+ * @throws PojoCacheException Throws if there is an error related to the cache operation.
+ */
+ Object attach(Fqn<?> id, Object pojo) throws PojoCacheException;
+
+ /**
* Remove POJO object from the cache.
*
* @param id Is string that associates with this node.
@@ -65,6 +95,15 @@
Object detach(String id) throws PojoCacheException;
/**
+ * Remove POJO object from the cache.
+ *
+ * @param id location of the object to remove
+ * @return Original value object from this node.
+ * @throws PojoCacheException Throws if there is an error related to the cache operation.
+ */
+ Object detach(Fqn<?> id) throws PojoCacheException;
+
+ /**
* Return the POJO id that is associated with PojoCache. Note that if a POJO has not yet
* attached to the cache system, it will simply return null.
*
@@ -84,6 +123,16 @@
Object find(String id) throws PojoCacheException;
/**
+ * Retrieve POJO from the cache system. Return null if object does not exist in the cache.
+ * Note that this operation is fast if there is already a POJO instance attached to the cache.
+ *
+ * @param id that associates with this node.
+ * @return Current content value. Null if does not exist.
+ * @throws PojoCacheException Throws if there is an error related to the cache operation.
+ */
+ Object find(Fqn<?> id) throws PojoCacheException;
+
+ /**
* Query all managed POJO objects under the id recursively. Note that this will not return
* the sub-object POJOs, e.g., if <em>Person</em> has a sub-object of <em>Address</em>, it
* won't return <em>Address</em> pojo. Also note also that this operation is not thread-safe
@@ -94,9 +143,22 @@
* @return Map of all POJOs found with (id, POJO) pair. Return size of 0, if not found.
* @throws PojoCacheException Throws if there is an error related to the cache operation.
*/
- Map findAll(String id) throws PojoCacheException;
+ Map<Fqn<?>, Object> findAll(String id) throws PojoCacheException;
/**
+ * Query all managed POJO objects under the id recursively. Note that this will not return
+ * the sub-object POJOs, e.g., if <em>Person</em> has a sub-object of <em>Address</em>, it
+ * won't return <em>Address</em> pojo. Also note also that this operation is not thread-safe
+ * now. In addition, it assumes that once a POJO is found with a id, no more POJO is stored
+ * under the children of the id. That is, we don't mix the id with different POJOs.
+ *
+ * @param id The starting place to find all POJOs.
+ * @return Map of all POJOs found with (id, POJO) pair. Return size of 0, if not found.
+ * @throws PojoCacheException Throws if there is an error related to the cache operation.
+ */
+ Map<Fqn<?>, Object> findAll(Fqn<?> id) throws PojoCacheException;
+
+ /**
* Lifecycle method to start PojoCache.
*
* @throws PojoCacheException
Modified: pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java
===================================================================
--- pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java 2007-09-19 17:05:59 UTC (rev 4488)
+++ pojo/trunk/src/main/java/org/jboss/cache/pojo/impl/PojoCacheImpl.java 2007-09-20 04:28:36 UTC (rev 4489)
@@ -27,7 +27,6 @@
import org.jboss.cache.pojo.annotation.Attach;
import org.jboss.cache.pojo.annotation.Detach;
import org.jboss.cache.pojo.annotation.Find;
-import org.jboss.cache.pojo.notification.annotation.PojoCacheListener;
/**
* Implementation class for PojoCache interface
@@ -73,7 +72,7 @@
{
try
{
- cache = (CacheSPI) DefaultCacheFactory.getInstance().createCache(config, toStart);
+ cache = (CacheSPI<Object, Object>) DefaultCacheFactory.getInstance().createCache(config, toStart);
}
catch (Exception e)
{
@@ -83,7 +82,7 @@
delegate_ = new PojoCacheDelegate(this);
}
- public CacheSPI getCacheSPI()
+ public CacheSPI<Object, Object> getCacheSPI()
{
return cache;
}
@@ -94,7 +93,7 @@
}
@Attach
- public Object attach(Fqn id, Object pojo) throws PojoCacheException
+ public Object attach(Fqn<?> id, Object pojo) throws PojoCacheException
{
try
{
@@ -108,7 +107,7 @@
}
@Attach
- public Object attach(Fqn id, Object pojo, String field) throws PojoCacheException
+ public Object attach(Fqn<?> id, Object pojo, String field) throws PojoCacheException
{
try
{
@@ -124,7 +123,7 @@
/**
* This public API is called from internal package only.
*/
- public Object putObject(Fqn id, Object pojo, String field)
+ public Object putObject(Fqn<?> id, Object pojo, String field)
throws CacheException
{
Object obj = null;
@@ -143,7 +142,7 @@
}
@Detach
- public Object detach(Fqn id, String field) throws PojoCacheException
+ public Object detach(Fqn<?> id, String field) throws PojoCacheException
{
try
{
@@ -159,12 +158,12 @@
}
}
- public Object detach(Fqn id) throws PojoCacheException
+ public Object detach(Fqn<?> id) throws PojoCacheException
{
return detach(id, null);
}
- public Object removeObject(Fqn id, String field) throws CacheException
+ public Object removeObject(Fqn<?> id, String field) throws CacheException
{
delegate_.setBulkRemove(false);
return delegate_.removeObject(id, field);
@@ -181,7 +180,7 @@
}
@Find
- public Object find(Fqn id) throws PojoCacheException
+ public Object find(Fqn<?> id) throws PojoCacheException
{
try
{
@@ -193,24 +192,24 @@
}
}
- public Object getObject(Fqn id) throws CacheException
+ public Object getObject(Fqn<?> id) throws CacheException
{
return getObject(id, null);
}
- public Object getObject(Fqn id, String field) throws CacheException
+ public Object getObject(Fqn<?> id, String field) throws CacheException
{
return delegate_.getObject(id, field);
}
- public Map findAll(String id) throws PojoCacheException
+ public Map<Fqn<?>, Object> findAll(String id) throws PojoCacheException
{
return findAll(Fqn.fromString(id));
}
@Find
- public Map findAll(Fqn id) throws PojoCacheException
+ public Map<Fqn<?>, Object> findAll(Fqn<?> id) throws PojoCacheException
{
// Should produce "/"
if (id == null) id = Fqn.ROOT;
@@ -320,22 +319,6 @@
}
/**
- * Used by internal implementation. Not for general public.
- */
- public Object _evictObject(Fqn fqn) throws CacheException
- {
- boolean evict = true;
- boolean removeCacheInterceptor = false;
-
- // Configurable option to see if we want to remove the cache interceptor when the pojo is
- // evicted.
- // if(detachPojoWhenEvicted_) removeCacheInterceptor = true;
- delegate_.setBulkRemove(false);
- // return delegate_._removeObject(fqn, removeCacheInterceptor);
- return null;
- }
-
- /**
* Obtain a cache aop type for user to traverse the defined "primitive" types in aop.
* Note that this is not a synchronized call now for speed optimization.
*
Modified: pojo/trunk/src/test/java/org/jboss/cache/pojo/NewLocalTest.java
===================================================================
--- pojo/trunk/src/test/java/org/jboss/cache/pojo/NewLocalTest.java 2007-09-19 17:05:59 UTC (rev 4488)
+++ pojo/trunk/src/test/java/org/jboss/cache/pojo/NewLocalTest.java 2007-09-20 04:28:36 UTC (rev 4489)
@@ -211,7 +211,7 @@
map = cache_.findAll("/");
assertEquals("Objects size should be ", 2, map.size());
- map = cache_.findAll(null); // should everything.
+ map = cache_.findAll((String)null); // should everything.
assertEquals("Objects size should be ", 2, map.size());
}
}
17 years, 1 month
JBoss Cache SVN: r4488 - in core/trunk/src: test/java/org/jboss/cache and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-19 13:05:59 -0400 (Wed, 19 Sep 2007)
New Revision: 4488
Modified:
core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java
Log:
JBCACHE-1179
Modified: core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-09-19 15:23:19 UTC (rev 4487)
+++ core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-09-19 17:05:59 UTC (rev 4488)
@@ -3387,8 +3387,9 @@
{
if (channel != null)
{
+ channel.disconnect();
channel.close();
- channel.disconnect();
+// channel.disconnect();
}
}
@@ -3952,6 +3953,20 @@
}
+ private void blockUntilCacheStarts() throws InterruptedException
+ {
+ int pollFrequencyMS = 100;
+ long startupWaitTime = configuration.getStateRetrievalTimeout();
+ long giveUpTime = System.currentTimeMillis() + startupWaitTime;
+
+ while (System.currentTimeMillis() < giveUpTime)
+ {
+ if (cacheStatus.allowInvocations()) break;
+ Thread.sleep(pollFrequencyMS);
+ }
+
+ }
+
/**
* Invokes a method against this object. Contains the logger_ic for handling
* the various use cases, e.g. mode (local, repl_async, repl_sync),
@@ -3976,8 +3991,25 @@
}
else
{
- log.warn("Received a remote call but the cache is not in STARTED state - ignoring call.");
- return null;
+ if (getCacheStatus() == CacheStatus.STARTING)
+ {
+ try
+ {
+ blockUntilCacheStarts();
+ }
+ catch (InterruptedException e)
+ {
+ Thread.currentThread().interrupt();
+ }
+
+ // if the cache STILL can't take invocations...
+ if (!cacheStatus.allowInvocations()) throw new IllegalStateException("Cache not in STARTED state!");
+ }
+ else
+ {
+ log.warn("Received a remote call but the cache is not in STARTED state - ignoring call.");
+ return null;
+ }
}
}
Modified: core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java 2007-09-19 15:23:19 UTC (rev 4487)
+++ core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java 2007-09-19 17:05:59 UTC (rev 4488)
@@ -19,6 +19,7 @@
import org.jboss.cache.transaction.DummyTransactionManager;
import org.jboss.cache.misc.TestingUtil;
import org.testng.annotations.Test;
+import org.testng.annotations.AfterMethod;
import java.util.List;
import java.util.LinkedList;
@@ -29,294 +30,338 @@
* @author Bela Ban
* @version $Id$
*/
+@Test(groups = {"functional"})
public class LifeCycleTest
{
-
private static Log log = LogFactory.getLog(LifeCycleTest.class);
+ private CacheImpl[] c;
- @Test(groups = {"functional"})
+ @AfterMethod
+ public void tearDown()
+ {
+ if (c != null)
+ {
+ for (Cache cache : c)
+ {
+ if (cache != null)
+ {
+ try
+ {
+ cache.stop();
+ }
+ catch (Exception e)
+ {
+ // do nothing
+ }
+ }
+ }
+ }
+ c = null;
+ }
+
+ private void createAndRegisterCache(Configuration.CacheMode mode, boolean start) throws Exception
+ {
+ Cache cache = createCache(mode);
+ List<Cache> caches = new LinkedList<Cache>();
+ if (c != null) for (Cache existingCache : c) caches.add(existingCache);
+ caches.add(cache);
+ c = caches.toArray(new CacheImpl[]{});
+ if (start)
+ {
+ cache.start();
+ if (c.length > 1) TestingUtil.blockUntilViewsReceived(c, 10000);
+ }
+ }
+
+
public void testLocalRestartNoTransactions() throws Exception
{
- CacheImpl cache = createCache(Configuration.CacheMode.LOCAL);
- cache.create();
- cache.start();
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, true);
- cache.put("/a/b/c", null);
- assertTrue(cache.getNumberOfNodes() > 0);
- assertEquals(0, cache.getNumberOfLocksHeld());
+ c[0].put("/a/b/c", null);
+ assertTrue(c[0].getNumberOfNodes() > 0);
+ assertEquals(0, c[0].getNumberOfLocksHeld());
- System.out.println("cache locks before restart:\n" + cache.printLockInfo());
- restartCache(cache);
- System.out.println("cache locks after restart:\n" + cache.printLockInfo());
+ System.out.println("cache locks before restart:\n" + c[0].printLockInfo());
+ restartCache(c[0]);
+ System.out.println("cache locks after restart:\n" + c[0].printLockInfo());
- assertEquals(0, cache.getNumberOfNodes());
- assertEquals(0, cache.getNumberOfLocksHeld());
+ assertEquals(0, c[0].getNumberOfNodes());
+ assertEquals(0, c[0].getNumberOfLocksHeld());
}
- @Test(groups = {"functional"})
public void testLocalRestartWithTransactions() throws Exception
{
- CacheImpl cache = createCache(Configuration.CacheMode.LOCAL);
- cache.create();
- cache.start();
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, true);
Transaction tx = beginTransaction();
- cache.put("/a/b/c", null);
- log.debug("cache locks before restart:\n" + cache.printLockInfo());
- assertTrue(cache.getNumberOfNodes() > 0);
- assertEquals(4, cache.getNumberOfLocksHeld());
+ c[0].put("/a/b/c", null);
+ log.debug("cache locks before restart:\n" + c[0].printLockInfo());
+ assertTrue(c[0].getNumberOfNodes() > 0);
+ assertEquals(4, c[0].getNumberOfLocksHeld());
- restartCache(cache);
- log.debug("cache locks after restart:\n" + cache.printLockInfo());
+ restartCache(c[0]);
+ log.debug("cache locks after restart:\n" + c[0].printLockInfo());
//assertEquals(4, cache.getNumberOfLocksHeld());
- assertEquals(0, cache.getNumberOfNodes());
+ assertEquals(0, c[0].getNumberOfNodes());
tx.rollback();
- assertEquals(0, cache.getNumberOfLocksHeld());
+ assertEquals(0, c[0].getNumberOfLocksHeld());
}
- @Test(groups = {"functional"})
public void testStartNoCreate() throws Exception
{
- CacheImpl cache = createCache(Configuration.CacheMode.LOCAL);
- cache.start();
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, false);
+ c[0].start();
- cache.put("/a/b/c", null);
- assertTrue(cache.getNumberOfNodes() > 0);
- assertEquals(0, cache.getNumberOfLocksHeld());
+ c[0].put("/a/b/c", null);
+ assertTrue(c[0].getNumberOfNodes() > 0);
+ assertEquals(0, c[0].getNumberOfLocksHeld());
- System.out.println("cache locks before restart:\n" + cache.printLockInfo());
- restartCache(cache);
- System.out.println("cache locks after restart:\n" + cache.printLockInfo());
+ System.out.println("cache locks before restart:\n" + c[0].printLockInfo());
+ restartCache(c[0]);
+ System.out.println("cache locks after restart:\n" + c[0].printLockInfo());
- assertEquals(0, cache.getNumberOfNodes());
- assertEquals(0, cache.getNumberOfLocksHeld());
+ assertEquals(0, c[0].getNumberOfNodes());
+ assertEquals(0, c[0].getNumberOfLocksHeld());
}
- @Test(groups = {"functional"})
public void testReStartNoCreate() throws Exception
{
- CacheImpl cache = createCache(Configuration.CacheMode.LOCAL);
- cache.start();
- cache.stop();
- cache.start();
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, false);
+ c[0].start();
+ c[0].stop();
+ c[0].start();
- cache.put("/a/b/c", null);
- assertTrue(cache.getNumberOfNodes() > 0);
- assertEquals(0, cache.getNumberOfLocksHeld());
+ c[0].put("/a/b/c", null);
+ assertTrue(c[0].getNumberOfNodes() > 0);
+ assertEquals(0, c[0].getNumberOfLocksHeld());
- System.out.println("cache locks before restart:\n" + cache.printLockInfo());
- restartCache(cache);
- System.out.println("cache locks after restart:\n" + cache.printLockInfo());
+ System.out.println("cache locks before restart:\n" + c[0].printLockInfo());
+ restartCache(c[0]);
+ System.out.println("cache locks after restart:\n" + c[0].printLockInfo());
- assertEquals(0, cache.getNumberOfNodes());
- assertEquals(0, cache.getNumberOfLocksHeld());
+ assertEquals(0, c[0].getNumberOfNodes());
+ assertEquals(0, c[0].getNumberOfLocksHeld());
}
- @Test(groups = {"functional"})
public void testDuplicateInvocation() throws Exception
{
- CacheImpl cache = createCache(Configuration.CacheMode.LOCAL);
- cache.create();
- cache.start();
- cache.create();
- cache.start();
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, false);
+ c[0].create();
+ c[0].start();
+ c[0].create();
+ c[0].start();
- cache.put("/a/b/c", null);
- assertTrue(cache.getNumberOfNodes() > 0);
- assertEquals(0, cache.getNumberOfLocksHeld());
+ c[0].put("/a/b/c", null);
+ assertTrue(c[0].getNumberOfNodes() > 0);
+ assertEquals(0, c[0].getNumberOfLocksHeld());
- System.out.println("cache locks before restart:\n" + cache.printLockInfo());
- restartCache(cache);
- System.out.println("cache locks after restart:\n" + cache.printLockInfo());
+ System.out.println("cache locks before restart:\n" + c[0].printLockInfo());
+ restartCache(c[0]);
+ System.out.println("cache locks after restart:\n" + c[0].printLockInfo());
- assertEquals(0, cache.getNumberOfNodes());
- assertEquals(0, cache.getNumberOfLocksHeld());
+ assertEquals(0, c[0].getNumberOfNodes());
+ assertEquals(0, c[0].getNumberOfLocksHeld());
- cache.stop();
- cache.destroy();
- cache.stop();
- cache.destroy();
+ c[0].stop();
+ c[0].destroy();
+ c[0].stop();
+ c[0].destroy();
}
- @Test(groups = {"functional"})
public void testFailedStart() throws Exception
{
- CacheImpl cache = createCache(Configuration.CacheMode.LOCAL);
- assertEquals("Correct state", CacheStatus.INSTANTIATED, cache.getCacheStatus());
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, false);
+ assertEquals("Correct state", CacheStatus.INSTANTIATED, c[0].getCacheStatus());
DisruptLifecycleListener listener = new DisruptLifecycleListener();
- cache.addCacheListener(listener);
+ c[0].addCacheListener(listener);
- cache.create();
+ c[0].create();
listener.disrupt = true;
- assertEquals("Correct state", CacheStatus.CREATED, cache.getCacheStatus());
+ assertEquals("Correct state", CacheStatus.CREATED, c[0].getCacheStatus());
try
{
- cache.start();
+ c[0].start();
fail("Listener did not prevent start");
}
catch (CacheException good)
{
}
- assertEquals("Correct state", CacheStatus.FAILED, cache.getCacheStatus());
+ assertEquals("Correct state", CacheStatus.FAILED, c[0].getCacheStatus());
- cache.addCacheListener(listener);
+ c[0].addCacheListener(listener);
listener.disrupt = false;
- cache.start();
+ c[0].start();
- assertEquals("Correct state", CacheStatus.STARTED, cache.getCacheStatus());
+ assertEquals("Correct state", CacheStatus.STARTED, c[0].getCacheStatus());
- cache.put("/a/b/c", null);
- assertTrue(cache.getNumberOfNodes() > 0);
- assertEquals(0, cache.getNumberOfLocksHeld());
+ c[0].put("/a/b/c", null);
+ assertTrue(c[0].getNumberOfNodes() > 0);
+ assertEquals(0, c[0].getNumberOfLocksHeld());
listener.disrupt = true;
- cache.addCacheListener(listener);
+ c[0].addCacheListener(listener);
try
{
- cache.stop();
+ c[0].stop();
fail("Listener did not prevent stop");
}
catch (CacheException good)
{
}
- assertEquals("Correct state", CacheStatus.FAILED, cache.getCacheStatus());
+ assertEquals("Correct state", CacheStatus.FAILED, c[0].getCacheStatus());
listener.disrupt = false;
- cache.stop();
- assertEquals("Correct state", CacheStatus.STOPPED, cache.getCacheStatus());
- cache.destroy();
- assertEquals("Correct state", CacheStatus.DESTROYED, cache.getCacheStatus());
+ c[0].stop();
+ assertEquals("Correct state", CacheStatus.STOPPED, c[0].getCacheStatus());
+ c[0].destroy();
+ assertEquals("Correct state", CacheStatus.DESTROYED, c[0].getCacheStatus());
}
- @Test(groups = {"functional"})
public void testInvalidStateInvocations() throws Exception
{
- Cache<Object, Object> c = createCache(Configuration.CacheMode.LOCAL);
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, false);
try
{
- try
- {
- c.get(Fqn.ROOT, "k");
- fail("Cache isn't ready!");
- }
- catch (IllegalStateException good)
- {
- }
+ c[0].get(Fqn.ROOT, "k");
+ fail("Cache isn't ready!");
+ }
+ catch (IllegalStateException good)
+ {
+ }
- c.create();
- try
- {
- c.get(Fqn.ROOT, "k");
- fail("Cache isn't ready!");
- }
- catch (IllegalStateException good)
- {
- }
+ c[0].create();
+ try
+ {
+ c[0].get(Fqn.ROOT, "k");
+ fail("Cache isn't ready!");
+ }
+ catch (IllegalStateException good)
+ {
+ }
- c.start();
- c.get(Fqn.ROOT, "k"); // should work
+ c[0].start();
+ c[0].get(Fqn.ROOT, "k"); // should work
- c.stop();
+ c[0].stop();
- try
- {
- c.get(Fqn.ROOT, "k");
- fail("Cache isn't ready!");
- }
- catch (IllegalStateException good)
- {
- }
+ try
+ {
+ c[0].get(Fqn.ROOT, "k");
+ fail("Cache isn't ready!");
+ }
+ catch (IllegalStateException good)
+ {
+ }
- c.destroy();
- try
- {
- c.get(Fqn.ROOT, "k");
- fail("Cache isn't ready!");
- }
- catch (IllegalStateException good)
- {
- }
+ c[0].destroy();
+ try
+ {
+ c[0].get(Fqn.ROOT, "k");
+ fail("Cache isn't ready!");
}
- finally
+ catch (IllegalStateException good)
{
- c.stop();
}
}
- @Test(groups = {"functional"})
public void testRemoteInvalidStateInvocations() throws Exception
{
- CacheImpl<Object, Object> c1 = createCache(Configuration.CacheMode.REPL_SYNC);
- CacheImpl<Object, Object> c2 = createCache(Configuration.CacheMode.REPL_SYNC);
+ createAndRegisterCache(Configuration.CacheMode.REPL_SYNC, true);
+ createAndRegisterCache(Configuration.CacheMode.REPL_SYNC, true);
try
{
- // need to start them both first to ensure they see each other
- c1.start();
- c2.start();
+ // now DIRECTLY change the status of c2.
+ // emulate the race condition where the remote cache is stopping but hasn't disconnected from the channel.
+ c[1].cacheStatus = CacheStatus.STOPPING;
+ // Thanks to JBCACHE-1179, this should only log a warning and not throw an exception
+ c[0].put(Fqn.ROOT, "k", "v");
+ }
+ finally
+ {
+ // reset c[1] to running so the tearDown method can clean it up
+ c[1].cacheStatus = CacheStatus.STARTED;
+ }
+ }
+
+ public void testRemoteInvalidStateInvocations2() throws Exception
+ {
+ createAndRegisterCache(Configuration.CacheMode.REPL_SYNC, true);
+ createAndRegisterCache(Configuration.CacheMode.REPL_SYNC, true);
+ try
+ {
// now DIRECTLY change the status of c2.
// emulate the race condition where the remote cache is stopping but hasn't disconnected from the channel.
- c2.cacheStatus = CacheStatus.STOPPING;
+ c[1].cacheStatus = CacheStatus.STARTING;
try
{
- c1.put(Fqn.ROOT, "k", "v");
- fail("Cache isn't ready!");
+ // This call should wait for up to StateRetrievalTimeout secs or until c[1] has entered the STARTED state, and then barf.
+ c[0].put(Fqn.ROOT, "k", "v");
+ fail("Should barf!");
}
catch (IllegalStateException good)
{
+
}
+
+ // now kick off another thread to sleep for a few secs and then set c[1] to STARTED
+ final int sleepTime = 500;
+ new Thread()
+ {
+ public void run()
+ {
+ TestingUtil.sleepThread(sleepTime);
+ c[1].cacheStatus = CacheStatus.STARTED;
+ }
+ }.start();
+
+ // should succeed but should take at least 1000ms.
+ long startTime = System.currentTimeMillis();
+ c[0].put(Fqn.ROOT, "k", "v");
+ assert System.currentTimeMillis() > (startTime + sleepTime) : "Should wait till c[1] has STARTED state";
+
}
finally
{
- c1.stop();
- c2.stop();
+ // reset c[1] to running so the tearDown method can clean it up
+ c[1].cacheStatus = CacheStatus.STARTED;
}
}
- @Test(groups = {"functional"})
public void testInvalidStateTxCommit() throws Exception
{
- CacheImpl<Object, Object> c = createCache(Configuration.CacheMode.LOCAL);
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, true);
+ c[0].getTransactionManager().begin();
+ c[0].put(Fqn.ROOT, "k1", "v1");
+ c[0].put(Fqn.ROOT, "k2", "v2");
+
+ // now DIRECTLY change the status of c.
+ c[0].cacheStatus = CacheStatus.STOPPING;
+
try
{
- c.start();
-
- c.getTransactionManager().begin();
- c.put(Fqn.ROOT, "k1", "v1");
- c.put(Fqn.ROOT, "k2", "v2");
-
- // now DIRECTLY change the status of c.
- c.cacheStatus = CacheStatus.STOPPING;
-
- try
- {
- c.getTransactionManager().commit();
- fail("Cache isn't STARTED!");
- }
- catch (RollbackException good)
- {
- }
+ c[0].getTransactionManager().commit();
+ fail("Cache isn't STARTED!");
}
- finally
+ catch (RollbackException good)
{
- c.stop();
}
}
- @Test(groups = {"functional"})
@SuppressWarnings("unchecked")
public void testStopInstanceWhileOtherInstanceSends() throws Exception
{
@@ -325,84 +370,64 @@
final List<Exception> exceptions = new LinkedList<Exception>();
running.add(true);
- final CacheImpl <Object, Object> c[] = new CacheImpl[2];
- try
- {
- c[0] = createCache(Configuration.CacheMode.REPL_SYNC);
- c[1] = createCache(Configuration.CacheMode.REPL_SYNC);
- c[0].start();
- c[1].start();
- TestingUtil.blockUntilViewsReceived(5000, c[0], c[1]);
+ createAndRegisterCache(Configuration.CacheMode.REPL_SYNC, true);
+ createAndRegisterCache(Configuration.CacheMode.REPL_SYNC, true);
- c[0].put(fqn, "k", "v");
+ c[0].put(fqn, "k", "v");
- assert "v".equals(c[0].get(fqn, "k"));
- assert "v".equals(c[1].get(fqn, "k"));
+ assert "v".equals(c[0].get(fqn, "k"));
+ assert "v".equals(c[1].get(fqn, "k"));
- // now kick start a thread on c[1] that will constantly update the fqn
+ // now kick start a thread on c[1] that will constantly update the fqn
- Thread updater = new Thread()
+ Thread updater = new Thread()
+ {
+ public void run()
{
- public void run()
+ int i=0;
+ while (running.get(0))
{
- int i=0;
- while (running.get(0))
+ try
{
- try
- {
- i++;
- c[1].put(fqn, "k", "v" + i);
- }
- catch (Exception e)
- {
- exceptions.add(e);
- }
- TestingUtil.sleepThread(20);
+ i++;
+ if (running.get(0)) c[1].put(fqn, "k", "v" + i);
+ }
+ catch (ReplicationException re)
+ {
+ // this sometimes happens when JGroups suspects the remote node. This is ok, as long as we don't get an ISE.
+ }
+ catch (Exception e)
+ {
+ exceptions.add(e);
+ }
+ TestingUtil.sleepThread(20);
- }
}
- };
+ }
+ };
- updater.start();
+ updater.start();
- c[0].stop();
- running.add(false);
- running.remove(true);
- updater.join();
+ c[0].stop();
+ running.add(false);
+ running.remove(true);
+ updater.join();
- for (Exception e : exceptions) throw e;
- }
- finally
- {
- for (CacheImpl ci : c)
- {
- if (ci != null) ci.stop();
- }
- }
+ for (Exception e : exceptions) throw e;
}
- @Test(groups = {"functional"})
public void testInvalidStateTxRollback() throws Exception
{
- CacheImpl<Object, Object> c = createCache(Configuration.CacheMode.LOCAL);
- try
- {
- c.start();
+ createAndRegisterCache(Configuration.CacheMode.LOCAL, true);
+ c[0].getTransactionManager().begin();
+ c[0].put(Fqn.ROOT, "k1", "v1");
+ c[0].put(Fqn.ROOT, "k2", "v2");
- c.getTransactionManager().begin();
- c.put(Fqn.ROOT, "k1", "v1");
- c.put(Fqn.ROOT, "k2", "v2");
+ // now DIRECTLY change the status of c.
+ c[0].cacheStatus = CacheStatus.STOPPING;
- // now DIRECTLY change the status of c.
- c.cacheStatus = CacheStatus.STOPPING;
-
- // rollbacks should just log a message
- c.getTransactionManager().rollback();
- }
- finally
- {
- c.stop();
- }
+ // rollbacks should just log a message
+ c[0].getTransactionManager().rollback();
}
@@ -419,8 +444,7 @@
{
DummyTransactionManager mgr = DummyTransactionManager.getInstance();
mgr.begin();
- Transaction tx = mgr.getTransaction();
- return tx;
+ return mgr.getTransaction();
}
17 years, 1 month
JBoss Cache SVN: r4487 - in core/trunk/src: test/java/org/jboss/cache and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-19 11:23:19 -0400 (Wed, 19 Sep 2007)
New Revision: 4487
Modified:
core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java
Log:
JBCACHE-1179
Modified: core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-09-19 13:32:27 UTC (rev 4486)
+++ core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-09-19 15:23:19 UTC (rev 4487)
@@ -3968,8 +3968,20 @@
// BR methods should NOT block on the cache being started, since the cache depends on these completing to start.
if (!MethodDeclarations.isBuddyGroupOrganisationMethod(m.getMethodId()) && !cacheStatus.allowInvocations() && !ctx.getOptionOverrides().isSkipCacheStatusCheck())
- throw new IllegalStateException("Cache not in STARTED state!");
+ {
+ // only throw an exception if this is a locally originating call - JBCACHE-1179
+ if (originLocal)
+ {
+ throw new IllegalStateException("Cache not in STARTED state!");
+ }
+ else
+ {
+ log.warn("Received a remote call but the cache is not in STARTED state - ignoring call.");
+ return null;
+ }
+ }
+
MethodCall oldCall = null;
try
{
Modified: core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java 2007-09-19 13:32:27 UTC (rev 4486)
+++ core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java 2007-09-19 15:23:19 UTC (rev 4487)
@@ -17,7 +17,12 @@
import org.jboss.cache.notifications.annotation.CacheStopped;
import org.jboss.cache.notifications.event.Event;
import org.jboss.cache.transaction.DummyTransactionManager;
+import org.jboss.cache.misc.TestingUtil;
import org.testng.annotations.Test;
+
+import java.util.List;
+import java.util.LinkedList;
+
/**
* Tests restart (stop-destroy-create-start) of CacheImpl
*
@@ -315,13 +320,57 @@
@SuppressWarnings("unchecked")
public void testStopInstanceWhileOtherInstanceSends() throws Exception
{
- CacheImpl <Object, Object> c[] = new CacheImpl[2];
+ final Fqn fqn = Fqn.fromString("/a");
+ final List<Boolean> running = new LinkedList<Boolean>();
+ final List<Exception> exceptions = new LinkedList<Exception>();
+ running.add(true);
+
+ final CacheImpl <Object, Object> c[] = new CacheImpl[2];
try
{
c[0] = createCache(Configuration.CacheMode.REPL_SYNC);
c[1] = createCache(Configuration.CacheMode.REPL_SYNC);
+ c[0].start();
+ c[1].start();
+ TestingUtil.blockUntilViewsReceived(5000, c[0], c[1]);
- c[0].put()
+ c[0].put(fqn, "k", "v");
+
+ assert "v".equals(c[0].get(fqn, "k"));
+ assert "v".equals(c[1].get(fqn, "k"));
+
+ // now kick start a thread on c[1] that will constantly update the fqn
+
+ Thread updater = new Thread()
+ {
+ public void run()
+ {
+ int i=0;
+ while (running.get(0))
+ {
+ try
+ {
+ i++;
+ c[1].put(fqn, "k", "v" + i);
+ }
+ catch (Exception e)
+ {
+ exceptions.add(e);
+ }
+ TestingUtil.sleepThread(20);
+
+ }
+ }
+ };
+
+ updater.start();
+
+ c[0].stop();
+ running.add(false);
+ running.remove(true);
+ updater.join();
+
+ for (Exception e : exceptions) throw e;
}
finally
{
17 years, 1 month
JBoss Cache SVN: r4486 - in core/trunk/src: main/java/org/jboss/cache and 6 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-19 09:32:27 -0400 (Wed, 19 Sep 2007)
New Revision: 4486
Added:
core/trunk/src/test/java/org/jboss/cache/eviction/minttl/
core/trunk/src/test/java/org/jboss/cache/eviction/minttl/FIFOMinTTLTest.java
core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LFUMinTTLTest.java
core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LRUMinTTLTest.java
core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MRUMinTTLTest.java
core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MinTTLTestBase.java
Modified:
core/trunk/src/main/docbook/userguide/en/modules/eviction_policies.xml
core/trunk/src/main/docbook/userguide/en/modules/transactions.xml
core/trunk/src/main/java/org/jboss/cache/RegionManager.java
core/trunk/src/main/java/org/jboss/cache/eviction/BaseEvictionAlgorithm.java
core/trunk/src/main/java/org/jboss/cache/eviction/ElementSizeAlgorithm.java
core/trunk/src/main/java/org/jboss/cache/eviction/EvictionPolicyConfigBase.java
core/trunk/src/main/java/org/jboss/cache/eviction/FIFOAlgorithm.java
core/trunk/src/main/java/org/jboss/cache/eviction/LFUAlgorithm.java
core/trunk/src/main/java/org/jboss/cache/eviction/LRUAlgorithm.java
core/trunk/src/main/java/org/jboss/cache/eviction/MRUAlgorithm.java
core/trunk/src/main/java/org/jboss/cache/eviction/NodeEntry.java
core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java
core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java
core/trunk/src/test/resources/log4j.xml
Log:
JBCACHE-1155
Modified: core/trunk/src/main/docbook/userguide/en/modules/eviction_policies.xml
===================================================================
--- core/trunk/src/main/docbook/userguide/en/modules/eviction_policies.xml 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/docbook/userguide/en/modules/eviction_policies.xml 2007-09-19 13:32:27 UTC (rev 4486)
@@ -36,8 +36,9 @@
</region>
<!-- override policy used for this region -->
- <region name="/org/jboss/data" policyClass="org.jboss.cache.eviction.MRUPolicy">
+ <region name="/org/jboss/data" policyClass="org.jboss.cache.eviction.LRUPolicy">
<attribute name="maxNodes">250</attribute>
+ <attribute name="minTimeToLiveSeconds">10</attribute>
</region>
<!-- We expect a lot of events for this region,
@@ -105,7 +106,8 @@
<literal>maxNodes</literal>
parameter which defines
how many nodes can exist in the region before it chooses to start evicting nodes. See the javadocs for each
- policy for a list of allowed parameters.
+ policy for a list of allowed parameters. It also defines a <literal>minTimeToLiveSeconds</literal> parameter,
+ which defines a minimum time a node must exist in memory before being considered for eviction.
</para>
<section>
@@ -206,6 +208,12 @@
- Lifespan of a node (in seconds) regardless of idle time before the node is swept away. 0 denotes no
limit.
</listitem>
+
+ <listitem>
+ <literal>minTimeToLiveSeconds</literal>
+ - the minimum amount of time a node must be allowed to live after being accessed before it is allowed to
+ be considered for eviction. 0 denotes that this feature is disabled, which is the default value.
+ </listitem>
</itemizedlist>
</section>
@@ -226,6 +234,11 @@
<literal>maxNodes</literal>
- This is the maximum number of nodes allowed in this region. 0 denotes no limit.
</listitem>
+ <listitem>
+ <literal>minTimeToLiveSeconds</literal>
+ - the minimum amount of time a node must be allowed to live after being accessed before it is allowed to
+ be considered for eviction. 0 denotes that this feature is disabled, which is the default value.
+ </listitem>
</itemizedlist>
</section>
@@ -249,6 +262,11 @@
<literal>maxNodes</literal>
- This is the maximum number of nodes allowed in this region. 0 denotes no limit.
</listitem>
+ <listitem>
+ <literal>minTimeToLiveSeconds</literal>
+ - the minimum amount of time a node must be allowed to live after being accessed before it is allowed to
+ be considered for eviction. 0 denotes that this feature is disabled, which is the default value.
+ </listitem>
</itemizedlist>
</section>
@@ -293,7 +311,11 @@
eviction timer makes a pass through the eviction
algorithm.
</listitem>
-
+ <listitem>
+ <literal>minTimeToLiveSeconds</literal>
+ - the minimum amount of time a node must be allowed to live after being accessed before it is allowed to
+ be considered for eviction. 0 denotes that this feature is disabled, which is the default value.
+ </listitem>
</itemizedlist>
</section>
@@ -342,7 +364,6 @@
<literal>maxNodes</literal>
- This is the maximum number of nodes allowed in this region. 0 denotes no limit.
</listitem>
-
</itemizedlist>
<para>
@@ -391,6 +412,11 @@
- This is the trigger number of attributes per node for the node to be selected for eviction. 0 denotes
no limit.
</listitem>
+ <listitem>
+ <literal>minTimeToLiveSeconds</literal>
+ - the minimum amount of time a node must be allowed to live after being accessed before it is allowed to
+ be considered for eviction. 0 denotes that this feature is disabled, which is the default value.
+ </listitem>
</itemizedlist>
</section>
</section>
Modified: core/trunk/src/main/docbook/userguide/en/modules/transactions.xml
===================================================================
--- core/trunk/src/main/docbook/userguide/en/modules/transactions.xml 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/docbook/userguide/en/modules/transactions.xml 2007-09-19 13:32:27 UTC (rev 4486)
@@ -247,6 +247,12 @@
...
]]>
</programlisting>
+ It is generally advisable that if you have an eviction policy defined along with optimistic locking, you define
+ the eviction policy's <literal>minTimeToLiveSeconds</literal> parameter to be slightly greater than the transaction
+ timeout value set in your transaction manager. This ensures that data versions in the cache are not evicted
+ while transactions are in progress<footnote>
+ <para>See <ulink url="http://jira.jboss.com/jira/browse/JBCACHE-1155">JBCACHE-1155</ulink></para>
+ </footnote>.
</section>
</section>
</section>
Modified: core/trunk/src/main/java/org/jboss/cache/RegionManager.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/RegionManager.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/RegionManager.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -166,15 +166,6 @@
}
return r;
}
- else
- {
- // first test if the default region has been defined. If not, and if eviction regions
- // are in use, throw an exception since it is required.
- if (isUsingEvictions() && !regionsRegistry.containsKey(Fqn.ROOT))
- {
- throw new RuntimeException("No default eviction region defined!");
- }
- }
// else try and find a parent which has a defined region, may return null if nothing is defined.
Region nextBestThing = null;
@@ -199,6 +190,14 @@
if (nextFqn.isRoot()) break;
}
+ // test if the default region has been defined. If not, and if eviction regions
+ // are in use, throw an exception since it is required.
+ if ((nextBestThing == null || nextBestThing.getFqn().isRoot() && !regionsRegistry.containsKey(Fqn.ROOT))
+ && isUsingEvictions())
+ {
+ throw new RuntimeException("No default eviction region defined!");
+ }
+
return nextBestThing;
}
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/BaseEvictionAlgorithm.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/BaseEvictionAlgorithm.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/BaseEvictionAlgorithm.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -428,6 +428,7 @@
// also treat it as a node visit.
ne.setNumberOfNodeVisits(ne.getNumberOfNodeVisits() + 1);
ne.setModifiedTimeStamp(System.currentTimeMillis());
+// log.error ("*** Processing nodeAdded for fqn " + fqn + " NodeEntry's hashcode is " + ne.hashCode());
}
@@ -529,4 +530,24 @@
" evict=" + evictionQueue.getNumberOfNodes();
}
+ /**
+ * Tests whether a node entry is younger than the minimum time to live - if one is configured.
+ * @param entry the node entry being examined
+ * @return true if the node is younger than - or exactly equal to - the minimum time to live, if one is configured for the given region. False otherwise.
+ */
+ protected boolean isYoungerThanMinimumTimeToLive(NodeEntry entry)
+ {
+ if (region.getEvictionPolicyConfig() instanceof EvictionPolicyConfigBase)
+ {
+ EvictionPolicyConfigBase cfg = (EvictionPolicyConfigBase) region.getEvictionPolicyConfig();
+ int minTTL = cfg.getMinTimeToLiveSeconds();
+ return minTTL >= 1 && (entry.getModifiedTimeStamp() + (1000 * minTTL) > System.currentTimeMillis());
+ }
+ else
+ {
+ log.trace("Eviction policy implementation does not support minimum TTL!");
+ return false;
+ }
+ }
+
}
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/ElementSizeAlgorithm.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/ElementSizeAlgorithm.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/ElementSizeAlgorithm.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -22,6 +22,10 @@
protected boolean shouldEvictNode(NodeEntry ne)
{
+ // check the minimum time to live and see if we should not evict the node. This check will
+ // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
+ if (isYoungerThanMinimumTimeToLive(ne)) return false;
+
ElementSizeConfiguration config = (ElementSizeConfiguration) region.getEvictionPolicyConfig();
int size = this.getEvictionQueue().getNumberOfNodes();
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/EvictionPolicyConfigBase.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/EvictionPolicyConfigBase.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/EvictionPolicyConfigBase.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -22,6 +22,9 @@
@Dynamic
private int maxNodes = 0;
+ @Dynamic
+ private int minTimeToLiveSeconds = 0;
+
/**
* Can only be instantiated by a subclass.
*
@@ -53,6 +56,16 @@
testImmutability("maxNodes");
this.maxNodes = maxNodes;
}
+
+ public int getMinTimeToLiveSeconds()
+ {
+ return this.minTimeToLiveSeconds;
+ }
+
+ public void setMinTimeToLiveSeconds(int minTimeToLiveSeconds)
+ {
+ this.minTimeToLiveSeconds = minTimeToLiveSeconds;
+ }
public void validate() throws ConfigurationException
{
@@ -69,7 +82,7 @@
{
EvictionPolicyConfigBase other = (EvictionPolicyConfigBase) obj;
- return this.maxNodes == other.maxNodes
+ return this.maxNodes == other.maxNodes && this.minTimeToLiveSeconds == other.minTimeToLiveSeconds
&& safeEquals(this.evictionPolicyClass, other.evictionPolicyClass);
}
@@ -81,6 +94,7 @@
{
int result = 17;
result = 31 * result + maxNodes;
+ result = 31 * result + minTimeToLiveSeconds;
result = 31 * result + (evictionPolicyClass == null ? 0 : evictionPolicyClass.hashCode());
return result;
}
@@ -89,6 +103,7 @@
{
setEvictionPolicyClass(null);
setMaxNodes(0);
+ setMinTimeToLiveSeconds(0);
setEvictionPolicyClassName();
}
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/FIFOAlgorithm.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/FIFOAlgorithm.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/FIFOAlgorithm.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -37,6 +37,10 @@
*/
protected boolean shouldEvictNode(NodeEntry ne)
{
+ // check the minimum time to live and see if we should not evict the node. This check will
+ // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
+ if (isYoungerThanMinimumTimeToLive(ne)) return false;
+
FIFOConfiguration config = (FIFOConfiguration) region.getEvictionPolicyConfig();
if (log.isTraceEnabled())
{
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/LFUAlgorithm.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/LFUAlgorithm.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/LFUAlgorithm.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -49,6 +49,10 @@
log.trace("Deciding whether node in queue " + ne.getFqn() + " requires eviction.");
}
+ // check the minimum time to live and see if we should not evict the node. This check will
+ // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
+ if (isYoungerThanMinimumTimeToLive(ne)) return false;
+
LFUConfiguration config = (LFUConfiguration) region.getEvictionPolicyConfig();
int size = this.getEvictionQueue().getNumberOfNodes();
if (config.getMaxNodes() != 0 && size > config.getMaxNodes())
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/LRUAlgorithm.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/LRUAlgorithm.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/LRUAlgorithm.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -36,6 +36,10 @@
protected boolean shouldEvictNode(NodeEntry entry)
{
+ // check the minimum time to live and see if we should not evict the node. This check will
+ // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
+ if (isYoungerThanMinimumTimeToLive(entry)) return false;
+
LRUConfiguration config = (LRUConfiguration) region.getEvictionPolicyConfig();
// no idle or max time limit
if (config.getTimeToLiveSeconds() == 0 && config.getMaxAgeSeconds() == 0) return false;
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/MRUAlgorithm.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/MRUAlgorithm.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/MRUAlgorithm.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -29,6 +29,10 @@
protected boolean shouldEvictNode(NodeEntry ne)
{
+ // check the minimum time to live and see if we should not evict the node. This check will
+ // ensure that, if configured, nodes are kept alive for at least a minimum period of time.
+ if (isYoungerThanMinimumTimeToLive(ne)) return false;
+
MRUConfiguration config = (MRUConfiguration) region.getEvictionPolicyConfig();
return evictionQueue.getNumberOfNodes() > config.getMaxNodes();
}
Modified: core/trunk/src/main/java/org/jboss/cache/eviction/NodeEntry.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/eviction/NodeEntry.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/eviction/NodeEntry.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -1,6 +1,8 @@
package org.jboss.cache.eviction;
import org.jboss.cache.Fqn;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
/**
* Value object used in queue
@@ -20,6 +22,7 @@
private boolean currentlyInUse = false;
EvictionQueue queue;
+ private static Log log = LogFactory.getLog(NodeEntry.class);
/**
* Private constructor that automatically sets the creation time stamp of the node entry.
@@ -78,6 +81,7 @@
public void setModifiedTimeStamp(long modifiedTimeStamp)
{
+// log.error("Being modified to " + modifiedTimeStamp, new Throwable());
this.modifiedTimeStamp = modifiedTimeStamp;
}
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -205,7 +205,7 @@
/**
* Same as <code>invalidateModifications(modifications, workspace, defaultSynchronous)</code>
- * @deprecated use {@link #invalidateModifications(List<MethodCall>, TransactionWorkspace, boolean)
+ * @deprecated use {@link #invalidateAcrossCluster(org.jboss.cache.Fqn, org.jboss.cache.optimistic.TransactionWorkspace, boolean)}
*/
protected void invalidateModifications(List<MethodCall> modifications, TransactionWorkspace workspace) throws Throwable
{
Modified: core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/test/java/org/jboss/cache/LifeCycleTest.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -312,6 +312,27 @@
}
@Test(groups = {"functional"})
+ @SuppressWarnings("unchecked")
+ public void testStopInstanceWhileOtherInstanceSends() throws Exception
+ {
+ CacheImpl <Object, Object> c[] = new CacheImpl[2];
+ try
+ {
+ c[0] = createCache(Configuration.CacheMode.REPL_SYNC);
+ c[1] = createCache(Configuration.CacheMode.REPL_SYNC);
+
+ c[0].put()
+ }
+ finally
+ {
+ for (CacheImpl ci : c)
+ {
+ if (ci != null) ci.stop();
+ }
+ }
+ }
+
+ @Test(groups = {"functional"})
public void testInvalidStateTxRollback() throws Exception
{
CacheImpl<Object, Object> c = createCache(Configuration.CacheMode.LOCAL);
Added: core/trunk/src/test/java/org/jboss/cache/eviction/minttl/FIFOMinTTLTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/eviction/minttl/FIFOMinTTLTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/eviction/minttl/FIFOMinTTLTest.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -0,0 +1,76 @@
+package org.jboss.cache.eviction.minttl;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.AfterMethod;
+import org.jboss.cache.eviction.EvictionPolicyConfigBase;
+import org.jboss.cache.eviction.LRUConfiguration;
+import org.jboss.cache.eviction.FIFOConfiguration;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.util.CachePrinter;
+import org.jboss.cache.misc.TestingUtil;
+
+/**
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ * @since 2.1.0
+ */
+@Test(groups = {"functional"})
+public class FIFOMinTTLTest extends MinTTLTestBase
+{
+ private Fqn fqn2 = new Fqn(region, "b");
+ private Thread busyThread;
+ private boolean busyThreadRunning = true;
+
+ @Override
+ protected EvictionPolicyConfigBase getEvictionPolicyConfig()
+ {
+ startBusyThread();
+ FIFOConfiguration cfg = new FIFOConfiguration();
+ cfg.setMaxNodes(1);
+ return cfg;
+ }
+
+ @AfterMethod
+ public void stopBusyThread()
+ {
+ busyThreadRunning = false;
+ try
+ {
+ busyThread.join();
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+
+ private void startBusyThread()
+ {
+ // start a thread to constantly put another node in the cache to make sure the maxNodes is exceeded.
+ // this should only happen AFTER the main node is entered to guarantee FIFO.
+ busyThreadRunning = true;
+ busyThread = new Thread("BusyThread")
+ {
+ public void run()
+ {
+ try
+ {
+ cacheInitialisedLatch.await();
+ }
+ catch (InterruptedException e)
+ {
+ // do nothing
+ }
+
+ while (busyThreadRunning)
+ {
+ cache.put(fqn2, "k", "v");
+ TestingUtil.sleepRandom(150);
+ }
+ }
+ };
+
+ busyThread.setDaemon(true);
+ busyThread.start();
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LFUMinTTLTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LFUMinTTLTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LFUMinTTLTest.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -0,0 +1,22 @@
+package org.jboss.cache.eviction.minttl;
+
+import org.testng.annotations.Test;
+import org.jboss.cache.eviction.EvictionPolicyConfigBase;
+import org.jboss.cache.eviction.LRUConfiguration;
+import org.jboss.cache.eviction.LFUConfiguration;
+
+/**
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ * @since 2.1.0
+ */
+@Test(groups = {"functional"})
+public class LFUMinTTLTest extends MinTTLTestBase
+{
+ @Override
+ protected EvictionPolicyConfigBase getEvictionPolicyConfig()
+ {
+ LFUConfiguration cfg = new LFUConfiguration();
+ return cfg;
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LRUMinTTLTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LRUMinTTLTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/eviction/minttl/LRUMinTTLTest.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -0,0 +1,22 @@
+package org.jboss.cache.eviction.minttl;
+
+import org.testng.annotations.Test;
+import org.jboss.cache.eviction.EvictionPolicyConfigBase;
+import org.jboss.cache.eviction.LRUConfiguration;
+
+/**
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ * @since 2.1.0
+ */
+@Test(groups = {"functional"})
+public class LRUMinTTLTest extends MinTTLTestBase
+{
+ @Override
+ protected EvictionPolicyConfigBase getEvictionPolicyConfig()
+ {
+ LRUConfiguration cfg = new LRUConfiguration();
+ cfg.setTimeToLiveSeconds(1);
+ return cfg;
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MRUMinTTLTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MRUMinTTLTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MRUMinTTLTest.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -0,0 +1,59 @@
+package org.jboss.cache.eviction.minttl;
+
+import org.testng.annotations.Test;
+import org.jboss.cache.eviction.EvictionPolicyConfigBase;
+import org.jboss.cache.eviction.LRUConfiguration;
+import org.jboss.cache.eviction.MRUConfiguration;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.CacheStatus;
+import org.jboss.cache.misc.TestingUtil;
+
+/**
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ * @since 2.1.0
+ */
+@Test(groups = {"functional"})
+public class MRUMinTTLTest extends MinTTLTestBase
+{
+ private Fqn fqn2 = new Fqn(region, "b");
+ @Override
+ protected EvictionPolicyConfigBase getEvictionPolicyConfig()
+ {
+ MRUConfiguration cfg = new MRUConfiguration();
+ cfg.setMaxNodes(1);
+ startBusyThread();
+ return cfg;
+ }
+
+ private void startBusyThread()
+ {
+ // start a thread to constantly put another node in the cache to make sure the maxNodes is exceeded.
+ // this should only happen AFTER the main node is entered to guarantee FIFO.
+
+ Thread busyThread = new Thread()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ if (cache != null)
+ {
+ if (cache.getCacheStatus() == CacheStatus.STARTED)
+ {
+ if (cache.getRoot().hasChild(fqn))
+ {
+ cache.put(fqn2, "k", "v");
+ break;
+ }
+ }
+ }
+ TestingUtil.sleepRandom(50);
+ }
+ }
+ };
+
+ busyThread.setDaemon(true);
+ busyThread.start();
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MinTTLTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MinTTLTestBase.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/eviction/minttl/MinTTLTestBase.java 2007-09-19 13:32:27 UTC (rev 4486)
@@ -0,0 +1,114 @@
+package org.jboss.cache.eviction.minttl;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.jboss.cache.Cache;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.util.CachePrinter;
+import org.jboss.cache.eviction.EvictionPolicyConfigBase;
+import org.jboss.cache.eviction.LRUConfiguration;
+import org.jboss.cache.misc.TestingUtil;
+import org.jboss.cache.config.EvictionConfig;
+import org.jboss.cache.config.EvictionRegionConfig;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.List;
+import java.util.LinkedList;
+import java.util.Collections;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * This test exercises the minimum time to live for any element in the cache
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ * @since 2.1.0
+ */
+public abstract class MinTTLTestBase
+{
+ // this should ideally be in an eviction test base class so all eviction policies can be tested
+
+ protected Cache cache;
+ protected Fqn region = Fqn.fromString("/test-region");
+ protected Fqn fqn = new Fqn(region, "a");
+ // allows the test methods to notify any support threads in subclasses that data is in the cache and the test is about to begin
+ protected CountDownLatch cacheInitialisedLatch;
+
+ protected abstract EvictionPolicyConfigBase getEvictionPolicyConfig();
+
+ @BeforeMethod
+ public void setUp()
+ {
+ cacheInitialisedLatch = new CountDownLatch(1);
+
+ // the LRU policy cfg
+ EvictionPolicyConfigBase cfg = getEvictionPolicyConfig();
+
+ // the region configuration
+ EvictionRegionConfig regionCfg = new EvictionRegionConfig();
+ regionCfg.setRegionFqn(region);
+ regionCfg.setRegionName(region.toString());
+ regionCfg.setEvictionPolicyConfig(cfg);
+
+ // set regions in a list
+ List<EvictionRegionConfig> evictionRegionConfigs = Collections.singletonList(regionCfg);
+
+ // cache-wide
+ EvictionConfig ec = new EvictionConfig();
+ ec.setWakeupIntervalSeconds(1);
+ ec.setEvictionRegionConfigs(evictionRegionConfigs);
+
+ cache = DefaultCacheFactory.getInstance().createCache(false);
+ cache.getConfiguration().setEvictionConfig(ec);
+ }
+
+ @AfterMethod
+ public void tearDown()
+ {
+ cache.stop();
+ }
+
+ @Test(groups = {"functional"})
+ public void testNoMinimumTTL()
+ {
+ cache.start();
+ cache.put(fqn, "k", "v");
+ // in case any waiting threads in subclasses are waiting for the cache to be initialised
+ cacheInitialisedLatch.countDown();
+
+ assert cache.get(fqn, "k") != null : "Node should be in the cache";
+
+ TestingUtil.sleepThread(3000);
+
+ assert cache.get(fqn, "k") == null : "Node should have been evicted";
+ }
+
+ @Test(groups = {"functional"})
+ public void testWithMinimumTTL()
+ {
+ ((EvictionPolicyConfigBase) cache.getConfiguration().getEvictionConfig().getEvictionRegionConfigs().get(0).getEvictionPolicyConfig()).setMinTimeToLiveSeconds(3);
+
+ cache.start();
+ cache.put(fqn, "k", "v");
+ // in case any waiting threads in subclasses are waiting for the cache to be initialised
+ cacheInitialisedLatch.countDown();
+
+ assert cache.get(fqn, "k") != null : "Node should be in the cache";
+
+ TestingUtil.sleepThread(3000);
+
+ assert cache.get(fqn, "k") != null : "Node should still be in cache due to a minTTL of 3 secs";
+
+ // the last cache.get() would have updated the last modified tstamp so we need to wait at least 3 secs (+1 sec maybe for the eviction thread)
+ // to make sure this is evicted.
+
+ TestingUtil.sleepThread(4500);
+
+ assert cache.get(fqn, "k") == null : "Node should have been evicted";
+ }
+
+}
Modified: core/trunk/src/test/resources/log4j.xml
===================================================================
--- core/trunk/src/test/resources/log4j.xml 2007-09-18 16:58:19 UTC (rev 4485)
+++ core/trunk/src/test/resources/log4j.xml 2007-09-19 13:32:27 UTC (rev 4486)
@@ -69,7 +69,7 @@
-->
<category name="org.jboss.cache">
- <priority value="ERROR"/>
+ <priority value="INFO"/>
</category>
<category name="org.jboss.tm">
@@ -86,7 +86,7 @@
<root>
<priority value="ERROR"/>
- <!-- appender-ref ref="CONSOLE"/> -->
+ <appender-ref ref="CONSOLE"/>
<!--<appender-ref ref="FILE"/>-->
</root>
17 years, 1 month
JBoss Cache SVN: r4485 - core/trunk/src/main/java/org/jboss/cache.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-18 12:58:19 -0400 (Tue, 18 Sep 2007)
New Revision: 4485
Modified:
core/trunk/src/main/java/org/jboss/cache/Fqn.java
Log:
JBCACHE-1171
Modified: core/trunk/src/main/java/org/jboss/cache/Fqn.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/Fqn.java 2007-09-18 16:43:17 UTC (rev 4484)
+++ core/trunk/src/main/java/org/jboss/cache/Fqn.java 2007-09-18 16:58:19 UTC (rev 4485)
@@ -107,7 +107,7 @@
* @param names List of names
* @param safe whether this list is referenced externally (safe = false) or not (safe = true).
*/
- protected Fqn(List<E> names, boolean safe)
+ public Fqn(List<E> names, boolean safe)
{
if (names != null)
{
17 years, 1 month
JBoss Cache SVN: r4484 - in core/trunk/src: main/java/org/jboss/cache/interceptors and 3 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-18 12:43:17 -0400 (Tue, 18 Sep 2007)
New Revision: 4484
Added:
core/trunk/src/test/java/org/jboss/cache/invalidation/VersionInconsistencyTest.java
Modified:
core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java
core/trunk/src/main/java/org/jboss/cache/marshall/MethodDeclarations.java
core/trunk/src/main/java/org/jboss/cache/util/Util.java
Log:
JBCACHE-1155
Modified: core/trunk/src/main/java/org/jboss/cache/CacheImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-09-18 03:43:06 UTC (rev 4483)
+++ core/trunk/src/main/java/org/jboss/cache/CacheImpl.java 2007-09-18 16:43:17 UTC (rev 4484)
@@ -2769,26 +2769,64 @@
if (!exists(fqn))
return true;// node does not exist
- boolean create_undo_ops = false;
- boolean sendNodeEvent = false;
- boolean eviction = true;
if (log.isTraceEnabled())
{
log.trace("_evict(" + fqn + ", " + version + ")");
}
+
if (hasChild(fqn))
{
- _removeData(null, fqn, create_undo_ops, sendNodeEvent, eviction, version);
+ _removeData(null, fqn, false, false, true, version);
return false;
}
else
{
- _remove(null, fqn, create_undo_ops, sendNodeEvent, eviction, version);
+ _remove(null, fqn, false, false, true, version);
return true;
}
}
/**
+ * Very much like an evict(), except that regardless of whether there is a child present, this call will never
+ * remove the node from memory - just remove its contents.
+ *
+ * Also, potentially throws a cache exception if data versioning is used and the node in memory has a newer data
+ * version than what is passed in.
+ *
+ * Finally, the data version of the in-memory node is updated to the version being evicted to prevent versions
+ * going out of sync.
+ *
+ * @param fqn
+ * @param versionToInvalidate
+ */
+ public void invalidate(Fqn fqn, DataVersion versionToInvalidate)
+ {
+ Node node = get(fqn); // force interceptor chain, load if necessary from cache loader.
+
+ if (node != null)
+ {
+ _removeData(null, fqn, false, false, true, versionToInvalidate);
+ if (versionToInvalidate != null)
+ {
+ NodeSPI n = peek(fqn, false);
+ n.setVersion(versionToInvalidate);
+ }
+ }
+ else
+ {
+ // if pessimistic locking, just return.
+ if (!configuration.isNodeLockingOptimistic()) return;
+ // create the node we need.
+ Map<K, V> m = Collections.emptyMap();
+ getInvocationContext().getOptionOverrides().setCacheModeLocal(true);
+ put(fqn, m);
+ getInvocationContext().getOptionOverrides().setCacheModeLocal(false);
+ NodeSPI nodeSPI = (NodeSPI) root.getChild(fqn);
+ nodeSPI.setVersion(versionToInvalidate);
+ }
+ }
+
+ /**
* Evicts a key/value pair from a node's attributes. Note that this is <em>local</em>, will not be replicated.
* @param fqn
* @param key
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java 2007-09-18 03:43:06 UTC (rev 4483)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/InvalidationInterceptor.java 2007-09-18 16:43:17 UTC (rev 4484)
@@ -191,9 +191,12 @@
m_invalidations++;
// only propagate version details if we're using explicit versioning.
+ /*
MethodCall call = workspace != null && !workspace.isVersioningImplicit() ?
MethodCallFactory.create(MethodDeclarations.evictVersionedNodeMethodLocal, fqn, workspace.getNode(fqn).getVersion()) :
MethodCallFactory.create(MethodDeclarations.evictNodeMethodLocal, fqn);
+ */
+ MethodCall call = MethodCallFactory.create(MethodDeclarations.invalidateMethodLocal, fqn, (workspace == null ? null : workspace.getNode(fqn).getVersion()));
if (log.isDebugEnabled()) log.debug("Cache [" + cache.getLocalAddress() + "] replicating " + call);
// voila, invalidated!
Modified: core/trunk/src/main/java/org/jboss/cache/marshall/MethodDeclarations.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/marshall/MethodDeclarations.java 2007-09-18 03:43:06 UTC (rev 4483)
+++ core/trunk/src/main/java/org/jboss/cache/marshall/MethodDeclarations.java 2007-09-18 16:43:17 UTC (rev 4484)
@@ -133,6 +133,8 @@
public static final Method removeDataVersionedMethodLocal;
+ public static final Method invalidateMethodLocal;
+
//not all of these are used for RPC - trim accordingly.
public static final int putDataMethodLocal_id = 1;
@@ -223,7 +225,9 @@
public static final int putForExternalReadVersionedMethodLocal_id = 46;
+ public static final int invalidateMethodLocal_id = 47;
+
static
{
try
@@ -289,6 +293,8 @@
removeKeyVersionedMethodLocal = CacheImpl.class.getDeclaredMethod("_remove", GlobalTransaction.class, Fqn.class, Object.class, boolean.class, DataVersion.class);
removeDataVersionedMethodLocal = CacheImpl.class.getDeclaredMethod("_removeData", GlobalTransaction.class, Fqn.class, boolean.class, DataVersion.class);
+ invalidateMethodLocal = CacheImpl.class.getDeclaredMethod("invalidate", Fqn.class, DataVersion.class);
+
}
catch (NoSuchMethodException e)
{
@@ -342,6 +348,8 @@
methods.put(putForExternalReadVersionedMethodLocal_id, putForExternalReadVersionedMethodLocal);
methods.put(putForExternalReadMethodLocal_id, putForExternalReadMethodLocal);
+ methods.put(invalidateMethodLocal_id, invalidateMethodLocal);
+
for (Integer id : methods.keySet())
{
methodIds.put(methods.get(id), id);
Modified: core/trunk/src/main/java/org/jboss/cache/util/Util.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/Util.java 2007-09-18 03:43:06 UTC (rev 4483)
+++ core/trunk/src/main/java/org/jboss/cache/util/Util.java 2007-09-18 16:43:17 UTC (rev 4484)
@@ -60,9 +60,9 @@
}
/**
- * Calculates the diffs between data maps passed in to {@link org.jboss.cache.CacheListener#nodeModified(org.jboss.cache.Fqn,boolean,boolean,org.jboss.cache.CacheListener.ModificationType,java.util.Map)}
- * before and after modification. This only makes sense if the modification type is {@link org.jboss.cache.CacheListener.ModificationType#PUT_MAP}.
- * Refer to {@link org.jboss.cache.CacheListener#nodeModified(org.jboss.cache.Fqn,boolean,boolean,org.jboss.cache.CacheListener.ModificationType,Map)}.
+ * Calculates the diffs between data maps passed in to {@link org.jboss.cache.notifications.event.NodeModifiedEvent#getData()}
+ * before and after modification. This only makes sense if the modification type is {@link org.jboss.cache.notifications.event.NodeModifiedEvent.ModificationType#PUT_MAP}.
+ * Refer to {@link org.jboss.cache.notifications.event.NodeModifiedEvent} and {@link org.jboss.cache.notifications.annotation.NodeModified}.
*
* @param pre map of data before the node was modified
* @param post Map of data after the node was modified
Added: core/trunk/src/test/java/org/jboss/cache/invalidation/VersionInconsistencyTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/invalidation/VersionInconsistencyTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/invalidation/VersionInconsistencyTest.java 2007-09-18 16:43:17 UTC (rev 4484)
@@ -0,0 +1,97 @@
+package org.jboss.cache.invalidation;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.AfterTest;
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.NodeSPI;
+import org.jboss.cache.optimistic.DefaultDataVersion;
+import org.jboss.cache.misc.TestingUtil;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
+import org.jboss.cache.config.Configuration;
+
+import javax.transaction.TransactionManager;
+import javax.transaction.Transaction;
+
+/**
+ * This test simulates the problem described in JBCACHE-1155
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ * @since 2.1.0
+ */
+@Test(groups = {"functional"})
+public class VersionInconsistencyTest
+{
+ private Cache cache1, cache2;
+ private TransactionManager tm1, tm2;
+ private Fqn node = Fqn.fromString("/a");
+
+ @BeforeTest
+ public void setUp()
+ {
+ cache1 = DefaultCacheFactory.getInstance().createCache(false);
+ cache2 = DefaultCacheFactory.getInstance().createCache(false);
+
+ cache1.getConfiguration().setCacheMode(Configuration.CacheMode.INVALIDATION_SYNC);
+ cache2.getConfiguration().setCacheMode(Configuration.CacheMode.INVALIDATION_SYNC);
+
+ cache1.getConfiguration().setNodeLockingScheme(Configuration.NodeLockingScheme.OPTIMISTIC);
+ cache2.getConfiguration().setNodeLockingScheme(Configuration.NodeLockingScheme.OPTIMISTIC);
+
+ cache1.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache2.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+
+ cache1.start();
+ cache2.start();
+
+ tm1 = cache1.getConfiguration().getRuntimeConfig().getTransactionManager();
+ tm2 = cache2.getConfiguration().getRuntimeConfig().getTransactionManager();
+
+ TestingUtil.blockUntilViewsReceived(1000, cache1, cache2);
+ }
+
+ @AfterTest
+ public void tearDown()
+ {
+ cache1.stop();
+ cache2.stop();
+ }
+
+ public void dataInconsistency() throws Exception
+ {
+ tm1.begin();
+ cache1.put(node, "k", "v-older");
+ Transaction t1 = tm1.suspend();
+
+ tm2.begin();
+ cache2.put(node, "k", "v-newer");
+ tm2.commit();
+
+ tm1.resume(t1);
+ try
+ {
+ tm1.commit();
+ assert false : "Should not be allowed to commit with older data!!";
+ }
+ catch (Exception good)
+ {
+ }
+
+ // the NEWER version of the data should be available, not the OLDER one.
+
+ Object val = cache1.get(node, "k");
+ System.out.println("val = " + val);
+ assert val == null : "Older data should not have committed";
+
+ val = cache2.get(node, "k");
+ System.out.println("val = " + val);
+ assert val.equals("v-newer");
+
+ // test node versions
+ NodeSPI n = (NodeSPI) cache1.getRoot().getChild(node);
+ assert ((DefaultDataVersion) n.getVersion()).getRawVersion() == 1 : "Version should be 1";
+ }
+}
17 years, 1 month
JBoss Cache SVN: r4483 - in core/trunk/src: test/java/org/jboss/cache/jmx and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2007-09-17 23:43:06 -0400 (Mon, 17 Sep 2007)
New Revision: 4483
Modified:
core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java
core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapperMBean.java
core/trunk/src/test/java/org/jboss/cache/jmx/CacheJmxWrapperTest.java
Log:
[JBCACHE-1181] Expose voluminous details via "printXXX" operations, not attributes
Modified: core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java 2007-09-18 03:26:48 UTC (rev 4482)
+++ core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapper.java 2007-09-18 03:43:06 UTC (rev 4483)
@@ -126,24 +126,24 @@
return cfg;
}
- public String getConfigurationAsString()
+ public String printConfigurationAsString()
{
Configuration cfg = getConfiguration();
return cfg == null ? "Configuration is null" : cfg.toString();
}
- public String getConfigurationAsHtmlString()
+ public String printConfigurationAsHtmlString()
{
Configuration cfg = getConfiguration();
return cfg == null ? "Configuration is null" : formatHtml(cfg.toString());
}
- public String getCacheDetails()
+ public String printCacheDetails()
{
return cache == null ? "Cache is null" : cache.printDetails();
}
- public String getCacheDetailsAsHtml()
+ public String printCacheDetailsAsHtml()
{
return cache == null ? "Cache is null" : formatHtml(cache.printDetails());
}
@@ -199,12 +199,12 @@
return cache == null ? -1 : cache.getNumberOfAttributes();
}
- public String getLockInfo()
+ public String printLockInfo()
{
return cache == null ? "Cache is null" : cache.printLockInfo();
}
- public String getLockInfoAsHtml()
+ public String printLockInfoAsHtml()
{
return cache == null ? "Cache is null" : formatHtml(cache.printLockInfo());
}
Modified: core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapperMBean.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapperMBean.java 2007-09-18 03:26:48 UTC (rev 4482)
+++ core/trunk/src/main/java/org/jboss/cache/jmx/CacheJmxWrapperMBean.java 2007-09-18 03:43:06 UTC (rev 4483)
@@ -85,22 +85,22 @@
/**
* @return a string based representation of the configuration
*/
- String getConfigurationAsString();
+ String printConfigurationAsString();
/**
* @return an HTML formatted string based representation of the configuration
*/
- String getConfigurationAsHtmlString();
+ String printConfigurationAsHtmlString();
/**
* @return details of nodes in the cache
*/
- String getCacheDetails();
+ String printCacheDetails();
/**
* @return details of nodes in the cache, formatted as HTML
*/
- String getCacheDetailsAsHtml();
+ String printCacheDetailsAsHtml();
/**
* Returns the local address of this cache in a cluster, or <code>null</code>
@@ -133,12 +133,12 @@
/**
* @return information on the state of node locks
*/
- String getLockInfo();
+ String printLockInfo();
/**
* @return information on the state of node locks, formatted as HTML
*/
- String getLockInfoAsHtml();
+ String printLockInfoAsHtml();
/**
* Gets whether this object should register the cache's interceptors
Modified: core/trunk/src/test/java/org/jboss/cache/jmx/CacheJmxWrapperTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/jmx/CacheJmxWrapperTest.java 2007-09-18 03:26:48 UTC (rev 4482)
+++ core/trunk/src/test/java/org/jboss/cache/jmx/CacheJmxWrapperTest.java 2007-09-18 03:43:06 UTC (rev 4483)
@@ -118,10 +118,10 @@
*
* @throws Exception
*/
- public void testGetConfigurationAsString1() throws Exception
+ public void testPrintConfigurationAsString1() throws Exception
{
CacheJmxWrapperMBean<String, String> wrapper = registerWrapper();
- String cfgFromJmx = wrapper.getConfigurationAsString();
+ String cfgFromJmx = wrapper.printConfigurationAsString();
assertEquals(cache.getConfiguration().toString(), cfgFromJmx);
}
@@ -133,13 +133,13 @@
*
* @throws Exception
*/
- public void testGetConfigurationAsString2() throws Exception
+ public void testPrintConfigurationAsString2() throws Exception
{
Configuration cfg = createConfiguration();
CacheJmxWrapperMBean<String, String> wrapper = registerWrapper(cfg);
wrapper.create();
wrapper.start();
- String cfgFromJmx = wrapper.getConfigurationAsString();
+ String cfgFromJmx = wrapper.printConfigurationAsString();
assertEquals(wrapper.getCache().getConfiguration().toString(), cfgFromJmx);
}
@@ -152,10 +152,10 @@
*
* @throws Exception
*/
- public void testGetConfigurationAsHtml1() throws Exception
+ public void testPrintConfigurationAsHtml1() throws Exception
{
CacheJmxWrapperMBean<String, String> wrapper = registerWrapper();
- String cfgFromJmx = wrapper.getConfigurationAsHtmlString();
+ String cfgFromJmx = wrapper.printConfigurationAsHtmlString();
assertEquals(CacheJmxWrapper.formatHtml(cache.getConfiguration().toString()), cfgFromJmx);
checkHtml(cfgFromJmx, false);
}
@@ -169,13 +169,13 @@
*
* @throws Exception
*/
- public void testGetConfigurationAsHtml2() throws Exception
+ public void testPrintConfigurationAsHtml2() throws Exception
{
Configuration cfg = createConfiguration();
CacheJmxWrapperMBean<String, String> wrapper = registerWrapper(cfg);
wrapper.create();
wrapper.start();
- String cfgFromJmx = wrapper.getConfigurationAsHtmlString();
+ String cfgFromJmx = wrapper.printConfigurationAsHtmlString();
assertEquals(CacheJmxWrapper.formatHtml(wrapper.getCache().getConfiguration().toString()), cfgFromJmx);
checkHtml(cfgFromJmx, false);
}
@@ -198,9 +198,9 @@
assertEquals("value", cacheJmx.get(fqn, "key"));
}
- public void testGetCacheDetails() throws Exception
+ public void testPrintCacheDetails() throws Exception
{
- getCacheDetailsTest(false);
+ printCacheDetailsTest(false);
}
/**
@@ -211,15 +211,15 @@
*
* @throws Exception
*/
- public void testGetCacheDetailsAsHtml() throws Exception
+ public void testPrintCacheDetailsAsHtml() throws Exception
{
- String html = getCacheDetailsTest(true);
+ String html = printCacheDetailsTest(true);
checkHtml(html, true);
}
- public void testGetLockInfo() throws Exception
+ public void testPrintLockInfo() throws Exception
{
- getLockInfoTest(false);
+ printLockInfoTest(false);
}
/**
@@ -230,9 +230,9 @@
*
* @throws Exception
*/
- public void testGetLockInfoAsHtml() throws Exception
+ public void testPrintLockInfoAsHtml() throws Exception
{
- getLockInfoTest(true);
+ printLockInfoTest(true);
}
public void testGetLocalAddress() throws Exception
@@ -289,10 +289,10 @@
assertTrue(cache.getNumberOfNodes() > 0);
assertEquals(0, cache.getNumberOfAttributes());
- System.out.println("cache locks before restart:\n" + cache.getLockInfo());
+ System.out.println("cache locks before restart:\n" + cache.printLockInfo());
cache.destroy();
cache.start();
- System.out.println("cache locks after restart:\n" + cache.getLockInfo());
+ System.out.println("cache locks after restart:\n" + cache.printLockInfo());
assertEquals(0, cache.getNumberOfNodes());
assertEquals(0, cache.getNumberOfAttributes());
@@ -359,7 +359,7 @@
assertEquals("Correct state", CacheStatus.DESTROYED, wrapper.getCacheStatus());
}
- private String getCacheDetailsTest(boolean html) throws Exception
+ private String printCacheDetailsTest(boolean html) throws Exception
{
CacheJmxWrapperMBean<String, String> wrapper = registerWrapper();
@@ -370,7 +370,7 @@
assertEquals("barfoo", cache.get(fqn, "foobar"));
- String details = html ? wrapper.getCacheDetailsAsHtml() : wrapper.getCacheDetails();
+ String details = html ? wrapper.printCacheDetailsAsHtml() : wrapper.printCacheDetails();
assertTrue("Details include testing", details.contains("testing"));
assertTrue("Details include jmx", details.contains("jmx"));
@@ -380,7 +380,7 @@
return details;
}
- private String getLockInfoTest(boolean html) throws Exception
+ private String printLockInfoTest(boolean html) throws Exception
{
Configuration config = createConfiguration();
config.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
@@ -400,7 +400,7 @@
Fqn fqn = Fqn.fromString("/testing/jmx");
cache.put(fqn, "foobar", "barfoo");
- String locks = html ? wrapper.getLockInfoAsHtml() : wrapper.getLockInfo();
+ String locks = html ? wrapper.printLockInfoAsHtml() : wrapper.printLockInfo();
assertTrue("Details include testing", locks.contains("testing"));
assertTrue("Details include jmx", locks.contains("jmx"));
17 years, 1 month
JBoss Cache SVN: r4482 - core/trunk/src/test/java/org/jboss/cache/options.
by jbosscache-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2007-09-17 23:26:48 -0400 (Mon, 17 Sep 2007)
New Revision: 4482
Added:
core/trunk/src/test/java/org/jboss/cache/options/LockAcquisitionTimeoutTest.java
Log:
[JBCACHE-1178] Option to set lock timeout
Added: core/trunk/src/test/java/org/jboss/cache/options/LockAcquisitionTimeoutTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/options/LockAcquisitionTimeoutTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/options/LockAcquisitionTimeoutTest.java 2007-09-18 03:26:48 UTC (rev 4482)
@@ -0,0 +1,371 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.options;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNotNull;
+import static org.testng.AssertJUnit.assertNull;
+import static org.testng.AssertJUnit.fail;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.lock.TimeoutException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Test functionality of {@link Option#setLockAcquisitionTimeout(int)}.
+ *
+ * @author Brian Stansberry
+ */
+@Test(groups = {"functional"})
+public class LockAcquisitionTimeoutTest
+{
+ private static final Log log = LogFactory.getLog(LockAcquisitionTimeoutTest.class);
+
+ private static final Fqn FQNA = Fqn.fromString("/A");
+ private static final Fqn FQNB = Fqn.fromString("/B");
+ private static final String KEY = "key";
+ private static final String VALUE1 = "value1";
+ private static final String VALUE2 = "value2";
+
+ private CacheImpl<Object, Object> cache;
+ private Option option;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ cache = (CacheImpl<Object, Object>)DefaultCacheFactory.getInstance().createCache(false);
+ Configuration c = new Configuration();
+ cache.setConfiguration(c);
+ c.setCacheMode("REPL_SYNC");
+ c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
+
+ cache.start();
+
+ option = new Option();
+ option.setLockAcquisitionTimeout(0);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ if (cache != null)
+ {
+ cache.stop();
+ cache = null;
+ }
+ }
+
+ /**
+ * Confirms that doing a put with a lockAcquisitionTime option set
+ * does the put as expected. There is no other thread or tx contesting
+ * the lock the put needs, so this is just a simple test that the option
+ * doesn't somehow screw up the put.
+ *
+ * @throws Exception
+ */
+ public void testSimplePut() throws Exception
+ {
+ log.info("++++ testSimplePut() ++++");
+ simplePutTest(false);
+ }
+
+ /**
+ * Confirms that doing a put with a lockAcquisitionTime option set
+ * does the put as expected when executed within a transaction. There is no
+ * other thread or tx contesting the lock the put needs, so this is just a
+ * simple test that the option doesn't somehow screw up the put.
+ *
+ * @throws Exception
+ */
+ public void testSimplePutWithTx() throws Exception
+ {
+ log.info("++++ testSimplePutWithTx() ++++");
+ simplePutTest(true);
+ }
+
+ private void simplePutTest(boolean useTx) throws Exception
+ {
+ TransactionManager tm = useTx ? cache.getTransactionManager() : null;
+ LowTimeoutSetter setter = new LowTimeoutSetter(tm);
+ setter.start();
+
+ setter.join(2000);
+ if (!setter.finished)
+ {
+ setter.interrupt();
+ fail("Puts failed to complete in a timely manner");
+ }
+
+ assertNull("LowTimeoutSetter saw no TimeoutException", setter.te);
+ assertNull("LowTimeoutSetter saw no misc Exception", setter.failure);
+ assertEquals("Cache correct for " + FQNA, VALUE2, cache.get(FQNA, KEY));
+ assertEquals("Cache correct for " + FQNB, VALUE2, cache.get(FQNB, KEY));
+ }
+
+ /**
+ * Confirms that a put with a lockAcquisitionTimeout option set to zero
+ * fails promptly in the presence of a lock on the target node.
+ *
+ * @throws Exception
+ */
+ public void testContestedPut() throws Exception
+ {
+ log.info("++++ testContestedPut() ++++");
+ contestedPutTest(false);
+ }
+
+ /**
+ * Confirms that a put with a lockAcquisitionTimeout option set to zero
+ * is ignored if executed within a transaction.
+ *
+ * @throws Exception
+ */
+ public void testContestedPutWithTx() throws Exception
+ {
+ log.info("++++ testContestedPutWithTx() ++++");
+ contestedPutTest(true);
+ }
+
+ private void contestedPutTest(boolean tx) throws Exception
+ {
+ TransactionManager mgr = cache.getTransactionManager();
+ mgr.begin();
+
+ LowTimeoutSetter setter = null;
+ try
+ {
+ // Put a WL on /A
+ cache.put(FQNA, KEY, VALUE1);
+
+ // Launch a thread that tries to write to /A
+ setter = new LowTimeoutSetter(tx ? mgr : null);
+ setter.start();
+
+ setter.join(2000);
+ if (!setter.finished)
+ {
+ setter.interrupt();
+ fail("Puts failed to complete in a timely manner");
+ }
+ }
+ finally
+ {
+ // always commit the tx
+ mgr.commit();
+ }
+
+ assertNotNull("LowTimeoutSetter saw TimeoutException", setter.te);
+ assertNull("LowTimeoutSetter saw no misc Exception", setter.failure);
+ assertEquals("Cache correct for " + FQNA, VALUE1, cache.get(FQNA, KEY));
+ assertEquals("Cache correct for " + FQNB, VALUE2, cache.get(FQNB, KEY));
+
+ }
+
+ public void testSimpleRead() throws Exception
+ {
+ log.info("++++++ testSimpleRead() ++++++");
+ simpleReadTest(false);
+ }
+
+ public void testSimpleReadWithTx() throws Exception
+ {
+ log.info("++++++ testSimpleReadWithTx() ++++++");
+ simpleReadTest(true);
+ }
+
+ private void simpleReadTest(boolean useTx) throws Exception
+ {
+ TransactionManager tm = useTx ? cache.getTransactionManager() : null;
+ LowTimeoutReader reader = new LowTimeoutReader(tm);
+
+ cache.put(FQNA, KEY, VALUE1);
+
+ reader.start();
+
+ reader.join(2000);
+ if (!reader.finished)
+ {
+ reader.interrupt();
+ fail("Read failed to complete in a timely manner");
+ }
+
+ assertNull("LowTimeoutSetter saw no TimeoutException", reader.te);
+ assertNull("LowTimeoutSetter saw no misc Exception", reader.failure);
+ assertEquals("LowTimeoutSetter correct for " + FQNA, VALUE1, reader.value);
+
+ }
+
+ public void testContestedRead() throws Exception
+ {
+ log.info("++++++ testContestedRead() ++++++");
+ contestedReadTest(false);
+ }
+
+ public void testContestedReadWithTx() throws Exception
+ {
+ log.info("++++++ testContestedReadWithTx() ++++++");
+ contestedReadTest(true);
+ }
+
+ private void contestedReadTest(boolean tx) throws Exception
+ {
+ TransactionManager mgr = cache.getTransactionManager();
+ mgr.begin();
+
+ LowTimeoutReader reader = null;
+ try
+ {
+ // Put a WL on /A
+ cache.put(FQNA, KEY, VALUE1);
+
+ // Launch a thread that tries to read from /A
+ reader = new LowTimeoutReader(tx ? mgr : null);
+ reader.start();
+
+ reader.join(2000);
+ if (!reader.finished)
+ {
+ reader.interrupt();
+ fail("Read failed to complete in a timely manner");
+ }
+ }
+ finally
+ {
+ // always commit the tx
+ mgr.commit();
+ }
+
+ assertNotNull("LowTimeoutSetter saw TimeoutException", reader.te);
+ assertNull("LowTimeoutSetter saw no misc Exception", reader.failure);
+ assertNull("LowTimeoutSetter unable to read " + FQNA, reader.value);
+
+ }
+
+ class LowTimeoutSetter extends Thread
+ {
+ TransactionManager tm;
+ TimeoutException te;
+ Throwable failure;
+ boolean finished;
+
+ LowTimeoutSetter(TransactionManager tm)
+ {
+ this.tm = tm;
+ }
+
+ public void run()
+ {
+ try
+ {
+ Transaction tx = null;
+
+ try
+ {
+ if (tm != null)
+ {
+ tm.begin();
+ tx = tm.getTransaction();
+ }
+
+ cache.put(FQNB, KEY, VALUE2);
+
+ cache.getInvocationContext().setOptionOverrides(option);
+ cache.put(FQNA, KEY, VALUE2);
+ }
+ catch (TimeoutException te)
+ {
+ this.te = te;
+ }
+ catch (Exception e)
+ {
+ if (tx != null)
+ tx.setRollbackOnly();
+ throw e;
+ }
+ finally
+ {
+ if (tx != null)
+ {
+ tx.commit();
+ }
+ finished = true;
+ }
+ }
+ catch (Throwable t)
+ {
+ failure = t;
+ }
+ }
+ }
+
+ class LowTimeoutReader extends Thread
+ {
+ TransactionManager tm;
+ TimeoutException te;
+ Throwable failure;
+ Object value;
+ boolean finished;
+
+ LowTimeoutReader(TransactionManager tm)
+ {
+ this.tm = tm;
+ }
+
+ public void run()
+ {
+ try
+ {
+ Transaction tx = null;
+
+ try
+ {
+ if (tm != null)
+ {
+ tm.begin();
+ tx = tm.getTransaction();
+ }
+
+ cache.getInvocationContext().setOptionOverrides(option);
+ value = cache.get(FQNA, KEY);
+ }
+ catch (TimeoutException te)
+ {
+ this.te = te;
+ }
+ catch (Exception e)
+ {
+ if (tx != null)
+ tx.setRollbackOnly();
+ throw e;
+ }
+ finally
+ {
+ if (tx != null)
+ {
+ tx.commit();
+ }
+ finished = true;
+ }
+ }
+ catch (Throwable t)
+ {
+ failure = t;
+ }
+ }
+ }
+}
Property changes on: core/trunk/src/test/java/org/jboss/cache/options/LockAcquisitionTimeoutTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
17 years, 1 month
JBoss Cache SVN: r4481 - core/trunk/src/main/java/org/jboss/cache/interceptors.
by jbosscache-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2007-09-17 23:26:11 -0400 (Mon, 17 Sep 2007)
New Revision: 4481
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java
core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
Log:
[JBCACHE-1178] Option to set lock timeout
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java 2007-09-18 03:25:32 UTC (rev 4480)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/OptimisticLockingInterceptor.java 2007-09-18 03:26:11 UTC (rev 4481)
@@ -47,9 +47,15 @@
case MethodDeclarations.optimisticPrepareMethod_id:
//try and acquire the locks - before passing on
GlobalTransaction gtx = getGlobalTransaction(ctx);
+ long timeout = lockAcquisitionTimeout;
+ if (ctx.getOptionOverrides() != null
+ && ctx.getOptionOverrides().getLockAcquisitionTimeout() >= 0)
+ {
+ timeout = ctx.getOptionOverrides().getLockAcquisitionTimeout();
+ }
try
{
- lockNodes(gtx);
+ lockNodes(gtx, timeout);
}
catch (Throwable e)
{
@@ -108,7 +114,7 @@
*
* @param gtx global transaction which contains a workspace
*/
- private void lockNodes(GlobalTransaction gtx) throws InterruptedException
+ private void lockNodes(GlobalTransaction gtx, long timeout) throws InterruptedException
{
TransactionWorkspace<?, ?> workspace = getTransactionWorkspace(gtx);
if (log.isDebugEnabled()) log.debug("Locking nodes in transaction workspace for GlobalTransaction " + gtx);
Modified: core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2007-09-18 03:25:32 UTC (rev 4480)
+++ core/trunk/src/main/java/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2007-09-18 03:26:11 UTC (rev 4481)
@@ -179,9 +179,10 @@
{
if (!locksAlreadyObtained)
{
+ long timeout = zeroLockTimeout ? 0 : getLockAcquisitionTimeout(ctx);
do
{
- lock(ctx, fqn, lock_type, recursive, createIfNotExists, zeroLockTimeout ? 0 : lock_acquisition_timeout, isDeleteOperation, isEvictOperation, isRemoveDataOperation);
+ lock(ctx, fqn, lock_type, recursive, createIfNotExists, timeout, isDeleteOperation, isEvictOperation, isRemoveDataOperation);
}
while (createIfNotExists && cache.peek(fqn, false) == null);// keep trying until we have the lock (fixes concurrent remove())
}
@@ -221,18 +222,32 @@
return o;
}
+ private long getLockAcquisitionTimeout(InvocationContext ctx)
+ {
+ long timeout = lock_acquisition_timeout;
+ if (ctx.getOptionOverrides() != null
+ && ctx.getOptionOverrides().getLockAcquisitionTimeout() >= 0)
+ {
+ timeout = ctx.getOptionOverrides().getLockAcquisitionTimeout();
+ }
+ return timeout;
+ }
+
+
private void obtainLocksForMove(InvocationContext ctx, Fqn node, Fqn parent) throws InterruptedException
{
// parent node (new parent) and current node's existing parent should both get RLs.
// node should have a WL.
+ long timeout = getLockAcquisitionTimeout(ctx);
+
// this call will ensure the node gets a WL and it's current parent gets RL.
if (log.isTraceEnabled()) log.trace("Attempting to get WL on node to be moved [" + node + "]");
- lock(ctx, node, NodeLock.LockType.WRITE, true, false, lock_acquisition_timeout, true, false, false);
+ lock(ctx, node, NodeLock.LockType.WRITE, true, false, timeout, true, false, false);
//now for an RL for the new parent.
if (log.isTraceEnabled()) log.trace("Attempting to get RL on new parent [" + parent + "]");
- lock(ctx, parent, NodeLock.LockType.READ, true, false, lock_acquisition_timeout, false, false, false);
+ lock(ctx, parent, NodeLock.LockType.READ, true, false, timeout, false, false, false);
}
17 years, 1 month
JBoss Cache SVN: r4480 - core/trunk/src/test/java/org/jboss/cache/options.
by jbosscache-commits@lists.jboss.org
Author: bstansberry(a)jboss.com
Date: 2007-09-17 23:25:32 -0400 (Mon, 17 Sep 2007)
New Revision: 4480
Added:
core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java
Log:
[JBCACHE-1175] Option to force call sync/async
Added: core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java 2007-09-18 03:25:32 UTC (rev 4480)
@@ -0,0 +1,489 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.cache.options;
+
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertTrue;
+
+import java.util.concurrent.CountDownLatch;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.config.Configuration.CacheMode;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
+import org.jboss.cache.misc.TestingUtil;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.NodeEvicted;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.NodeRemoved;
+import org.jboss.cache.notifications.event.NodeEvent;
+import org.jboss.cache.notifications.event.NodeEvictedEvent;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests functionality of {@link Option#setForceAsynchronous(boolean)} and
+ * {@link Option#setForceSynchronous(boolean)}.
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani (manik(a)jboss.org)</a>
+ */
+@Test(groups = {"functional"})
+public class ForceCacheModeTest
+{
+ private static final Log log = LogFactory.getLog(ForceCacheModeTest.class);
+
+ private static final Fqn FQNA = Fqn.fromString("/A");
+ private static final String KEY = "key";
+ private static final String VALUE1 = "value1";
+ private static final String VALUE2 = "value2";
+
+ private CacheImpl<Object, Object> cache1, cache2;
+ private Option asyncOption;
+ private Option syncOption;
+ private static CountDownLatch latch;
+ private BlockingListener listener;
+
+ private void createCaches(NodeLockingScheme scheme, CacheMode mode) throws Exception
+ {
+ cache1 = (CacheImpl<Object, Object>)DefaultCacheFactory.getInstance().createCache(false);
+ Configuration c = new Configuration();
+ cache1.setConfiguration(c);
+ c.setNodeLockingScheme(scheme);
+ c.setCacheMode(mode);
+ c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
+
+ cache2 = (CacheImpl<Object, Object>)DefaultCacheFactory.getInstance().createCache(false);
+ c = new Configuration();
+ cache2.setConfiguration(c);
+ c.setNodeLockingScheme(scheme);
+ c.setCacheMode(mode);
+ c.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
+
+ cache1.start();
+ cache2.start();
+
+ asyncOption = new Option();
+ asyncOption.setForceAsynchronous(true);
+
+ syncOption = new Option();
+ syncOption.setForceSynchronous(true);
+
+ Option local = new Option();
+ local.setCacheModeLocal(true);
+
+ cache1.getInvocationContext().setOptionOverrides(local);
+ cache1.put(FQNA, KEY, VALUE1);
+
+ cache2.getInvocationContext().setOptionOverrides(local);
+ cache2.put(FQNA, KEY, VALUE1);
+
+ listener = new BlockingListener();
+ cache2.addCacheListener(listener);
+ }
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ latch = new CountDownLatch(1);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ if (cache1 != null)
+ {
+ cache1.stop();
+ cache1.destroy();
+ cache1 = null;
+ }
+
+ if (cache2 != null)
+ {
+ if (listener != null)
+ cache2.removeCacheListener(listener);
+ cache2.stop();
+ cache2.destroy();
+ cache2 = null;
+ }
+
+ latch.countDown();
+ }
+
+ public void testPessimisticReplicationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testPessimisticReplicationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testPessimisticReplicationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testPessimisticInvalidationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testPessimisticInvalidationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testPessimisticInvalidationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testPessimisticReplicationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testPessimisticReplicationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testPessimisticReplicationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ public void testPessimisticInvalidationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testPessimisticInvalidationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testPessimisticInvalidationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.PESSIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ public void testOptimisticReplicationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testOptimisticReplicationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testOptimisticReplicationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testOptimisticInvalidationPutForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, false);
+ }
+
+ public void testOptimisticInvalidationRemoveForceAsync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkNoBlocking(null, asyncOption, true);
+ }
+
+ public void testOptimisticInvalidationPutForceAsyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_SYNC);
+
+ checkBlocking(cache1.getTransactionManager(), asyncOption, false);
+ }
+
+ public void testOptimisticReplicationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testOptimisticReplicationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testOptimisticReplicationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.REPL_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ public void testOptimisticInvalidationPutForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, false);
+ }
+
+ public void testOptimisticInvalidationRemoveForceSync() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkBlocking(null, syncOption, true);
+ }
+
+ public void testOptimisticInvalidationPutForceSyncWithTx() throws Exception
+ {
+ createCaches(NodeLockingScheme.OPTIMISTIC, CacheMode.INVALIDATION_ASYNC);
+
+ checkNoBlocking(cache1.getTransactionManager(), syncOption, false);
+ }
+
+ /**
+ * Confirms the updater is not blocked and that the cache state is as
+ * expected at the end.
+ *
+ * @param tm transction manager Updater should use. For non-transactional
+ * tests, should be <code>null</code>
+ * @param option Option to set before doing put
+ * @param removeTest true if we're testing a remove; false if a put
+ * @throws InterruptedException
+ * @throws CacheException
+ */
+ private void checkNoBlocking(TransactionManager tm, Option option, boolean removeTest) throws InterruptedException, CacheException
+ {
+ Updater updater = new Updater(tm, option, removeTest);
+ updater.start();
+
+ updater.join(250);
+ assertTrue("Updater finished", updater.finished);
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ assertTrue("Listener blocked", listener.blocked);
+ assertEquals("Cache1 correct", removeTest ? null : VALUE2, cache1.get(FQNA, KEY));
+
+ latch.countDown();
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (!listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ // sleep a bit more to ensure the cache2 thread completes
+ TestingUtil.sleepThread(5);
+ CacheMode mode = cache2.getConfiguration().getCacheMode();
+ boolean expectNull = (removeTest || mode == CacheMode.INVALIDATION_ASYNC || mode == CacheMode.INVALIDATION_SYNC);
+ assertEquals("Cache2 correct", expectNull ? null : VALUE2, cache2.get(FQNA, KEY));
+ }
+
+ /**
+ * Confirms the updater is blocked and that the cache state is as
+ * expected at the end.
+ *
+ * @param tm transction manager Updater should use. For non-transactional
+ * tests, should be <code>null</code>
+ * @param option Option to set before doing put
+ * @param removeTest true if we're testing a remove; false if a put
+ * @throws InterruptedException
+ * @throws CacheException
+ */
+ private void checkBlocking(TransactionManager tm, Option option, boolean removeTest) throws InterruptedException, CacheException
+ {
+ Updater updater = new Updater(tm, option, removeTest);
+ updater.start();
+
+ updater.join(250);
+ assertFalse("Updater blocked", updater.finished);
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ assertTrue("Listener blocked", listener.blocked);
+
+ latch.countDown();
+
+ for (int i = 0; i < 50; i++)
+ {
+ if (updater.finished && !listener.blocked)
+ break;
+ TestingUtil.sleepThread(10);
+ }
+
+ assertEquals("Cache1 correct", removeTest ? null : VALUE2, cache1.get(FQNA, KEY));
+
+ // sleep a bit more to ensure the cache2 thread completes
+ TestingUtil.sleepThread(5);
+ CacheMode mode = cache2.getConfiguration().getCacheMode();
+ boolean expectNull = (removeTest || mode == CacheMode.INVALIDATION_ASYNC || mode == CacheMode.INVALIDATION_SYNC);
+ assertEquals("Cache2 correct", expectNull ? null : VALUE2, cache2.get(FQNA, KEY));
+ }
+
+ class Updater extends Thread
+ {
+ TransactionManager tm;
+ Option option;
+ boolean remove;
+ Throwable failure;
+ boolean finished;
+
+ Updater(TransactionManager tm, Option option)
+ {
+ this(tm, option, false);
+ }
+
+ Updater(TransactionManager tm, Option option, boolean remove)
+ {
+ this.tm = tm;
+ this.option = option;
+ this.remove = remove;
+ }
+
+ public void run()
+ {
+ try
+ {
+ Transaction tx = null;
+
+ try
+ {
+ if (tm != null)
+ {
+ tm.begin();
+ tx = tm.getTransaction();
+ }
+
+ cache1.getInvocationContext().setOptionOverrides(option);
+ if (remove)
+ cache1.remove(FQNA, KEY);
+ else
+ cache1.put(FQNA, KEY, VALUE2);
+ }
+ catch (Exception e)
+ {
+ if (tx != null)
+ tx.setRollbackOnly();
+ throw e;
+ }
+ finally
+ {
+ if (tx != null)
+ {
+ tx.commit();
+ }
+ finished = true;
+ }
+ }
+ catch (Throwable t)
+ {
+ failure = t;
+ }
+ }
+ }
+
+ @CacheListener
+ public static class BlockingListener
+ {
+ boolean blocked;
+
+ @NodeModified
+ public void nodeModified(NodeModifiedEvent event)
+ {
+ block(event);
+ }
+
+ @NodeRemoved
+ public void nodeRemoved(NodeRemovedEvent event)
+ {
+ block(event);
+ }
+
+ @NodeEvicted
+ public void nodeEvicted(NodeEvictedEvent event)
+ {
+ block(event);
+ }
+
+ private void block(NodeEvent event)
+ {
+ if (event.isPre() == false && FQNA.equals(event.getFqn()))
+ {
+ blocked = true;
+ try
+ {
+ latch.await();
+ }
+ catch (InterruptedException e) {}
+
+ blocked = false;
+ }
+ }
+ }
+
+}
Property changes on: core/trunk/src/test/java/org/jboss/cache/options/ForceCacheModeTest.java
___________________________________________________________________
Name: svn:keywords
+ Id Revision
Name: svn:eol-style
+ native
17 years, 1 month