JBoss Cache SVN: r4469 - pojo/trunk.
by jbosscache-commits@lists.jboss.org
Author: jason.greene(a)jboss.com
Date: 2007-09-17 13:30:49 -0400 (Mon, 17 Sep 2007)
New Revision: 4469
Modified:
pojo/trunk/pom.xml
Log:
Fix javadoc task
Modified: pojo/trunk/pom.xml
===================================================================
--- pojo/trunk/pom.xml 2007-09-17 17:28:32 UTC (rev 4468)
+++ pojo/trunk/pom.xml 2007-09-17 17:30:49 UTC (rev 4469)
@@ -33,6 +33,7 @@
<artifactId>jbosscache-core</artifactId>
<version>2.1.0-SNAPSHOT</version>
<type>test-jar</type>
+ <scope>test</scope>
</dependency>
</dependencies>
<build>
17 years, 2 months
JBoss Cache SVN: r4468 - core/trunk.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-17 13:28:32 -0400 (Mon, 17 Sep 2007)
New Revision: 4468
Modified:
core/trunk/pom.xml
Log:
JBCACHE-1127 and removed MC/AOP deps
Modified: core/trunk/pom.xml
===================================================================
--- core/trunk/pom.xml 2007-09-17 14:14:07 UTC (rev 4467)
+++ core/trunk/pom.xml 2007-09-17 17:28:32 UTC (rev 4468)
@@ -54,15 +54,10 @@
<version>2.0b4</version>
</dependency>
<dependency>
- <groupId>jboss</groupId>
- <artifactId>jboss-j2ee</artifactId>
- <version>4.2.0.GA</version>
+ <groupId>org.jboss.javaee</groupId>
+ <artifactId>jboss-javaee</artifactId>
+ <version>4.0.0.Beta3</version>
</dependency>
- <dependency>
- <groupId>org.jboss.microcontainer</groupId>
- <artifactId>jboss-aop-mc-int</artifactId>
- <version>2.0.0-SNAPSHOT</version>
- </dependency>
<!-- test dependencies -->
<dependency>
<groupId>org.easymock</groupId>
17 years, 2 months
JBoss Cache SVN: r4467 - pojo/trunk.
by jbosscache-commits@lists.jboss.org
Author: jason.greene(a)jboss.com
Date: 2007-09-17 10:14:07 -0400 (Mon, 17 Sep 2007)
New Revision: 4467
Modified:
pojo/trunk/pom.xml
Log:
fully qualify path to aop file
Modified: pojo/trunk/pom.xml
===================================================================
--- pojo/trunk/pom.xml 2007-09-17 13:23:30 UTC (rev 4466)
+++ pojo/trunk/pom.xml 2007-09-17 14:14:07 UTC (rev 4467)
@@ -77,7 +77,7 @@
</systemProperties>
<groups>functional</groups>
<forkMode>always</forkMode>
- <argLine>-Djboss.aop.path=src/main/resources/META-INF/pojocache-aop.xml -javaagent:${settings.localRepository}/org/jboss/aop/jboss-aop/2.0.0-SNAPSHOT/jboss-aop-2.0.0-SNAPSHOT.jar</argLine>
+ <argLine>-Djboss.aop.path=${basedir}/src/main/resources/META-INF/pojocache-aop.xml -javaagent:${settings.localRepository}/org/jboss/aop/jboss-aop/2.0.0-SNAPSHOT/jboss-aop-2.0.0-SNAPSHOT.jar</argLine>
<!-- Warning, this does not work right on 2.4-SNAPSHOT, (see SUREFIRE-349) -->
<!-- This seems to fail in some cases on 2.3 as well, disable for now -->
<useSystemClassLoader>true</useSystemClassLoader>
@@ -97,7 +97,7 @@
</goals>
<configuration>
<verbose>false</verbose>
- <aoppath>src/main/resources/META-INF/pojocache-aop.xml</aoppath>
+ <aoppath>${basedir}/src/main/resources/META-INF/pojocache-aop.xml</aoppath>
</configuration>
</execution>
</executions>
17 years, 2 months
JBoss Cache SVN: r4466 - in core/branches/1.4.X: tests/functional/org/jboss/cache/lock/pessimistic and 1 other directory.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-17 09:23:30 -0400 (Mon, 17 Sep 2007)
New Revision: 4466
Removed:
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
Modified:
core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
Log:
Fixes for JBCACHE-1165, JBCACHE-1166, JBCACHE-1168, JBCACHE-1164, JBCACHE-1183
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-09-17 13:14:29 UTC (rev 4465)
+++ core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2007-09-17 13:23:30 UTC (rev 4466)
@@ -173,7 +173,7 @@
// If no TX: add each acquired lock to the list of locks for this method (locks)
// If TX: [merge code from TransactionInterceptor]: register with TxManager, on commit/rollback,
// release the locks for the given TX
- if (fqn != null)
+ /*if (fqn != null)
{
// limit the time spent in the loop attempting to acquire locks.
long startTime = System.currentTimeMillis();
@@ -218,7 +218,67 @@
{
if (log.isTraceEnabled())
log.trace("bypassed locking as method " + m.getName() + "() doesn't require locking");
+ }*/
+
+
+ if (fqn != null)
+ {
+ long startTime = System.currentTimeMillis();//we can;t spend in this loop more than lock_timeout!
+ if (createIfNotExists)
+ {
+ boolean finish = false;
+ do
+ {
+ if (!zeroLockTimeout && (System.currentTimeMillis()-startTime>lock_timeout)){
+ String msg = "PessimicticLockInterceptor can't acquire lock after ["+lock_timeout+"] ms.";
+ log.error(msg);
+ throw new TimeoutException(msg);
+ }
+ DataNode lockedNode = lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, zeroLockTimeout ? 0 : lock_timeout, createIfNotExists, storeLockedNode, isRemoveData);
+ DataNode dataNode = getNodeFromCache(fqn,ctx.getGlobalTransaction());
+ finish = dataNode!=null;
+ if (finish && lockedNode!=null){
+ if (dataNode!=lockedNode){
+ finish = false;
+ log.trace("Lock was acquired but node changed (createIfNotExists=true)");
+ }
+ }
+ }
+ while(!finish); // keep trying until we have the lock (fixes concurrent remove())
+ // terminates successfully, or with (Timeout)Exception
+ }
+ else{
+ boolean finish = false;
+ do
+ {
+ if (!zeroLockTimeout && (System.currentTimeMillis()-startTime>lock_timeout)){
+ String msg = "PessimicticLockInterceptor can't acquire lock after ["+lock_timeout+"] ms";
+ log.error(msg);
+ throw new TimeoutException(msg);
+ }
+ DataNode lockedNode = lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, zeroLockTimeout ? 0 : lock_timeout, createIfNotExists, storeLockedNode, isRemoveData);
+ if (lockedNode!=null){
+ DataNode dataNode = getNodeFromCache(fqn,ctx.getGlobalTransaction());
+ if (dataNode!=lockedNode){
+ finish = false;
+ log.trace("Lock was acquired but node changed (createIfNotExists=false)");
+ }else{
+ finish=true;
+ }
+ }else{
+ finish = true;
+ }
+ }
+ while(!finish); // keep trying until we have the lock (fixes concurrent remove())
+ }
}
+ else
+ {
+ if (log.isTraceEnabled())
+ log.trace("bypassed locking as method " + m.getName() + "() doesn't require locking");
+ }
+
+
if (m.getMethodId() == MethodDeclarations.lockMethodLocal_id)
return null;
Deleted: core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java 2007-09-17 13:14:29 UTC (rev 4465)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java 2007-09-17 13:23:30 UTC (rev 4466)
@@ -1,175 +0,0 @@
-package org.jboss.cache.lock.pessimistic;
-
-import junit.framework.TestCase;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.DummyTransactionManagerLookup;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Node;
-import org.jboss.cache.TreeCache;
-import org.jboss.cache.lock.IsolationLevel;
-
-import javax.transaction.TransactionManager;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-
-public class LockNotReleasedTest extends TestCase
-{
- Random rand = new Random(System.currentTimeMillis());
-
- private TransactionManager tm;
-
- private TreeCache cache;
-
- private void startTest() throws Exception
- {
- cache = new TreeCache();
- cache.setCacheMode(TreeCache.LOCAL);
- cache.setIsolationLevel(IsolationLevel.READ_COMMITTED);
- cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
- cache.setLockAcquisitionTimeout(1000);
- cache.create();
- cache.start();
- tm = cache.getTransactionManager();
- }
-
- public void tearDown() throws Exception
- {
- cache.stop();
- cache.destroy();
- }
-
-
- public int getNumberOfLocksHeld()
- {
- return numLocks((Node) cache.getRoot());
- }
-
- private int numLocks(Node n)
- {
- int num = 0;
- Map children;
-
- if (n.getLock().isLocked())
- {
- num++;
- System.out.println("Node [" + n.getFqn() + "] is locked");
- }
- if ((children = n.getChildren(true)) != null)
- {
- for (Iterator i = children.values().iterator(); i.hasNext();)
- {
- num += numLocks((Node) i.next());
- }
- }
- return num;
- }
-
- public void testTransactionStorm() throws Exception
- {
- startTest();
- List threads = new ArrayList();
-// System.out.println(cache.getNumberOfLocksHeld());
- assertEquals(0, getNumberOfLocksHeld());
- while (true)
- {
- for (int x = 0; x < 2; x++)
- {
- WorkThread t = new WorkThread(x == 1);
- threads.add(t);
- t.start();
- }
- for (Iterator i = threads.iterator(); i.hasNext();)
- {
- WorkThread separateThread = (WorkThread) i.next();
- separateThread.join();
- if (separateThread.getException() != null)
- {
- //separateThread.getException().getMessage();
- }
- }
- int locksNum = getNumberOfLocksHeld();
-// System.out.println("Locks="+locksNum);
- // checkpoint
- if (cache.getNumberOfLocksHeld() > 0)
- {
- System.out.println("ERROR, locks=" + locksNum);
- doDomethingOnCache(1);
- }
- assertEquals(0, locksNum);
- }
-
- }
-
- private class WorkThread extends Thread
- {
- Exception e = null;
-
- private boolean remove;
-
- public WorkThread(boolean remove)
- {
- this.remove = remove;
- }
-
- public Exception getException()
- {
- return e;
- }
-
- public void run()
- {
- try
- {
- for (int x = 0; x < 100; x++)
- {
- tm.begin();
- try
- {
- doDomethingOnCache(x);
- }
- finally
- {
- if (x % 3 == 0)
- {
- tm.commit();
- }
- else
- {
- tm.rollback();
- }
- }
- }
- }
- catch (Exception e)
- {
-// System.out.println(e.getMessage());
- this.e = e;
- }
- }
-
- }
-
- private void doDomethingOnCache(int x) throws CacheException, InterruptedException
- {
- cache.put(Fqn.fromString("/a/b/c/a"), "text1" + x, "");
- cache.remove(Fqn.fromString("/q/b/c/d"));
- cache.put(Fqn.fromString("/a/b/c/b"), "text2" + x, "");
- cache.remove(Fqn.fromString("/q/b/c/c"));
- cache.put(Fqn.fromString("/a/b/c/c"), "text3" + x, "");
- cache.remove(Fqn.fromString("/q/b/c/b"));
- cache.put(Fqn.fromString("/a/b/c/d"), "text4" + x, "");
- cache.remove(Fqn.fromString("/q/b/c/a"));
- cache.put(Fqn.fromString("/q/b/c/a"), "text5" + x, "");
- cache.remove(Fqn.fromString("/a/b/c/d"));
- cache.put(Fqn.fromString("/q/b/c/b"), "text6" + x, "");
- cache.remove(Fqn.fromString("/a/b/c/c"));
- cache.put(Fqn.fromString("/q/b/c/c"), "text7" + x, "");
- cache.remove(Fqn.fromString("/a/b/c/b"));
- cache.put(Fqn.fromString("/q/b/c/d"), "text8" + x, "");
- cache.remove(Fqn.fromString("/a/b/c/a"));
- }
-
-}
17 years, 2 months
JBoss Cache SVN: r4465 - in core/branches/1.4.X: src/org/jboss/cache/interceptors and 1 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-17 09:14:29 -0400 (Mon, 17 Sep 2007)
New Revision: 4465
Added:
core/branches/1.4.X/src/org/jboss/cache/NodeCreationResult.java
Modified:
core/branches/1.4.X/src/org/jboss/cache/DataNode.java
core/branches/1.4.X/src/org/jboss/cache/Node.java
core/branches/1.4.X/src/org/jboss/cache/TransactionTable.java
core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java
core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTransactionManager.java
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
Log:
Fixes for JBCACHE-1165, JBCACHE-1166, JBCACHE-1168, JBCACHE-1164, JBCACHE-1183
Modified: core/branches/1.4.X/src/org/jboss/cache/DataNode.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/DataNode.java 2007-09-14 17:18:10 UTC (rev 4464)
+++ core/branches/1.4.X/src/org/jboss/cache/DataNode.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -51,4 +51,14 @@
void unmarkForRemoval(boolean deep);
void markForRemoval();
+ /**
+ * This method hs identical functionality as getOrCreateChild, but returns a NodeCreationResult.
+ * If the node was created, NodeCreationResult#isCreated() returns true.
+ * @param name name of child to create
+ * @param tx transaction under which to create child
+ * @param createIfNotExists if false don't attempt to create the node if it doesn't exist
+ * @return a NodeCreationResult instance
+ */
+ NodeCreationResult getOrCreateChildWithCreateInformation(Object name, GlobalTransaction tx, boolean createIfNotExists);
+
}
Modified: core/branches/1.4.X/src/org/jboss/cache/Node.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/Node.java 2007-09-14 17:18:10 UTC (rev 4464)
+++ core/branches/1.4.X/src/org/jboss/cache/Node.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -318,55 +318,64 @@
return this.data().put(key, value);
}
}
+
+ public NodeCreationResult getOrCreateChildWithCreateInformation(Object child_name, GlobalTransaction gtx, boolean createIfNotExists){
+ NodeCreationResult result = new NodeCreationResult();
+ DataNode child;
+ if (child_name == null)
+ throw new IllegalArgumentException("null child name");
+ child = (DataNode) children().get(child_name);
+ if (createIfNotExists && child == null)
+ {
+ if (log.isTraceEnabled()) log.trace("Children:"+children);
+ // construct the new child outside the synchronized block to avoid
+ // spending any more time than necessary in the synchronized section
+ Fqn child_fqn = new Fqn(this.fqn, child_name);
+ DataNode newChild = (DataNode) NodeFactory.getInstance().createNodeOfType(this, child_name, child_fqn, this, null, cache);
+ if (newChild == null)
+ throw new IllegalStateException();
+ synchronized (this)
+ {
+ // check again to see if the child exists
+ // after acquiring exclusive lock
+ child = (Node) children().get(child_name);
+ if (child == null)
+ {
+ child = newChild;
+ children.put(child_name, child);
+ if (gtx != null)
+ {
+ MethodCall undo_op = MethodCallFactory.create(MethodDeclarations.removeNodeMethodLocal,
+ new Object[]{gtx, child_fqn, Boolean.FALSE});
+ cache.addUndoOperation(gtx, undo_op);
+ // add the node name to the list maintained for the current tx
+ // (needed for abort/rollback of transaction)
+ // cache.addNode(gtx, child.getFqn());
+ }
+ }
+ }
+
+ // notify if we actually created a new child
+ if (newChild == child)
+ {
+ if (trace)
+ {
+ log.trace("created child: fqn=" + child_fqn);
+ }
+ result.setCreated(true);
+ cache.notifyNodeCreated(child.getFqn());
+ }else{
+ result.setCreated(false);
+ }
+ }
+ result.setTreeNode(child);
+ return result;
+ }
+
public TreeNode getOrCreateChild(Object child_name, GlobalTransaction gtx, boolean createIfNotExists)
{
- DataNode child;
- if (child_name == null)
- throw new IllegalArgumentException("null child name");
-
- child = (DataNode) children().get(child_name);
- if (createIfNotExists && child == null)
- {
- // construct the new child outside the synchronized block to avoid
- // spending any more time than necessary in the synchronized section
- Fqn child_fqn = new Fqn(this.fqn, child_name);
- DataNode newChild = (DataNode) NodeFactory.getInstance().createNodeOfType(this, child_name, child_fqn, this, null, cache);
- if (newChild == null)
- throw new IllegalStateException();
- synchronized (this)
- {
- // check again to see if the child exists
- // after acquiring exclusive lock
- child = (Node) children().get(child_name);
- if (child == null)
- {
- child = newChild;
- children.put(child_name, child);
- if (gtx != null)
- {
- MethodCall undo_op = MethodCallFactory.create(MethodDeclarations.removeNodeMethodLocal,
- new Object[]{gtx, child_fqn, Boolean.FALSE});
- cache.addUndoOperation(gtx, undo_op);
- // add the node name to the list maintained for the current tx
- // (needed for abort/rollback of transaction)
- // cache.addNode(gtx, child.getFqn());
- }
- }
- }
-
- // notify if we actually created a new child
- if (newChild == child)
- {
- if (trace)
- {
- log.trace("created child: fqn=" + child_fqn);
- }
- cache.notifyNodeCreated(child.getFqn());
- }
- }
- return child;
-
+ return getOrCreateChildWithCreateInformation(child_name, gtx, createIfNotExists).getTreeNode();
}
public TreeNode createChild(Object child_name, Fqn fqn, TreeNode parent)
@@ -507,13 +516,13 @@
if (trace)
{
log.trace(new StringBuffer("acquiring RL: fqn=").append(fqn).append(", caller=").append(caller).
- append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)));
+ append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)).append("lock_hc="+lock_.hashCode()).append(", this._hc=").append(this.hashCode()));
}
boolean flag = lock_.acquireReadLock(caller, timeout);
if (trace)
{
log.trace(new StringBuffer("acquired RL: fqn=").append(fqn).append(", caller=").append(caller).
- append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)));
+ append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)).append("lock_hc="+lock_.hashCode()).append(", this._hc=").append(this.hashCode()));
}
return flag;
}
@@ -524,13 +533,13 @@
if (trace)
{
log.trace(new StringBuffer("acquiring WL: fqn=").append(fqn).append(", caller=").append(caller).
- append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)));
+ append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)).append("lock_hc="+lock_.hashCode()).append(", this._hc=").append(this.hashCode()));
}
boolean flag = lock_.acquireWriteLock(caller, timeout);
if (trace)
{
log.trace(new StringBuffer("acquired WL: fqn=").append(fqn).append(", caller=").append(caller).
- append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)));
+ append(", lock=").append(lock_.toString(DataNode.PRINT_LOCK_DETAILS)).append("lock_hc="+lock_.hashCode()).append(", this._hc=").append(this.hashCode()));
}
return flag;
}
Added: core/branches/1.4.X/src/org/jboss/cache/NodeCreationResult.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/NodeCreationResult.java (rev 0)
+++ core/branches/1.4.X/src/org/jboss/cache/NodeCreationResult.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -0,0 +1,19 @@
+package org.jboss.cache;
+
+public class NodeCreationResult
+{
+ private TreeNode treeNode;
+ private boolean created;
+ public boolean isCreated() {
+ return created;
+ }
+ public void setCreated(boolean created) {
+ this.created = created;
+ }
+ public TreeNode getTreeNode() {
+ return treeNode;
+ }
+ public void setTreeNode(TreeNode treeNode) {
+ this.treeNode = treeNode;
+ }
+}
Modified: core/branches/1.4.X/src/org/jboss/cache/TransactionTable.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/TransactionTable.java 2007-09-14 17:18:10 UTC (rev 4464)
+++ core/branches/1.4.X/src/org/jboss/cache/TransactionTable.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -179,39 +179,45 @@
/**
* Adds a lock to the global transaction.
+ * @return true if the lock was added
*/
- public void addLock(GlobalTransaction gtx, IdentityLock l) {
+ public boolean addLock(GlobalTransaction gtx, IdentityLock l) {
TransactionEntry entry=get(gtx);
if(entry == null) {
log.error("transaction entry not found for (gtx=" + gtx + ")");
- return;
+ return false;
}
entry.addLock(l);
+ return true;
}
/**
* Adds a collection of locks to the global transaction.
+ * @return true if the locks were added
*/
- public void addLocks(GlobalTransaction gtx, Collection locks) {
+ public boolean addLocks(GlobalTransaction gtx, Collection locks) {
TransactionEntry entry=get(gtx);
if(entry == null) {
log.error("transaction entry not found for (gtx=" + gtx + ")");
- return;
+ return false;
}
entry.addLocks(locks);
+ return true;
}
/**
* Adds a node that has been removed to the global transaction
+ * @return true if the removed node was added to the list of removed nodes
*/
- public void addRemovedNode(GlobalTransaction gtx, Fqn fqn)
+ public boolean addRemovedNode(GlobalTransaction gtx, Fqn fqn)
{
TransactionEntry entry=get(gtx);
if(entry == null) {
log.error("transaction entry not found for (gtx=" + gtx + ")");
- return;
+ return false;
}
entry.addRemovedNode(fqn);
+ return true;
}
/**
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-09-14 17:18:10 UTC (rev 4464)
+++ core/branches/1.4.X/src/org/jboss/cache/interceptors/PessimisticLockInterceptor.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -8,11 +8,14 @@
import org.jboss.cache.DataNode;
import org.jboss.cache.Fqn;
+import org.jboss.cache.NodeCreationResult;
import org.jboss.cache.GlobalTransaction;
import org.jboss.cache.InvocationContext;
+import org.jboss.cache.Node;
import org.jboss.cache.TransactionEntry;
import org.jboss.cache.TransactionTable;
import org.jboss.cache.TreeCache;
+import org.jboss.cache.TreeNode;
import org.jboss.cache.lock.IdentityLock;
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.cache.lock.LockingException;
@@ -41,9 +44,8 @@
public class PessimisticLockInterceptor extends Interceptor
{
TransactionTable tx_table = null;
-
boolean writeLockOnChildInsertRemove = true;
-
+
/**
* Map<Object, java.util.List>. Keys = threads, values = lists of locks held by that thread
*/
@@ -115,6 +117,9 @@
lock_timeout = ((Long) args[5]).longValue();
break;
case MethodDeclarations.removeNodeMethodLocal_id:
+ // createIfNotExists is set to true to prevent the endless loop in JBCACHE-1165.
+ // See http://jboss.org/index.html?module=bb&op=viewtopic&t=118186 for an explanation of this.
+ createIfNotExists = true;
fqn = (Fqn) args[1];
lock_type = DataNode.LOCK_TYPE_WRITE;
recursive = true; // remove node and *all* child nodes
@@ -170,17 +175,44 @@
// release the locks for the given TX
if (fqn != null)
{
- if (createIfNotExists)
+ // limit the time spent in the loop attempting to acquire locks.
+ long startTime = System.currentTimeMillis();
+ boolean finish;
+
+ do
{
- do
+ GlobalTransaction gtx = ctx.getGlobalTransaction();
+ // first try and lock the node in question.
+ DataNode lockedNode = lock(fqn, gtx, lock_type, recursive, zeroLockTimeout ? 0 : lock_timeout, createIfNotExists, storeLockedNode, isRemoveData);
+
+ // test whether we need to retry getting the lock.
+ finish = !createIfNotExists;
+
+ // if we need to create the node, or the locked node was not null, we need to test if this is the *same* node that is in the cache
+ // to prevent a race condition between concurrent creation and deletion.
+ if (createIfNotExists || lockedNode != null)
{
- lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, zeroLockTimeout ? 0 : lock_timeout, createIfNotExists, storeLockedNode, isRemoveData);
+ DataNode dataNode = getNodeFromCache(fqn, ctx.getGlobalTransaction());// fetch node from cache
+ finish = finish || dataNode != null;
+ // compare the two nodes. These *should* be the same object instances. If not, we have a problem - try and re-acquire the lock.
+ if (dataNode != lockedNode)
+ {
+ finish = false;
+ if (log.isDebugEnabled()) log.debug("Lock was acquired but node changed (createIfNotExists=" + createIfNotExists + ")");
+ releaseLock(lockedNode.getLock(), gtx == null ? (Object) Thread.currentThread() : gtx);
+ }
}
- while(!cache.exists(fqn)); // keep trying until we have the lock (fixes concurrent remove())
- // terminates successfully, or with (Timeout)Exception
- }
- else
- lock(fqn, ctx.getGlobalTransaction(), lock_type, recursive, zeroLockTimeout ? 0 : lock_timeout, createIfNotExists, storeLockedNode, isRemoveData);
+
+ // additional timeout check - if we haven't finished and have taken > lock_timeout milliseconds, throw a TimeoutException.
+ // if zeroLockTimeout is specified, there is no time for retries!
+ if (!finish && (zeroLockTimeout || System.currentTimeMillis() - startTime > lock_timeout))
+ {
+ String msg = "PessimicticLockInterceptor can't acquire lock after [" + lock_timeout + "] ms";
+ log.error(msg);
+ throw new TimeoutException(msg);
+ }
+
+ } while (!finish); // keep trying until we have the lock, or we time out.
}
else
{
@@ -209,9 +241,44 @@
return o;
}
+ /**
+ * Return node from cache, include nodes marked as removal only if they are removed by this transaction
+ *
+ * @param fqn fqn
+ * @return DataNode
+ */
+ private DataNode getNodeFromCache(Fqn fqn, GlobalTransaction gtx)
+ {
+ DataNode root = cache.getRoot();
+ if (fqn == null || fqn.size() == 0) return root;
+ TreeNode n = root;
+ int fqnSize = fqn.size();
+ for (int i = 0; i < fqnSize; i++)
+ {
+ Object obj = fqn.get(i);
+ n = n.getChild(obj);
+ if (n == null)
+ return null;
+ else if (((DataNode) n).isMarkedForRemoval())
+ {
+ if (gtx != null && !tx_table.get(gtx).getRemovedNodes().contains(n.getFqn()))
+ {
+ return null;
+ }
+ }
+ }
+ return (Node) n;
+ }
+
+
private void cleanup(GlobalTransaction gtx)
{
TransactionEntry entry = tx_table.get(gtx);
+ if (entry == null)
+ {
+ if (log.isInfoEnabled()) log.info("Unable to clean up since transaction entry for tx " + gtx + " is null. Perhaps the transaction has timed out?");
+ return;
+ }
// Let's do it in stack style, LIFO
entry.releaseAllLocksLIFO(gtx);
@@ -231,10 +298,11 @@
* @param gtx
* @param lock_type DataNode.LOCK_TYPE_READ, DataNode.LOCK_TYPE_WRITE or DataNode.LOCK_TYPE_NONE
* @param recursive Lock children recursively
+ * @return node on which lock was acquired or null if lock was not acquired
*/
- private void lock(Fqn fqn, GlobalTransaction gtx, int lock_type, boolean recursive,
- long lock_timeout, boolean createIfNotExists, boolean isRemoveNodeOperation, boolean isRemoveDataOperation)
- throws TimeoutException, LockingException, InterruptedException
+ private DataNode lock(Fqn fqn, GlobalTransaction gtx, int lock_type, boolean recursive,
+ long lock_timeout, boolean createIfNotExists, boolean isRemoveNodeOperation, boolean isRemoveDataOperation)
+ throws TimeoutException, LockingException, InterruptedException
{
DataNode n;
DataNode child_node;
@@ -250,11 +318,11 @@
if (fqn == null)
{
log.error("fqn is null - this should not be the case");
- return;
+ return null;
}
if ((treeNodeSize = fqn.size()) == 0)
- return;
+ return null;
if (cache.getIsolationLevelClass() == IsolationLevel.NONE)
lock_type = DataNode.LOCK_TYPE_NONE;
@@ -262,6 +330,7 @@
n = cache.getRoot();
for (int i = -1; i < treeNodeSize; i++)
{
+ boolean nodeCreated = false;
if (i == -1)
{
child_name = Fqn.ROOT.getName();
@@ -270,14 +339,17 @@
else
{
child_name = fqn.get(i);
- child_node = (DataNode) n.getOrCreateChild(child_name, gtx, createIfNotExists);
+// child_node = (DataNode) n.getOrCreateChild(child_name, gtx, createIfNotExists);
+ NodeCreationResult result = n.getOrCreateChildWithCreateInformation(child_name, gtx, createIfNotExists);
+ child_node = (DataNode) result.getTreeNode();
+ nodeCreated = result.isCreated();
}
if (child_node == null)
{
if (log.isTraceEnabled())
log.trace("failed to find or create child " + child_name + " of node " + n.getFqn());
- return;
+ return null;
}
if (lock_type == DataNode.LOCK_TYPE_NONE)
@@ -288,7 +360,7 @@
}
else
{
- if (writeLockNeeded(lock_type, i, treeNodeSize, isRemoveNodeOperation, createIfNotExists, isRemoveDataOperation, fqn, child_node.getFqn()))
+ if (nodeCreated || writeLockNeeded(lock_type, i, treeNodeSize, isRemoveNodeOperation, createIfNotExists, isRemoveDataOperation, fqn, child_node.getFqn()))
{
currentLockType = DataNode.LOCK_TYPE_WRITE;
}
@@ -297,14 +369,12 @@
currentLockType = DataNode.LOCK_TYPE_READ;
}
}
-
// reverse the "remove" if the node has been previously removed in the same tx, if this operation is a put()
if (gtx != null && needToReverseRemove(child_node, tx_table.get(gtx), lock_type, isRemoveNodeOperation, createIfNotExists))
{
reverseRemove(child_node);
}
-
// Try to acquire the lock; recording that we did if successful
acquireNodeLock(child_node, owner, gtx, currentLockType, lock_timeout);
@@ -316,7 +386,12 @@
{
if (gtx != null)
{
- cache.getTransactionTable().addLocks(gtx, acquired_locks);
+ boolean reallyAdded = tx_table.addLocks(gtx, acquired_locks);
+ if (!reallyAdded)
+ {
+ releaseLocks(acquired_locks, owner);
+ throw new LockingException("Locks can't be added to current transaction table (transaction timed out?)");
+ }
}
else
{
@@ -330,13 +405,21 @@
}
// Add the Fqn to be removed to the transaction entry so we can clean up after ourselves during commit/rollback
- if (isRemoveNodeOperation && gtx != null) cache.getTransactionTable().get(gtx).addRemovedNode(fqn);
+ if (isRemoveNodeOperation && gtx != null)
+ {
+ if (!tx_table.addRemovedNode(gtx, fqn))
+ {
+ throw new LockingException("Removed node can't be added to current transaction table (transaction timed out?)");
+ }
+ }
+ return n;
}
+
private boolean needToReverseRemove(DataNode n, TransactionEntry te, int lockTypeRequested, boolean isRemoveOperation, boolean createIfNotExists)
{
return !isRemoveOperation && createIfNotExists && lockTypeRequested == DataNode.LOCK_TYPE_WRITE && n.isMarkedForRemoval()
- && hasBeenRemovedInCurrentTx(te, n.getFqn());
+ && hasBeenRemovedInCurrentTx(te, n.getFqn());
}
private boolean hasBeenRemovedInCurrentTx(TransactionEntry te, Fqn f)
@@ -363,11 +446,11 @@
{
if (isRemoveOperation && currentNodeIndex == treeNodeSize - 2)
return true; // we're doing a remove and we've reached the PARENT node of the target to be removed.
-
+
if (!isTargetNode(currentNodeIndex, treeNodeSize) && !cache.exists(new Fqn(currentFqn, targetFqn.get(currentNodeIndex + 1))))
return isPutOperation; // we're at a node in the tree, not yet at the target node, and we need to create the next node. So we need a WL here.
}
-
+
return lock_type == DataNode.LOCK_TYPE_WRITE && isTargetNode(currentNodeIndex, treeNodeSize) && (isPutOperation || isRemoveOperation || isRemoveDataOperation); //normal operation, write lock explicitly requested and this is the target to be written to.
}
@@ -382,17 +465,50 @@
if (acquired)
{
// Record the lock for release on method return or tx commit/rollback
- recordNodeLock(gtx, node.getLock());
+ recordNodeLock(gtx, node.getLock(), owner);
}
}
- private void recordNodeLock(GlobalTransaction gtx, IdentityLock lock)
+ private void releaseLocks(Set acquired_locks, Object owner)
{
+ if (acquired_locks != null && !acquired_locks.isEmpty())
+ {
+ Iterator iter = acquired_locks.iterator();
+ while (iter.hasNext())
+ {
+ IdentityLock identityLock = (IdentityLock) iter.next();
+ releaseLock(identityLock, owner);
+ }
+ }
+ }
+
+ private void releaseLock(IdentityLock lock, Object owner)
+ {
+ if (lock != null)
+ {
+ if (log.isDebugEnabled())
+ {
+ log.debug("Releasing lock [" + lock + "]");
+ }
+ lock.release(owner);
+ }
+ }
+
+ private void recordNodeLock(GlobalTransaction gtx, IdentityLock lock, Object owner) throws LockingException
+ {
if (gtx != null)
{
+ // test that the gtx is associated with a valid tx.
+ Transaction tx = tx_table.getLocalTransaction(gtx);
+ if (!isValid(tx)) throw new LockingException("Locks can't be added to current transaction (transaction timed out?)");
// add the lock to the list of locks maintained for this transaction
// (needed for release of locks on commit or rollback)
- cache.getTransactionTable().addLock(gtx, lock);
+ boolean reallyAdded = tx_table.addLock(gtx, lock);
+ if (!reallyAdded)
+ {
+ releaseLock(lock, owner);
+ throw new LockingException("Locks can't be added to current transaction (transaction timed out?)");
+ }
}
else
{
@@ -402,7 +518,6 @@
}
}
-
private List getLocks(Thread currentThread)
{
// This sort of looks like a get/put race condition, but
@@ -457,7 +572,7 @@
TransactionEntry entry = tx_table.get(gtx);
if (entry == null)
{
- log.error("entry for transaction " + gtx + " not found (maybe already committed)");
+ if (log.isInfoEnabled()) log.info("entry for transaction " + gtx + " not found (transaction timed out?)");
return;
}
@@ -491,7 +606,7 @@
if (entry == null)
{
- log.error("entry for transaction " + tx + " not found (transaction has possibly already been rolled back)");
+ if (log.isInfoEnabled()) log.info("entry for transaction " + tx + " not found (transaction timed out?)");
return;
}
@@ -508,3 +623,4 @@
}
}
+
Modified: core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java
===================================================================
--- core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java 2007-09-14 17:18:10 UTC (rev 4464)
+++ core/branches/1.4.X/src/org/jboss/cache/interceptors/TxInterceptor.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -874,8 +874,7 @@
}
else
{
- log.warn("Local transaction does not exist or does not match expected transaction " + gtx);
- throw new CacheException(" local transaction " + ltx + " does not exist or does not match expected transaction " + gtx);
+ throw new CacheException(" local transaction " + ltx + " does not exist or does not match expected transaction " + gtx + " - perhaps the transaction has timed out?");
}
return result;
}
@@ -1037,18 +1036,27 @@
public void beforeCompletion()
{
- if (log.isTraceEnabled()) log.trace("Running beforeCompletion on gtx " + gtx);
- entry = txTable.get(gtx);
- if (entry == null)
- {
- log.error("Transaction has a null transaction entry - beforeCompletion() will fail.");
- log.error("TxTable contents: " + txTable);
- throw new IllegalStateException("cannot find transaction entry for " + gtx);
- }
+ if (log.isTraceEnabled()) log.trace("Running beforeCompletion on gtx " + gtx);
+ // make sure we refresh the tx from the tx_table as well, as it may have timed out.
+ this.tx = txTable.getLocalTransaction(gtx);
- modifications = entry.getModifications();
- }
+ if (tx == null)
+ {
+ log.error("Transaction is null in the transaction table. Perhaps it timed out?");
+ throw new IllegalStateException("Transaction is null in the transaction table. Perhaps it timed out?");
+ }
+ entry = txTable.get(gtx);
+ if (entry == null)
+ {
+ log.error("Transaction has a null transaction entry - beforeCompletion() will fail.");
+ log.error("TxTable contents: " + txTable);
+ throw new IllegalStateException("cannot find transaction entry for " + gtx);
+ }
+
+ modifications = entry.getModifications();
+ }
+
// this should really not be done here -
// it is supposed to be post commit not actually run the commit
public void afterCompletion(int status)
@@ -1155,7 +1163,7 @@
}
break;
default:
- throw new CacheException("transaction " + tx + " in status " + tx.getStatus() + " unbale to start transaction");
+ throw new CacheException("transaction " + tx + " in status " + tx.getStatus() + " unable to start transaction");
}
}
catch (Throwable t)
Modified: core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTransactionManager.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTransactionManager.java 2007-09-14 17:18:10 UTC (rev 4464)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTransactionManager.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -13,6 +13,7 @@
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
+import javax.transaction.Status;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -111,8 +112,19 @@
Transaction currentTx;
if ((currentTx = getTransaction()) != null)
{
- throw new NotSupportedException(Thread.currentThread() +
+ switch (currentTx.getStatus())
+ {
+ case Status.STATUS_COMMITTED:
+ case Status.STATUS_NO_TRANSACTION:
+ case Status.STATUS_ROLLEDBACK:
+ case Status.STATUS_UNKNOWN:
+ setTransaction(null);
+ break;
+ default:
+ throw new NotSupportedException(Thread.currentThread() +
" is already associated with a transaction (" + currentTx + ")");
+ }
+
}
AsyncRollbackTransaction tx = new AsyncRollbackTransaction(this, timeout);
setTransaction(tx);
Modified: core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java 2007-09-14 17:18:10 UTC (rev 4464)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java 2007-09-17 13:14:29 UTC (rev 4465)
@@ -25,7 +25,7 @@
protected void setUp() throws Exception
{
cache = new TreeCache();
- cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.setTransactionManagerLookupClass(AsyncRollbackTransactionManagerLookup.class.getName());
cache.start();
tm = cache.getTransactionManager();
cache.put(A, "k", "v");
@@ -62,7 +62,7 @@
cache.put(B, "k", "v");
// now the container should attempt to rollback the tx in a separate thread.
- new Thread()
+ Thread rollbackThread = new Thread()
{
public void run()
{
@@ -75,21 +75,31 @@
exceptions.add(e);
}
}
- }.start();
+ };
+ rollbackThread.start();
- // now try and put stuff in the main thread again
- cache.put(A, "k2", "v2");
try
{
+ // now try and put stuff in the main thread again
+ cache.put(A, "k2", "v2");
tm.commit();
}
- catch (RollbackException expected)
+ catch (Exception expected)
{
// this is expected.
}
- assertEquals("No stale locks should be around", 0, cache.getNumberOfLocksHeld());
+ // make sure the rollback thread has completed
+ rollbackThread.join();
+ int nL = cache.getNumberOfLocksHeld();
+ if (nL > 0)
+ {
+ System.out.println(cache.printLockInfo());
+ fail("Should be no stale locks around!");
+ }
+ //assertEquals("No stale locks should be around", 0, cache.getNumberOfLocksHeld());
+
if (exceptions.size() > 0) throw ((Exception) exceptions.get(0));
}
}
17 years, 2 months
JBoss Cache SVN: r4464 - core/branches/1.4.X/tests/functional/org/jboss/cache/transaction.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-14 13:18:10 -0400 (Fri, 14 Sep 2007)
New Revision: 4464
Modified:
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
Log:
Enhanced test for JBCACHE-1183
Modified: core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java 2007-09-14 16:00:29 UTC (rev 4463)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java 2007-09-14 17:18:10 UTC (rev 4464)
@@ -2,6 +2,7 @@
import junit.framework.TestCase;
import org.jboss.cache.TreeCache;
+import org.jboss.cache.lock.LockingException;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
@@ -9,7 +10,18 @@
import javax.transaction.TransactionManager;
/**
- * Test behaviour of async rollback timeouted transaction
+ * Test behaviour of async rollback of a tx that times out and subsequent operations on that transaction.
+ * <p/>
+ * NOTE: To run this test, add the following lines:
+ * <p/>
+ * <tt>
+ * <p/>
+ * <p/>
+ * if ("Thread-0".equals(Thread.currentThread().getName())) Thread.sleep(1500);
+ * <p/>
+ * </tt>
+ * <p/>
+ * to the first line of PessimistickLockInterceptor#recordNodeLock()
*
* @author <a href="mailto:jhalat@infovide.pl">Jacek Halat</a>
*/
@@ -78,7 +90,15 @@
});
assertNotNull(tm.getTransaction());
Thread.sleep(500);//transaction should be rolledback in another thread
- cache.put("/a", "k", "v");
+ try
+ {
+ cache.put("/a", "k", "v");
+ }
+ catch (LockingException expected)
+ {
+ // this is normal; the tx would have timed out and obtaining locks for this tx should fail.
+ }
+
tm.rollback();
assertNull(tm.getTransaction());
assertEquals(0, cache.getNumberOfLocksHeld());
17 years, 2 months
JBoss Cache SVN: r4463 - core/trunk/src/test/java/org/jboss/cache/transaction.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-14 12:00:29 -0400 (Fri, 14 Sep 2007)
New Revision: 4463
Added:
core/trunk/src/test/java/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
Log:
Added tests for a series of bugs, including JBCACHE-923, JBCACHE-1164, JBCACHE-1165, JBCACHE-1166, JBCACHE-1168, JBCACHE-1183.
Added: core/trunk/src/test/java/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java 2007-09-14 16:00:29 UTC (rev 4463)
@@ -0,0 +1,96 @@
+package org.jboss.cache.transaction;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * To test JBCACHE-923
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ */
+@Test(groups = {"functional"})
+public class SimultaneousRollbackAndPutTest
+{
+ private Cache cache;
+ private TransactionManager tm;
+ private Fqn A = Fqn.fromString("/a"), B = Fqn.fromString("/b");
+
+ @BeforeTest(alwaysRun = true)
+ protected void setUp() throws Exception
+ {
+ cache = DefaultCacheFactory.getInstance().createCache(false);
+ cache.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.start();
+ tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+ cache.put(A, "k", "v");
+ }
+
+ @AfterTest(alwaysRun = true)
+ protected void tearDown()
+ {
+ cache.stop();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ protected void resetCache()
+ {
+ cache.removeNode(B);
+ cache.getRoot().getChild(A).clearData();
+ cache.put(A, "k", "v");
+ }
+
+ @Test(invocationCount = 200, alwaysRun = false)
+ public void testStaleLocks() throws Exception
+ {
+ // scenario:
+ // Thread starts tx in cache. E.g., create and put into B
+ tm.begin();
+ final Transaction t = tm.getTransaction();
+ final List exceptions = new ArrayList();
+
+ cache.put(B, "k", "v");
+
+ // now the container should attempt to rollback the tx in a separate thread.
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ t.rollback();
+ }
+ catch (Exception e)
+ {
+ exceptions.add(e);
+ }
+ }
+ }.start();
+
+ // now try and put stuff in the main thread again
+ cache.put(A, "k2", "v2");
+ try
+ {
+ tm.commit();
+ }
+ catch (RollbackException expected)
+ {
+ // this is expected.
+ }
+
+ assert 0 == ((CacheImpl) cache).getNumberOfLocksHeld();
+
+ if (exceptions.size() > 0) throw ((Exception) exceptions.get(0));
+ }
+}
17 years, 2 months
JBoss Cache SVN: r4462 - in core/trunk/src/test/java/org/jboss/cache: lock and 2 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-14 11:51:46 -0400 (Fri, 14 Sep 2007)
New Revision: 4462
Added:
core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/
core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java
core/trunk/src/test/java/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
Removed:
core/trunk/src/test/java/org/jboss/cache/ConcurrentPutRemoveTest.java
Log:
Added tests for a series of bugs, including JBCACHE-923, JBCACHE-1164, JBCACHE-1165, JBCACHE-1166, JBCACHE-1168, JBCACHE-1183.
Deleted: core/trunk/src/test/java/org/jboss/cache/ConcurrentPutRemoveTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/ConcurrentPutRemoveTest.java 2007-09-14 15:50:44 UTC (rev 4461)
+++ core/trunk/src/test/java/org/jboss/cache/ConcurrentPutRemoveTest.java 2007-09-14 15:51:46 UTC (rev 4462)
@@ -1,87 +0,0 @@
-package org.jboss.cache;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.transaction.TransactionManager;
-
-import junit.framework.TestCase;
-
-import org.jboss.cache.lock.IsolationLevel;
-import org.jboss.cache.config.Configuration;
-import org.jboss.cache.transaction.DummyTransactionManagerLookup;
-
-public class ConcurrentPutRemoveTest extends TestCase {
-
- private TransactionManager tm;
-
- private Cache cache;
-
- protected void setUp() throws Exception {
- cache = DefaultCacheFactory.getInstance().createCache(false);
- cache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
- cache.getConfiguration().setIsolationLevel(IsolationLevel.READ_COMMITTED);
- cache.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
- cache.getConfiguration().setLockAcquisitionTimeout(10000);
- cache.start();
- tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
- }
-
- protected void tearDown() throws Exception {
- super.tearDown();
- cache.stop();
- cache.destroy();
- }
-
- public void testLock() throws Exception {
- List<SeparateThread> threads = new ArrayList<SeparateThread>();
- for (int x = 0; x < 2; x++) {
- SeparateThread t = new SeparateThread(x);
- threads.add(t);
- t.start();
- }
- for (SeparateThread separateThread : threads) {
- 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 < 1000; x++) {
- tm.begin();
- System.out.println("R" + Thread.currentThread().getName());
- //inside transaction
- cache.removeNode(Fqn.fromString("/a"));
- System.out.println("AR" + Thread.currentThread().getName());
- tm.commit();
- //outside transaction
- System.out.println("P" + Thread.currentThread().getName());
- cache.put(Fqn.fromString("/a/b/c/d"), "text"+x,"b");
- System.out.println("AP" + Thread.currentThread().getName());
- }
- } catch (Exception e) {
- this.e = e;
- }
- }
- }
-
-}
Added: core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/ConcurrentPutRemoveTest.java 2007-09-14 15:51:46 UTC (rev 4462)
@@ -0,0 +1,92 @@
+package org.jboss.cache.lock.pessimistic;
+
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.AfterMethod;
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.TransactionManager;
+
+@Test(groups = {"functional"})
+public class ConcurrentPutRemoveTest
+{
+ private TransactionManager tm;
+
+ private Cache cache;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception {
+ cache = DefaultCacheFactory.getInstance().createCache(false);
+ cache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
+ cache.getConfiguration().setIsolationLevel(IsolationLevel.READ_COMMITTED);
+ cache.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.getConfiguration().setLockAcquisitionTimeout(10000);
+ cache.start();
+ tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws Exception
+ {
+ cache.destroy();
+ }
+
+ public void testLock() throws Exception {
+ List<SeparateThread> threads = new ArrayList<SeparateThread>();
+ for (int x = 0; x < 2; x++) {
+ SeparateThread t = new SeparateThread(x);
+ threads.add(t);
+ t.start();
+ }
+ for (SeparateThread separateThread : threads) {
+ 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 < 1000; x++) {
+ tm.begin();
+ System.out.println("R" + Thread.currentThread().getName());
+ //inside transaction
+ cache.removeNode(Fqn.fromString("/a"));
+ System.out.println("AR" + Thread.currentThread().getName());
+ tm.commit();
+ //outside transaction
+ System.out.println("P" + Thread.currentThread().getName());
+ cache.put(Fqn.fromString("/a/b/c/d"), "text"+x,"b");
+ System.out.println("AP" + Thread.currentThread().getName());
+ }
+ } catch (Exception e) {
+ this.e = e;
+ }
+ }
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java 2007-09-14 15:51:46 UTC (rev 4462)
@@ -0,0 +1,161 @@
+package org.jboss.cache.lock.pessimistic;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+import javax.transaction.TransactionManager;
+
+
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Node;
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.UnversionedNode;
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.config.ConfigurationComponent;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
+import org.jboss.cache.lock.IsolationLevel;
+import org.testng.annotations.Test;
+import org.testng.annotations.AfterMethod;
+
+@Test(groups = {"functional"})
+public class LockNotReleasedTest
+{
+ Random rand = new Random(System.currentTimeMillis());
+
+ private TransactionManager tm;
+
+ private Cache cache;
+
+ private void startTest() throws Exception {
+ cache = DefaultCacheFactory.getInstance().createCache(false);
+ cache.getConfiguration().setCacheMode(Configuration.CacheMode.LOCAL);
+ cache.getConfiguration().setIsolationLevel(IsolationLevel.READ_COMMITTED);
+ cache.getConfiguration().setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.getConfiguration().setLockAcquisitionTimeout(1000);
+ cache.create();
+ cache.start();
+ tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown() throws Exception {
+ cache.stop();
+ cache.destroy();
+ }
+
+
+ public int getNumberOfLocksHeld()
+ {
+ return numLocks(cache.getRoot());
+ }
+
+ private int numLocks(Node node)
+ {
+ UnversionedNode n = (UnversionedNode) node;
+ int num = 0;
+ Map children;
+
+ if (n.getLock().isLocked()){
+ num++;
+ System.out.println("Node ["+n.getFqn()+"] is locked");
+ }
+ if ((children = n.getChildrenMapDirect()) != null)
+ {
+ for (Object o : children.values())
+ {
+ num += numLocks((Node) o);
+ }
+ }
+ return num;
+ }
+
+ public void testTransactionStorm() throws Exception {
+ startTest();
+ List<WorkThread> threads = new ArrayList<WorkThread>();
+// System.out.println(cache.getNumberOfLocksHeld());
+ assert 0 == getNumberOfLocksHeld();
+ while (true) {
+ for (int x = 0; x < 2; x++) {
+ WorkThread t = new WorkThread(x == 1);
+ threads.add(t);
+ t.start();
+ }
+ for (WorkThread separateThread : threads) {
+ separateThread.join();
+ if (separateThread.getException() != null) {
+ //separateThread.getException().getMessage();
+ }
+ }
+ int locksNum = getNumberOfLocksHeld();
+// System.out.println("Locks="+locksNum);
+ // checkpoint
+ if (((CacheImpl) cache).getNumberOfLocksHeld()>0){
+ System.out.println("ERROR, locks="+locksNum);
+ doDomethingOnCache(1);
+ }
+ assert 0 == locksNum;
+ }
+
+ }
+
+ private class WorkThread extends Thread {
+ Exception e = null;
+
+ private boolean remove;
+
+ public WorkThread(boolean remove) {
+ this.remove = remove;
+ }
+
+ public Exception getException() {
+ return e;
+ }
+
+ public void run() {
+ try {
+ for (int x = 0; x < 100; x++) {
+ tm.begin();
+ try {
+ doDomethingOnCache(x);
+ } finally {
+ if (x % 3 == 0) {
+ tm.commit();
+ } else {
+ tm.rollback();
+ }
+ }
+ }
+ } catch (Exception e) {
+// System.out.println(e.getMessage());
+ this.e = e;
+ }
+ }
+
+ }
+
+ private void doDomethingOnCache(int x) throws CacheException, InterruptedException {
+ cache.put(Fqn.fromString("/a/b/c/a"), "text1" + x, "");
+ cache.removeNode(Fqn.fromString("/q/b/c/d"));
+ cache.put(Fqn.fromString("/a/b/c/b"), "text2" + x, "");
+ cache.removeNode(Fqn.fromString("/q/b/c/c"));
+ cache.put(Fqn.fromString("/a/b/c/c"), "text3" + x, "");
+ cache.removeNode(Fqn.fromString("/q/b/c/b"));
+ cache.put(Fqn.fromString("/a/b/c/d"), "text4" + x, "");
+ cache.removeNode(Fqn.fromString("/q/b/c/a"));
+ cache.put(Fqn.fromString("/q/b/c/a"), "text5" + x, "");
+ cache.removeNode(Fqn.fromString("/a/b/c/d"));
+ cache.put(Fqn.fromString("/q/b/c/b"), "text6" + x, "");
+ cache.removeNode(Fqn.fromString("/a/b/c/c"));
+ cache.put(Fqn.fromString("/q/b/c/c"), "text7" + x, "");
+ cache.removeNode(Fqn.fromString("/a/b/c/b"));
+ cache.put(Fqn.fromString("/q/b/c/d"), "text8" + x, "");
+ cache.removeNode(Fqn.fromString("/a/b/c/a"));
+ }
+
+}
Added: core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java 2007-09-14 15:51:46 UTC (rev 4462)
@@ -0,0 +1,93 @@
+package org.jboss.cache.lock.pessimistic;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.transaction.TransactionManager;
+
+import junit.framework.TestCase;
+
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Configuration.CacheMode;
+import org.jboss.cache.factories.UnitTestCacheConfigurationFactory;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
+import org.testng.annotations.Test;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.AfterMethod;
+
+/**
+ * Test behaviour of concurent put/remove
+ *
+ * @author jhalat
+ */
+@Test(groups = {"functional"})
+public class LockUpgradeTest{
+
+ private TransactionManager tm;
+
+ private CacheImpl cache;
+
+ @BeforeMethod(alwaysRun = true)
+ protected void setUp() throws Exception {
+ Configuration c = new Configuration();
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache = (CacheImpl) DefaultCacheFactory.getInstance().createCache(c);
+ tm = DummyTransactionManager.getInstance();
+ }
+
+ @AfterMethod(alwaysRun = true)
+ protected void tearDown() throws Exception {
+ cache.stop();
+ cache.destroy();
+ }
+
+ public void testLock() throws Exception {
+ List<WorkThread> threads = new ArrayList<WorkThread>();
+ for (int x = 0; x < 2; x++) {
+ WorkThread t = new WorkThread(x == 1);
+ threads.add(t);
+ t.start();
+ }
+ for (WorkThread separateThread : threads) {
+ separateThread.join();
+ if (separateThread.getException() != null) {
+ throw separateThread.getException();
+ }
+ }
+ }
+
+ private class WorkThread extends Thread {
+ Exception e = null;
+
+ private boolean remove;
+
+ public WorkThread(boolean remove) {
+ this.remove = remove;
+ }
+
+ public Exception getException() {
+ return e;
+ }
+
+ public void run() {
+ try {
+ for (int x = 0; x < 1000; x++) {
+ tm.begin();
+ if (remove) {
+ cache.remove("/a/b/c/d");
+ cache.remove("/a");
+ } else {
+ cache.put("/a/b/c/d", "key","text" + x);
+ }
+ tm.commit();
+ Thread.sleep(1);
+ }
+ } catch (Exception e) {
+ this.e = e;
+ }
+ }
+ }
+}
Added: core/trunk/src/test/java/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java (rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java 2007-09-14 15:51:46 UTC (rev 4462)
@@ -0,0 +1,98 @@
+package org.jboss.cache.transaction;
+
+import junit.framework.TestCase;
+
+
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.jboss.cache.Cache;
+import org.jboss.cache.DefaultCacheFactory;
+import org.jboss.cache.CacheImpl;
+import org.jboss.cache.Fqn;
+import org.testng.annotations.Test;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+/**
+ * Test behaviour of async rollback timeouted transaction
+ *
+ * @author <a href="mailto:jhalat@infovide.pl">Jacek Halat</a>
+ */
+@Test(groups = {"functional"})
+public class AsyncRollbackTxLockTest
+{
+ private Cache cache;
+ private TransactionManager tm;
+
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ cache = DefaultCacheFactory.getInstance().createCache(false);
+
+ cache.getConfiguration().setTransactionManagerLookupClass(AsyncRollbackTransactionManagerLookup.class.getName());
+ cache.start();
+ tm = cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+ tm.setTransactionTimeout(2);
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ try
+ {
+ if (tm != null && tm.getTransaction() != null)
+ {
+ try
+ {
+ tm.rollback();
+ }
+ catch (SystemException e)
+ {
+ // do nothing
+ }
+ }
+ }
+ catch (SystemException e)
+ {
+ // do nothing
+ }
+ if (cache != null) cache.stop();
+ cache = null;
+ tm = null;
+ }
+
+
+ public void testTxTimeoutAndRemovePutAfter() throws Exception
+ {
+ Thread.currentThread().setName("Thread-0");
+ System.out.println("Main Thread:"+Thread.currentThread());
+ assert 0 == ((CacheImpl) cache).getNumberOfLocksHeld();
+ tm.setTransactionTimeout(1);//short transaction timeout
+ cache.put(Fqn.fromString("/a/b/c/d"), "k", "v");
+ tm.begin();
+ Transaction transaction = tm.getTransaction();
+ transaction.registerSynchronization(new Synchronization(){
+
+ public void afterCompletion(int arg0) {
+ System.out.println("Synchronization Thread:"+Thread.currentThread());
+ }
+
+ public void beforeCompletion() {
+ }
+
+ });
+ assert tm.getTransaction() != null;
+ Thread.sleep(500);//transaction should be rolledback in another thread
+ cache.put(Fqn.fromString("/a"), "k", "v");
+ tm.rollback();
+ assert tm.getTransaction() == null;
+ assert 0 == ((CacheImpl) cache).getNumberOfLocksHeld();
+ cache.put(Fqn.fromString("/a"), "k", "v");
+ }
+
+}
+
17 years, 2 months
JBoss Cache SVN: r4461 - in core/branches/1.4.X/tests/functional/org/jboss/cache: lock/pessimistic and 1 other directories.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-14 11:50:44 -0400 (Fri, 14 Sep 2007)
New Revision: 4461
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
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
Log:
Added tests for a series of bugs, including JBCACHE-923, JBCACHE-1164, JBCACHE-1165, JBCACHE-1166, JBCACHE-1168, JBCACHE-1183.
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-09-14 15:50:44 UTC (rev 4461)
@@ -0,0 +1,107 @@
+package org.jboss.cache.lock.pessimistic;
+
+import junit.framework.TestCase;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.lock.IsolationLevel;
+
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class ConcurrentPutRemoveTest extends TestCase
+{
+
+ private TransactionManager tm;
+
+ public ConcurrentPutRemoveTest(String s)
+ {
+ super(s);
+ }
+
+ private TreeCache cache;
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setCacheMode(TreeCache.LOCAL);
+ cache.setIsolationLevel(IsolationLevel.READ_COMMITTED);
+ cache.setTransactionManagerLookup(new DummyTransactionManagerLookup());
+ cache.setLockAcquisitionTimeout(10000);
+ cache.create();
+ cache.start();
+ tm = cache.getTransactionManager();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ cache.stop();
+ cache.destroy();
+ }
+
+ public void testLock() throws Exception
+ {
+ List threads = new ArrayList();
+ 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 < 1000; x++)
+ {
+ tm.begin();
+ System.out.println("R" + Thread.currentThread().getName());
+ //inside transaction
+ cache.remove("/a");
+ System.out.println("AR" + Thread.currentThread().getName());
+ tm.commit();
+ //outside transaction
+ System.out.println("P" + Thread.currentThread().getName());
+ cache.put("/a/b/c/d", "text" + x, "b");
+ System.out.println("AP" + Thread.currentThread().getName());
+ }
+ }
+ catch (Exception e)
+ {
+ this.e = e;
+ }
+ }
+ }
+
+}
Added: core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java (rev 0)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockNotReleasedTest.java 2007-09-14 15:50:44 UTC (rev 4461)
@@ -0,0 +1,175 @@
+package org.jboss.cache.lock.pessimistic;
+
+import junit.framework.TestCase;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Node;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.lock.IsolationLevel;
+
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+public class LockNotReleasedTest extends TestCase
+{
+ Random rand = new Random(System.currentTimeMillis());
+
+ private TransactionManager tm;
+
+ private TreeCache cache;
+
+ private void startTest() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setCacheMode(TreeCache.LOCAL);
+ cache.setIsolationLevel(IsolationLevel.READ_COMMITTED);
+ cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.setLockAcquisitionTimeout(1000);
+ cache.create();
+ cache.start();
+ tm = cache.getTransactionManager();
+ }
+
+ public void tearDown() throws Exception
+ {
+ cache.stop();
+ cache.destroy();
+ }
+
+
+ public int getNumberOfLocksHeld()
+ {
+ return numLocks((Node) cache.getRoot());
+ }
+
+ private int numLocks(Node n)
+ {
+ int num = 0;
+ Map children;
+
+ if (n.getLock().isLocked())
+ {
+ num++;
+ System.out.println("Node [" + n.getFqn() + "] is locked");
+ }
+ if ((children = n.getChildren(true)) != null)
+ {
+ for (Iterator i = children.values().iterator(); i.hasNext();)
+ {
+ num += numLocks((Node) i.next());
+ }
+ }
+ return num;
+ }
+
+ public void testTransactionStorm() throws Exception
+ {
+ startTest();
+ List threads = new ArrayList();
+// System.out.println(cache.getNumberOfLocksHeld());
+ assertEquals(0, getNumberOfLocksHeld());
+ while (true)
+ {
+ for (int x = 0; x < 2; x++)
+ {
+ WorkThread t = new WorkThread(x == 1);
+ threads.add(t);
+ t.start();
+ }
+ for (Iterator i = threads.iterator(); i.hasNext();)
+ {
+ WorkThread separateThread = (WorkThread) i.next();
+ separateThread.join();
+ if (separateThread.getException() != null)
+ {
+ //separateThread.getException().getMessage();
+ }
+ }
+ int locksNum = getNumberOfLocksHeld();
+// System.out.println("Locks="+locksNum);
+ // checkpoint
+ if (cache.getNumberOfLocksHeld() > 0)
+ {
+ System.out.println("ERROR, locks=" + locksNum);
+ doDomethingOnCache(1);
+ }
+ assertEquals(0, locksNum);
+ }
+
+ }
+
+ private class WorkThread extends Thread
+ {
+ Exception e = null;
+
+ private boolean remove;
+
+ public WorkThread(boolean remove)
+ {
+ this.remove = remove;
+ }
+
+ public Exception getException()
+ {
+ return e;
+ }
+
+ public void run()
+ {
+ try
+ {
+ for (int x = 0; x < 100; x++)
+ {
+ tm.begin();
+ try
+ {
+ doDomethingOnCache(x);
+ }
+ finally
+ {
+ if (x % 3 == 0)
+ {
+ tm.commit();
+ }
+ else
+ {
+ tm.rollback();
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+// System.out.println(e.getMessage());
+ this.e = e;
+ }
+ }
+
+ }
+
+ private void doDomethingOnCache(int x) throws CacheException, InterruptedException
+ {
+ cache.put(Fqn.fromString("/a/b/c/a"), "text1" + x, "");
+ cache.remove(Fqn.fromString("/q/b/c/d"));
+ cache.put(Fqn.fromString("/a/b/c/b"), "text2" + x, "");
+ cache.remove(Fqn.fromString("/q/b/c/c"));
+ cache.put(Fqn.fromString("/a/b/c/c"), "text3" + x, "");
+ cache.remove(Fqn.fromString("/q/b/c/b"));
+ cache.put(Fqn.fromString("/a/b/c/d"), "text4" + x, "");
+ cache.remove(Fqn.fromString("/q/b/c/a"));
+ cache.put(Fqn.fromString("/q/b/c/a"), "text5" + x, "");
+ cache.remove(Fqn.fromString("/a/b/c/d"));
+ cache.put(Fqn.fromString("/q/b/c/b"), "text6" + x, "");
+ cache.remove(Fqn.fromString("/a/b/c/c"));
+ cache.put(Fqn.fromString("/q/b/c/c"), "text7" + x, "");
+ cache.remove(Fqn.fromString("/a/b/c/b"));
+ cache.put(Fqn.fromString("/q/b/c/d"), "text8" + x, "");
+ cache.remove(Fqn.fromString("/a/b/c/a"));
+ }
+
+}
Added: core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java (rev 0)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/lock/pessimistic/LockUpgradeTest.java 2007-09-14 15:50:44 UTC (rev 4461)
@@ -0,0 +1,107 @@
+package org.jboss.cache.lock.pessimistic;
+
+import junit.framework.TestCase;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.TreeCache;
+import org.jboss.cache.transaction.DummyTransactionManager;
+
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Test behaviour of concurent put/remove
+ *
+ * @author jhalat
+ */
+public class LockUpgradeTest extends TestCase
+{
+
+ private TransactionManager tm;
+
+ public LockUpgradeTest(String s)
+ {
+ super(s);
+ }
+
+ private TreeCache cache;
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.start();
+ tm = DummyTransactionManager.getInstance();
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ cache.stop();
+ cache.destroy();
+ }
+
+ public void testLock() throws Exception
+ {
+ List threads = new ArrayList();
+ for (int x = 0; x < 2; x++)
+ {
+ WorkThread t = new WorkThread(x == 1);
+ threads.add(t);
+ t.start();
+ }
+ for (Iterator i = threads.iterator(); i.hasNext();)
+ {
+ WorkThread separateThread = (WorkThread) i.next();
+ separateThread.join();
+ if (separateThread.getException() != null)
+ {
+ throw separateThread.getException();
+ }
+ }
+ }
+
+ private class WorkThread extends Thread
+ {
+ Exception e = null;
+
+ private boolean remove;
+
+ public WorkThread(boolean remove)
+ {
+ this.remove = remove;
+ }
+
+ public Exception getException()
+ {
+ return e;
+ }
+
+ public void run()
+ {
+ try
+ {
+ for (int x = 0; x < 1000; x++)
+ {
+ tm.begin();
+ if (remove)
+ {
+ cache.remove("/a/b/c/d");
+ cache.remove("/a");
+ }
+ else
+ {
+ cache.put("/a/b/c/d", "key", "text" + x);
+ }
+ tm.commit();
+ Thread.sleep(1);
+ }
+ }
+ catch (Exception e)
+ {
+ this.e = e;
+ }
+ }
+ }
+}
Added: core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java (rev 0)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/AsyncRollbackTxLockTest.java 2007-09-14 15:50:44 UTC (rev 4461)
@@ -0,0 +1,89 @@
+package org.jboss.cache.transaction;
+
+import junit.framework.TestCase;
+import org.jboss.cache.TreeCache;
+
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * Test behaviour of async rollback timeouted transaction
+ *
+ * @author <a href="mailto:jhalat@infovide.pl">Jacek Halat</a>
+ */
+public class AsyncRollbackTxLockTest extends TestCase
+{
+ private TreeCache cache;
+ private TransactionManager tm;
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+
+ cache.setTransactionManagerLookupClass("org.jboss.cache.transaction.AsyncRollbackTransactionManagerLookup");
+ cache.startService();
+ tm = cache.getTransactionManager();
+ tm.setTransactionTimeout(2);
+ }
+
+ protected void tearDown()
+ {
+ try
+ {
+ if (tm != null && tm.getTransaction() != null)
+ {
+ try
+ {
+ tm.rollback();
+ }
+ catch (SystemException e)
+ {
+ // do nothing
+ }
+ }
+ }
+ catch (SystemException e)
+ {
+ // do nothing
+ }
+ if (cache != null) cache.stopService();
+ cache = null;
+ tm = null;
+ }
+
+
+ public void testTxTimeoutAndRemovePutAfter() throws Exception
+ {
+ Thread.currentThread().setName("Thread-0");
+ System.out.println("Main Thread:" + Thread.currentThread());
+ assertEquals(0, cache.getNumberOfLocksHeld());
+ tm.setTransactionTimeout(1);//short transaction timeout
+ cache.put("/a/b/c/d", "k", "v");
+ tm.begin();
+ Transaction transaction = tm.getTransaction();
+ transaction.registerSynchronization(new Synchronization()
+ {
+
+ public void afterCompletion(int arg0)
+ {
+ System.out.println("Synchronization Thread:" + Thread.currentThread());
+ }
+
+ public void beforeCompletion()
+ {
+ }
+
+ });
+ assertNotNull(tm.getTransaction());
+ Thread.sleep(500);//transaction should be rolledback in another thread
+ cache.put("/a", "k", "v");
+ tm.rollback();
+ assertNull(tm.getTransaction());
+ assertEquals(0, cache.getNumberOfLocksHeld());
+ cache.put("/a", "k", "v");
+ }
+
+}
+
Added: core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java
===================================================================
--- core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java (rev 0)
+++ core/branches/1.4.X/tests/functional/org/jboss/cache/transaction/SimultaneousRollbackAndPutTest.java 2007-09-14 15:50:44 UTC (rev 4461)
@@ -0,0 +1,95 @@
+package org.jboss.cache.transaction;
+
+import junit.framework.TestCase;
+import org.jboss.cache.DummyTransactionManagerLookup;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.TreeCache;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * To test JBCACHE-923
+ *
+ * @author <a href="mailto:manik@jboss.org">Manik Surtani</a>
+ */
+public class SimultaneousRollbackAndPutTest extends TestCase
+{
+ private TreeCache cache;
+ private TransactionManager tm;
+ private Fqn A = Fqn.fromString("/a"), B = Fqn.fromString("/b");
+
+ protected void setUp() throws Exception
+ {
+ cache = new TreeCache();
+ cache.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+ cache.start();
+ tm = cache.getTransactionManager();
+ cache.put(A, "k", "v");
+ }
+
+ protected void tearDown()
+ {
+ cache.stop();
+ }
+
+ public void testStaleLocks() throws Exception
+ {
+ // repeat this test several times.
+ for (int i = 0; i < 1000; i++)
+ {
+ System.out.println("In loop " + i);
+ doTest();
+ cache.remove(B);
+ cache.removeData(A);
+ cache.put(A, "k", "v");
+ }
+
+ }
+
+
+ private void doTest() throws Exception
+ {
+ // scenario:
+ // Thread starts tx in cache. E.g., create and put into B
+ tm.begin();
+ final Transaction t = tm.getTransaction();
+ final List exceptions = new ArrayList();
+
+ cache.put(B, "k", "v");
+
+ // now the container should attempt to rollback the tx in a separate thread.
+ new Thread()
+ {
+ public void run()
+ {
+ try
+ {
+ t.rollback();
+ }
+ catch (Exception e)
+ {
+ exceptions.add(e);
+ }
+ }
+ }.start();
+
+ // now try and put stuff in the main thread again
+ cache.put(A, "k2", "v2");
+ try
+ {
+ tm.commit();
+ }
+ catch (RollbackException expected)
+ {
+ // this is expected.
+ }
+
+ assertEquals("No stale locks should be around", 0, cache.getNumberOfLocksHeld());
+
+ if (exceptions.size() > 0) throw ((Exception) exceptions.get(0));
+ }
+}
17 years, 2 months
JBoss Cache SVN: r4460 - core/branches/1.4.X.
by jbosscache-commits@lists.jboss.org
Author: manik.surtani(a)jboss.com
Date: 2007-09-14 07:43:03 -0400 (Fri, 14 Sep 2007)
New Revision: 4460
Removed:
core/branches/1.4.X/.classpath
core/branches/1.4.X/.cvsignore
core/branches/1.4.X/.project
core/branches/1.4.X/.settings/
Log:
Removed unnecessary files
Deleted: core/branches/1.4.X/.classpath
===================================================================
--- core/branches/1.4.X/.classpath 2007-09-13 16:37:52 UTC (rev 4459)
+++ core/branches/1.4.X/.classpath 2007-09-14 11:43:03 UTC (rev 4460)
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
- <classpathentry kind="src" path="src"/>
- <classpathentry kind="src" path="tests/functional"/>
- <classpathentry kind="src" path="tests/perf"/>
- <classpathentry kind="src" path="tests/stress"/>
- <classpathentry kind="src" path="tests/interop"/>
- <classpathentry kind="lib" path="ant-dist/lib/ant.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/ant-junit.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/ant-launcher.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/ant-nodeps.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/ant-trax.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/ant-xslp.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/bsf.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/junit.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/pretty.jar"/>
- <classpathentry kind="lib" path="ant-dist/lib/resolver.jar"/>
- <classpathentry kind="lib" path="lib/bsh-2.0b4.jar"/>
- <classpathentry kind="lib" path="lib/commons-logging.jar"/>
- <classpathentry kind="lib" path="lib/concurrent.jar"/>
- <classpathentry kind="lib" path="lib/derby.jar"/>
- <classpathentry kind="lib" path="lib/javassist.jar"/>
- <classpathentry kind="lib" path="lib/jboss-aop.jar"/>
- <classpathentry kind="lib" path="lib/jboss-common.jar"/>
- <classpathentry kind="lib" path="lib/jboss-j2ee.jar"/>
- <classpathentry kind="lib" path="lib/jboss-jmx.jar"/>
- <classpathentry kind="lib" path="lib/jboss-minimal.jar"/>
- <classpathentry kind="lib" path="lib/jboss-system.jar"/>
- <classpathentry kind="lib" path="lib/jdbm-1.0.jar"/>
- <classpathentry kind="lib" path="lib/jgroups.jar"/>
- <classpathentry kind="lib" path="lib/junit.jar"/>
- <classpathentry kind="lib" path="lib/log4j.jar"/>
- <classpathentry kind="lib" path="lib/qdox.jar"/>
- <classpathentry kind="lib" path="lib/sleepycat/je.jar"/>
- <classpathentry kind="lib" path="lib/trove.jar"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
- <classpathentry kind="src" path="etc"/>
- <classpathentry kind="lib" path="lib/jboss-serialization.jar"/>
- <classpathentry kind="output" path="bin"/>
-</classpath>
Deleted: core/branches/1.4.X/.cvsignore
===================================================================
--- core/branches/1.4.X/.cvsignore 2007-09-13 16:37:52 UTC (rev 4459)
+++ core/branches/1.4.X/.cvsignore 2007-09-14 11:43:03 UTC (rev 4460)
@@ -1,14 +0,0 @@
-output
-build.log
-junit*
-0000*
-je.lck
-*.iml
-bin
-jbossdb
-dist
-JBossCache.ipr
-JBossCache.iws
-JBossCache140.ipr
-JBossCache140.iws
-derby.log
\ No newline at end of file
Deleted: core/branches/1.4.X/.project
===================================================================
--- core/branches/1.4.X/.project 2007-09-13 16:37:52 UTC (rev 4459)
+++ core/branches/1.4.X/.project 2007-09-14 11:43:03 UTC (rev 4460)
@@ -1,17 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>JBossCache</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
17 years, 2 months