Author: manik.surtani(a)jboss.com
Date: 2007-11-08 10:40:14 -0500 (Thu, 08 Nov 2007)
New Revision: 4740
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
Modified:
core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
core/branches/1.4.X/tests/functional/org/jboss/cache/misc/TestingUtil.java
Log:
JBCACHE-1165 - added test and fixed. No more endless loop and concurrent put/remove
issues with Pessimistic Locking.
Modified:
core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
===================================================================
---
core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2007-11-08
15:20:59 UTC (rev 4739)
+++
core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2007-11-08
15:40:14 UTC (rev 4740)
@@ -118,6 +118,7 @@
fqn = (Fqn) args[1];
lock_type = DataNode.LOCK_TYPE_WRITE;
recursive = true; // remove node and *all* child nodes
+ createIfNotExists = true;
// JBCACHE-871 We need to store the node
storeLockedNode = true;
break;
@@ -308,6 +309,19 @@
// Try to acquire the lock; recording that we did if successful
acquireNodeLock(child_node, owner, gtx, currentLockType, lock_timeout);
+ // make sure the lock we acquired isn't on a deleted node/is an orphan!!
+ DataNode repeek = cache.peek(child_node.getFqn());
+ if (repeek != null && child_node != repeek)
+ {
+ log.trace("Was waiting for and obtained a lock on a node that
doesn't exist anymore! Attempting lock acquisition again.");
+ // we have an orphan!! Lose the unnecessary lock and re-acquire the lock (and
potentially recreate the node).
+ child_node.getLock().release(owner);
+
+ // do the loop again, but don't assign child_node to n so that child_node
is processed again.
+ i--;
+ continue;
+ }
+
if (recursive && isTargetNode(i, treeNodeSize))
{
{
Added:
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
===================================================================
---
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
(rev 0)
+++
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java 2007-11-08
15:40:14 UTC (rev 4740)
@@ -0,0 +1,104 @@
+package org.jboss.cache.lock.pessimistic;
+
+import junit.framework.TestCase;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.cache.misc.TestingUtil;
+
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class ConcurrentPutRemoveTest extends TestCase
+{
+ private TransactionManager tm;
+
+ private TreeCache cache;
+
+ private final Log log = LogFactory.getLog(ConcurrentPutRemoveTest.class);
+ private List threads;
+
+
+ public void setUp() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setIsolationLevel(IsolationLevel.READ_COMMITTED);
+
cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.setLockAcquisitionTimeout(1000);
+ cache.start();
+ tm = cache.getTransactionManager();
+ threads = new ArrayList();
+ }
+
+ public void tearDown() throws Exception
+ {
+ TestingUtil.killCaches(new TreeCache[]{cache});
+ }
+
+ public void testLock() throws Exception
+ {
+ for (int x = 0; x < 2; x++)
+ {
+ SeparateThread t = new SeparateThread(x);
+ threads.add(t);
+ t.start();
+ }
+ for (Iterator i = threads.iterator(); i.hasNext();)
+ {
+ SeparateThread separateThread = (SeparateThread) i.next();
+ separateThread.join();
+ if (separateThread.getException() != null)
+ {
+ throw separateThread.getException();
+ }
+ }
+ }
+
+ private class SeparateThread extends Thread
+ {
+ Exception e = null;
+
+ private int num = 0;
+
+ public SeparateThread(int num)
+ {
+ this.num = num;
+ }
+
+ public Exception getException()
+ {
+ return e;
+ }
+
+ public void run()
+ {
+ Thread.currentThread().setName("Thread:" + num);
+ try
+ {
+ for (int x = 0; x < 100; x++)
+ {
+ tm.begin();
+ log.warn("Before Remove (" + x + ")");
+ //inside transaction
+ cache.remove(Fqn.fromString("/a"));
+ log.warn("After Remove (" + x + ")");
+ tm.commit();
+ //outside transaction
+ log.warn("Before Put (" + x + ")");
+ cache.put(Fqn.fromString("/a/b/c/d"), "text" + x,
"b");
+ log.warn("After Put (" + x + ")");
+ }
+ }
+ catch (Exception e)
+ {
+ this.e = e;
+ }
+ }
+ }
+
+}
Modified: core/branches/1.4.X/tests/functional/org/jboss/cache/misc/TestingUtil.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/misc/TestingUtil.java 2007-11-08
15:20:59 UTC (rev 4739)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/misc/TestingUtil.java 2007-11-08
15:40:14 UTC (rev 4740)
@@ -7,12 +7,13 @@
package org.jboss.cache.misc;
-import java.util.Vector;
-import java.io.File;
-
+import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCache;
import org.jboss.cache.TreeCacheMBean;
+import java.io.File;
+import java.util.Vector;
+
/**
* Utilities for unit testing JBossCache.
*
@@ -23,6 +24,48 @@
{
/**
+ * Kills a cache - stops it, clears any data in any cache loaders, and rolls back any
associated txs
+ */
+ public static void killCaches(TreeCache[] caches)
+ {
+ if (caches == null) return;
+
+ for (int i = 0; i<caches.length; i++)
+ {
+ TreeCache c = caches[i];
+ if (c != null)
+ {
+ if (c.getTransactionManager() != null)
+ {
+ try
+ {
+ c.getTransactionManager().rollback();
+ }
+ catch (Exception e)
+ {
+ // don't care
+ }
+ }
+
+ if (c.getCacheLoader() != null)
+ {
+ try
+ {
+ c.getCacheLoader().remove(Fqn.ROOT);
+ }
+ catch (Exception e)
+ {
+ // don't care
+ }
+ }
+
+ c.stop();
+ c.destroy();
+ }
+ }
+ }
+
+ /**
* Loops, continually calling {@link #areCacheViewsComplete(TreeCache[])}
* until it either returns true or <code>timeout</code> ms have elapsed.
*
Show replies by date