package org.jboss.cache.transaction;
import junit.framework.TestCase;
import org.jboss.cache.Fqn;
import org.jboss.cache.TreeCache;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
/**
* Test behaviour of async rollback timeouted transaction
*
* @author <a href="mailto:jhalat@infovide.pl">Jacek Halat</a>
* @since 1.4.0
*/
public class AsyncRollbackTxTest extends TestCase
{
private TreeCache cache;
private TransactionManager tm;
private Fqn fqn = Fqn.fromString("/test");
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 testCommitCreationInSameTx() throws Exception
{
assertEquals(0, cache.getNumberOfLocksHeld());
tm.begin();
cache.put(fqn, "k", "v");
assertEquals(2, cache.getNumberOfLocksHeld());
Thread.sleep(2500);
tm.commit();
assertEquals(0, cache.getNumberOfLocksHeld());
}
public void testRollbackCreationInSameTx() throws Exception
{
assertEquals(0, cache.getNumberOfLocksHeld());
tm.begin();
cache.put(fqn, "k", "v");
assertEquals(2, cache.getNumberOfLocksHeld());
Thread.sleep(2500);
tm.rollback();
assertEquals(0, cache.getNumberOfLocksHeld());
}
private void doTest(boolean commit, boolean writeLock) throws Exception
{
assertEquals(0, cache.getNumberOfLocksHeld());
cache.put(fqn, "k", "v");//Executed in Not transactional context
assertEquals(0, cache.getNumberOfLocksHeld());
SeparateThread t = new SeparateThread(commit, writeLock);
t.start();
t.join();
if (t.getException() != null)
{
throw t.getException();
}
assertEquals(0, cache.getNumberOfLocksHeld());
assertEquals("v", cache.get(fqn, "k"));
}
public void testRollbackCreationInDifferentTxReadLock() throws Exception
{
doTest(false, false);
}
public void testCommitCreationInDifferentTxReadLock() throws Exception
{
doTest(true, false);
}
public void testRollbackCreationInDifferentTxWriteLock() throws Exception
{
doTest(false, true);
}
public void testCommitCreationInDifferentTxWriteLock() throws Exception
{
doTest(true, true);
}
public void testTxTimeoutAndPutAfter() throws Exception
{
assertEquals(0, cache.getNumberOfLocksHeld());
tm.begin();
cache.put(fqn, "k", "v");
assertEquals(2, cache.getNumberOfLocksHeld());
assertNotNull(tm.getTransaction());
Thread.sleep(2500);
tm.rollback();
assertNull(tm.getTransaction());
assertEquals(0, cache.getNumberOfLocksHeld());
// make sure the node was NOT added!!
assertFalse(cache.exists(fqn));
// even in a "deleted" form
assertNull(cache.peek(fqn));
//Put not some data into cache. Because no transaction exist
//no locks should be helds after this line, correct?
cache.put(fqn, "k", "v");
//On version 1.4.0SP1 cache.getNumberOfLocksHeld()==1
assertEquals(0, cache.getNumberOfLocksHeld());
}
public void testTxTimeoutAndPutGetAfter() throws Exception
{
assertEquals(0, cache.getNumberOfLocksHeld());
tm.begin();
cache.put(fqn, "k", "v");
assertEquals(2, cache.getNumberOfLocksHeld());
assertNotNull(tm.getTransaction());
Thread.sleep(2500);
tm.rollback();
assertNull(tm.getTransaction());
assertEquals(0, cache.getNumberOfLocksHeld());
//Put not some data into cache. Because no transaction exist
//no locks should be helds after this line, correct?
cache.put(fqn, "k", "v");
cache.get(fqn, "k");
//Because this thread is Owner of lock, read this node can be readed
//but when we try read this value from another thread (another thread is of course NOT lock owner)
//we got...
SeparateThread t = new SeparateThread(false, false);
t.start();
t.join();
if (t.getException() != null)
{
throw t.getException();
}
//...TimeoutException. This happend On version 1.4.0SP1.
//org.jboss.cache.lock.TimeoutException: failure acquiring lock: fqn=/test, caller=GlobalTransaction:<null>:2, lock=write owner=GlobalTransaction:<null>:1 (activeReaders=0, activeWriter=Thread[main,5,main], waitingReaders=0, waitingWriters=0, waitingUpgrader=0)
//at org.jboss.cache.Node.acquire(Node.java:407)
}
private class SeparateThread extends Thread
{
Exception e = null;
boolean commit, writeLock;
public SeparateThread(boolean commit, boolean writeLock)
{
this.commit = commit;
this.writeLock = writeLock;
}
public Exception getException()
{
return e;
}
public void run()
{
try
{
tm.begin();
if (writeLock)
{
cache.put(fqn, "k", "v2");// obtain write lock on node
}
else
{
cache.get(fqn, "k");// obtain read lock on node
}
// sleep to ensure tx times out.
sleep(2500);
if (commit)
{
tm.commit();
}
else
{
tm.rollback();
}
assertEquals(0, cache.getNumberOfLocksHeld());
}
catch (Exception e)
{
this.e = e;
}
}
}
;
}