package org.jboss.cache.lock;
import junit.framework.TestCase;
import org.jboss.cache.TreeCache;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.util.Collections;
public class WriteLockOnParentTest extends TestCase
{
private TreeCache cache;
private TransactionManager tm;
protected void setUp() throws Exception
{
cache = new TreeCache();
cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
// reduce LAT so the test runs faster
cache.setLockAcquisitionTimeout(500);
cache.startService();
tm = cache.getTransactionManager();
}
protected void tearDown() throws Exception
{
if (tm.getTransaction() != null)
{
try
{
tm.rollback();
}
catch (Exception e)
{
// do sweet F.A.
}
}
cache.stopService();
}
public void testDefaultCfg()
{
assertFalse("Locking of parent nodes for child inserts and removes should be false by default", cache.getLockParentForChildInsertRemove());
}
public void testDefaultChildInsert() throws Exception
{
cache.put("/a", Collections.EMPTY_MAP);
assertTrue("/a should exist", cache.exists("/a"));
// concurrent insert of /a/b and /a/c
tm.begin();
cache.put("/a/b", Collections.EMPTY_MAP);
Transaction t1 = tm.suspend();
tm.begin();
cache.put("/a/c", Collections.EMPTY_MAP);
tm.commit();
tm.resume(t1);
tm.commit();
assertTrue("/a/b should exist", cache.exists("/a/b"));
assertTrue("/a/c should exist", cache.exists("/a/c"));
}
public void testLockParentChildInsert() throws Exception
{
cache.stop();
cache.setLockParentForChildInsertRemove(true);
cache.start();
cache.put("/a", Collections.EMPTY_MAP);
assertTrue("/a should exist", cache.exists("/a"));
// concurrent insert of /a/b and /a/c
tm.begin();
cache.put("/a/b", Collections.EMPTY_MAP);
Transaction t1 = tm.suspend();
tm.begin();
try
{
cache.put("/a/c", Collections.EMPTY_MAP);
fail("Should not get here.");
}
catch (TimeoutException e)
{
// expected
}
tm.commit();
tm.resume(t1);
tm.commit();
assertTrue("/a/b should exist", cache.exists("/a/b"));
assertTrue("/a/c should not exist", !cache.exists("/a/c"));
}
public void testDefaultChildRemove() throws Exception
{
cache.put("/a", Collections.EMPTY_MAP);
cache.put("/a/b", Collections.EMPTY_MAP);
cache.put("/a/c", Collections.EMPTY_MAP);
assertTrue("/a should exist", cache.exists("/a"));
assertTrue("/a/b should exist", cache.exists("/a/b"));
assertTrue("/a/c should exist", cache.exists("/a/c"));
// concurrent remove of /a/b and /a/c
tm.begin();
cache.remove("/a/b");
Transaction t1 = tm.suspend();
tm.begin();
cache.remove("/a/c");
tm.commit();
tm.resume(t1);
tm.commit();
assertTrue("/a should exist", cache.exists("/a"));
assertTrue("/a/b should not exist", !cache.exists("/a/b"));
assertTrue("/a/c should not exist", !cache.exists("/a/c"));
}
public void testLockParentChildRemove() throws Exception
{
cache.stop();
cache.setLockParentForChildInsertRemove(true);
cache.start();
cache.put("/a", Collections.EMPTY_MAP);
cache.put("/a/b", Collections.EMPTY_MAP);
cache.put("/a/c", Collections.EMPTY_MAP);
assertTrue("/a should exist", cache.exists("/a"));
assertTrue("/a/b should exist", cache.exists("/a/b"));
assertTrue("/a/c should exist", cache.exists("/a/c"));
// concurrent remove of /a/b and /a/c
tm.begin();
cache.remove("/a/b");
Transaction t1 = tm.suspend();
tm.begin();
try
{
cache.remove("/a/c");
fail("Should not get here.");
}
catch (TimeoutException e)
{
// expected
}
tm.commit();
tm.resume(t1);
tm.commit();
assertTrue("/a should exist", cache.exists("/a"));
assertTrue("/a/b should not exist", !cache.exists("/a/b"));
assertTrue("/a/c should exist", cache.exists("/a/c"));
}
}