Author: manik.surtani(a)jboss.com
Date: 2008-11-27 22:39:39 -0500 (Thu, 27 Nov 2008)
New Revision: 7227
Added:
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeMoveAPITest.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeReplicatedMoveTest.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTest.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTxTest.java
Modified:
core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCache.java
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java
core/branches/flat/src/test/java/org/jboss/starobrno/api/CacheAPITest.java
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java
core/branches/flat/src/test/java/org/jboss/starobrno/util/TestingUtil.java
Log:
Tree related stuff, move impl, etc
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java 2008-11-28
01:42:18 UTC (rev 7226)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/tree/NodeImpl.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -393,4 +393,12 @@
{
return (fqn != null ? fqn.hashCode() : 0);
}
+
+ @Override
+ public String toString()
+ {
+ return "NodeImpl{" +
+ "fqn=" + fqn +
+ '}';
+ }
}
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCache.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCache.java 2008-11-28
01:42:18 UTC (rev 7226)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCache.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -500,7 +500,7 @@
Configuration getConfiguration();
- Cache getCache();
+ Cache<K, V> getCache();
boolean exists(String fqn);
Modified: core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java
===================================================================
---
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java 2008-11-28
01:42:18 UTC (rev 7226)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeCacheImpl.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -192,7 +192,45 @@
public void move(Fqn nodeToMove, Fqn newParent) throws NodeNotExistsException
{
- //TODO: Autogenerated. Implement me properly
+ if (nodeToMove == null || newParent == null) throw new
NullPointerException("Cannot accept null parameters!");
+
+ if (nodeToMove.getParent().equals(newParent))
+ {
+ // moving onto self! Do nothing!
+ return;
+ }
+
+ // Depth first. Lets start with getting the node we want.
+ startAtomic();
+ try
+ {
+ Node node = getNode(nodeToMove);
+ if (node == null) return; // nothing to do here!
+ if (!exists(newParent))
+ {
+ // then we need to silently create the new parent
+ createNodeInCache(newParent);
+ }
+
+ // create an empty node for this new parent
+ Fqn newFqn = Fqn.fromRelativeElements(newParent, nodeToMove.getLastElement());
+ createNodeInCache(newFqn);
+ Node newNode = getNode(newFqn);
+ Map oldData = node.getData();
+ if (oldData != null && !oldData.isEmpty()) newNode.putAll(oldData);
+ for (Object child : node.getChildrenNames())
+ {
+ // move kids
+ Fqn oldChildFqn = Fqn.fromRelativeElements(nodeToMove, child);
+ move(oldChildFqn, newFqn);
+ }
+
+ removeNode(nodeToMove);
+ }
+ finally
+ {
+ endAtomic();
+ }
}
public void move(String nodeToMove, String newParent) throws NodeNotExistsException
Modified:
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java
===================================================================
---
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java 2008-11-28
01:42:18 UTC (rev 7226)
+++
core/branches/flat/src/main/java/org/jboss/starobrno/tree/TreeStructureSupport.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -94,4 +94,36 @@
return lockManager.isLocked(new NodeKey(fqn, NodeKey.Type.STRUCTURE)) &&
lockManager.isLocked(new NodeKey(fqn, NodeKey.Type.DATA));
}
+
+ /**
+ * Visual representation of a tree
+ * @param cache cache to dump
+ * @return String rep
+ */
+ public static String printTree(TreeCache<?, ?> cache, boolean details)
+ {
+ StringBuilder sb = new StringBuilder();
+// sb.append("Raw keys: " + cache.getCache().keySet());
+ sb.append("\n\n");
+
+ // walk tree
+ sb.append("+ ").append(Fqn.SEPARATOR);
+ if (details) sb.append(" ").append(cache.getRoot().getData());
+ sb.append("\n");
+ addChildren(cache.getRoot(), 1, sb, details);
+ return sb.toString();
+ }
+
+ private static void addChildren(Node<?, ?> node, int depth, StringBuilder sb,
boolean details)
+ {
+ for (Node<?, ?> child: node.getChildren())
+ {
+ for (int i=0; i<depth; i++) sb.append(" "); // indentations
+ sb.append("+ ");
+ sb.append(child.getFqn().getLastElementAsString()).append(Fqn.SEPARATOR);
+ if (details) sb.append(" ").append(child.getData());
+ sb.append("\n");
+ addChildren(child, depth + 1, sb, details);
+ }
+ }
}
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/api/CacheAPITest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/api/CacheAPITest.java 2008-11-28
01:42:18 UTC (rev 7226)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/api/CacheAPITest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -1,8 +1,11 @@
package org.jboss.starobrno.api;
import org.jboss.cache.CacheFactory;
-import org.jboss.cache.transaction.GenericTransactionManagerLookup;
+import org.jboss.cache.lock.IsolationLevel;
+import org.jboss.cache.transaction.DummyTransactionManager;
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.UnitTestCacheFactory;
import org.jboss.starobrno.config.Configuration;
import org.jboss.starobrno.config.ConfigurationException;
import org.jboss.starobrno.util.TestingUtil;
@@ -14,7 +17,6 @@
import java.util.HashMap;
import java.util.Map;
-import org.jboss.starobrno.UnitTestCacheFactory;
/**
* Tests the {@link org.jboss.cache.Cache} public API at a high level
@@ -23,7 +25,7 @@
*/
@Test(groups = {"functional", "pessimistic"})
-public class CacheAPITest
+public abstract class CacheAPITest
{
private ThreadLocal<CacheSPI<String, String>> cacheTL = new
ThreadLocal<CacheSPI<String, String>>();
@@ -31,19 +33,16 @@
public void setUp() throws Exception
{
// start a single cache instance
+ Configuration c = new Configuration();
+ c.setIsolationLevel(getIsolationLevel());
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
CacheFactory<String, String> cf = new UnitTestCacheFactory<String,
String>();
- CacheSPI<String, String> cache = (CacheSPI<String, String>)
cf.createCache("configs/local-tx.xml", false);
- cache.getConfiguration().setEvictionConfig(null);
- configure(cache.getConfiguration());
- cache.start();
+ CacheSPI<String, String> cache = (CacheSPI<String, String>)
cf.createCache(c.clone());
cacheTL.set(cache);
}
- protected void configure(Configuration c)
- {
- }
+ protected abstract IsolationLevel getIsolationLevel();
-
@AfterMethod(alwaysRun = true)
public void tearDown()
{
@@ -60,7 +59,7 @@
CacheSPI<String, String> cache = cacheTL.get();
Configuration c = cache.getConfiguration();
assertEquals(Configuration.CacheMode.LOCAL, c.getCacheMode());
- assertEquals(GenericTransactionManagerLookup.class.getName(),
c.getTransactionManagerLookupClass());
+ assertEquals(DummyTransactionManagerLookup.class.getName(),
c.getTransactionManagerLookupClass());
// note that certain values should be immutable. E.g., CacheMode cannot be changed
on the fly.
try
@@ -80,7 +79,7 @@
public void testGetMembersInLocalMode()
{
CacheSPI<String, String> cache = cacheTL.get();
- assert cache.getRPCManager() == null : "Cache members should be null if
running in LOCAL mode";
+ assert cache.getRPCManager().getLocalAddress() == null : "Cache members should
be null if running in LOCAL mode";
}
/**
@@ -155,4 +154,73 @@
assert !cache.containsKey(key);
assert cache.isEmpty();
}
+
+ public void testRollbackAfterPut() throws Exception
+ {
+ CacheSPI<String, String> cache = cacheTL.get();
+ String key = "key", value = "value";
+ cache.put(key, value);
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+
+ DummyTransactionManager.getInstance().begin();
+ cache.put("key2", "value2");
+ assert cache.get("key2").equals("value2");
+ DummyTransactionManager.getInstance().rollback();
+
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+ }
+
+ public void testRollbackAfterOverwrite() throws Exception
+ {
+ CacheSPI<String, String> cache = cacheTL.get();
+ String key = "key", value = "value";
+ cache.put(key, value);
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+
+ DummyTransactionManager.getInstance().begin();
+ cache.put(key, "value2");
+ assert cache.get(key).equals("value2");
+ assert 1 == cache.size();
+ DummyTransactionManager.getInstance().rollback();
+
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+ }
+
+ public void testRollbackAfterRemove() throws Exception
+ {
+ CacheSPI<String, String> cache = cacheTL.get();
+ String key = "key", value = "value";
+ cache.put(key, value);
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+
+ DummyTransactionManager.getInstance().begin();
+ cache.remove(key);
+ assert cache.get(key) == null;
+ DummyTransactionManager.getInstance().rollback();
+
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+ }
+
+ public void testRollbackAfterClear() throws Exception
+ {
+ CacheSPI<String, String> cache = cacheTL.get();
+ String key = "key", value = "value";
+ cache.put(key, value);
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+
+ DummyTransactionManager.getInstance().begin();
+ cache.clear();
+ assert cache.get(key) == null;
+ DummyTransactionManager.getInstance().rollback();
+
+ assert cache.get(key).equals(value);
+ assert 1 == cache.size();
+ }
}
Modified:
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java
===================================================================
---
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java 2008-11-28
01:42:18 UTC (rev 7226)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/read_committed/CacheAPIMVCCTest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -2,7 +2,6 @@
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.starobrno.api.CacheAPITest;
-import org.jboss.starobrno.config.Configuration;
import org.testng.annotations.Test;
/**
@@ -12,9 +11,8 @@
public class CacheAPIMVCCTest extends CacheAPITest
{
@Override
- protected void configure(Configuration c)
+ protected IsolationLevel getIsolationLevel()
{
- super.configure(c);
- c.setIsolationLevel(IsolationLevel.READ_COMMITTED);
+ return IsolationLevel.READ_COMMITTED;
}
}
\ No newline at end of file
Modified:
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java
===================================================================
---
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java 2008-11-28
01:42:18 UTC (rev 7226)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/api/mvcc/repeatable_read/CacheAPIMVCCTest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -2,7 +2,6 @@
import org.jboss.cache.lock.IsolationLevel;
import org.jboss.starobrno.api.CacheAPITest;
-import org.jboss.starobrno.config.Configuration;
import org.testng.annotations.Test;
/**
@@ -12,9 +11,8 @@
public class CacheAPIMVCCTest extends CacheAPITest
{
@Override
- protected void configure(Configuration c)
+ protected IsolationLevel getIsolationLevel()
{
- super.configure(c);
- c.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
+ return IsolationLevel.READ_COMMITTED;
}
}
\ No newline at end of file
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java
===================================================================
---
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java 2008-11-28
01:42:18 UTC (rev 7226)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeAPITest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -53,7 +53,7 @@
public void tearDown()
{
TreeCache<Object, Object> cache = cacheTL.get();
- TestingUtil.killCaches(cache.getCache());
+ TestingUtil.killTreeCaches(cache);
cacheTL.set(null);
}
Added: core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeMoveAPITest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeMoveAPITest.java
(rev 0)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeMoveAPITest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -0,0 +1,667 @@
+package org.jboss.starobrno.tree.api;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.NodeNotExistsException;
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.UnitTestCacheFactory;
+import org.jboss.starobrno.api.mvcc.LockAssert;
+import org.jboss.starobrno.config.CacheLoaderConfig;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.config.parsing.XmlConfigHelper;
+import org.jboss.starobrno.config.parsing.element.LoadersElementParser;
+import org.jboss.starobrno.factories.ComponentRegistry;
+import org.jboss.starobrno.invocation.InvocationContextContainer;
+import org.jboss.starobrno.lock.LockManager;
+import org.jboss.starobrno.tree.*;
+import org.jboss.starobrno.util.TestingUtil;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import org.w3c.dom.Element;
+
+import javax.transaction.TransactionManager;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Excercises and tests the new move() api
+ *
+ * @author <a href="mailto:manik AT jboss DOT org">Manik
Surtani</a>
+ * @since 2.0.0
+ */
+@Test(groups = {"functional", "pessimistic"}, testName =
"api.NodeMoveAPITest")
+public class NodeMoveAPITest
+{
+ protected final Log log = LogFactory.getLog(getClass());
+
+ protected static final Fqn A = Fqn.fromString("/a"), B =
Fqn.fromString("/b"), C = Fqn.fromString("/c"), D =
Fqn.fromString("/d"), E = Fqn.fromString("/e");
+ static final Fqn A_B = Fqn.fromRelativeFqn(A, B);
+ static final Fqn A_B_C = Fqn.fromRelativeFqn(A_B, C);
+ static final Fqn A_B_C_E = Fqn.fromRelativeFqn(A_B_C, E);
+ static final Fqn A_B_D = Fqn.fromRelativeFqn(A_B, D);
+ static final Fqn C_E = Fqn.fromRelativeFqn(C, E);
+ static final Fqn D_B = Fqn.fromRelativeFqn(D, B);
+ static final Fqn D_B_C = Fqn.fromRelativeFqn(D_B, C);
+ protected static final Object k = "key", vA = "valueA", vB =
"valueB", vC = "valueC", vD = "valueD", vE =
"valueE";
+
+ protected ThreadLocal<TreeCache<Object, Object>> cacheTL = new
ThreadLocal<TreeCache<Object, Object>>();
+ protected ThreadLocal<TransactionManager> tmTL = new
ThreadLocal<TransactionManager>();
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ // start a single cache instance
+ Configuration c = new Configuration();
+ c.setFetchInMemoryState(false);
+ c.setInvocationBatchingEnabled(true);
+ CacheSPI<Object, Object> cache = (CacheSPI<Object, Object>) new
UnitTestCacheFactory<Object, Object>().createCache(c);
+
+ cacheTL.set(new TreeCacheImpl<Object, Object>(cache));
+ tmTL.set(cache.getTransactionManager());
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ TestingUtil.killTreeCaches(cacheTL.get());
+ cacheTL.set(null);
+ }
+
+ public void testBasicMove()
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ TransactionManager tm = tmTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ nodeA.put(k, vA);
+ Node<Object, Object> nodeB = rootNode.addChild(B);
+ nodeB.put(k, vB);
+ Node<Object, Object> nodeC = nodeA.addChild(C);
+ nodeC.put(k, vC);
+ /*
+ /a/c
+ /b
+ */
+
+ assertTrue(rootNode.hasChild(A));
+ assertTrue(rootNode.hasChild(B));
+ assertFalse(rootNode.hasChild(C));
+ assertTrue(nodeA.hasChild(C));
+
+ // test data
+ assertEquals("" + nodeA, vA, nodeA.get(k));
+ assertEquals(vB, nodeB.get(k));
+ assertEquals(vC, nodeC.get(k));
+
+ // parentage
+ assertEquals(nodeA, nodeC.getParent());
+
+ log.info("BEFORE MOVE " + cache);
+ // move
+ cache.move(nodeC.getFqn(), nodeB.getFqn());
+
+ // re-fetch nodeC
+ nodeC = cache.getNode(Fqn.fromRelativeFqn(nodeB.getFqn(), C));
+
+ log.info("POST MOVE " + cache);
+ log.info("HC " + nodeC + " " +
System.identityHashCode(nodeC));
+ Node x = cache.getRoot().getChild(Fqn.fromString("b/c"));
+ log.info("HC " + x + " " + System.identityHashCode(x));
+ /*
+ /a
+ /b/c
+ */
+ assertEquals("NODE C " + nodeC, "/b/c",
nodeC.getFqn().toString());
+
+ assertTrue(rootNode.hasChild(A));
+ assertTrue(rootNode.hasChild(B));
+ assertFalse(rootNode.hasChild(C));
+ assertFalse(nodeA.hasChild(C));
+ assertTrue(nodeB.hasChild(C));
+
+ // test data
+ assertEquals(vA, nodeA.get(k));
+ assertEquals(vB, nodeB.get(k));
+ assertEquals(vC, nodeC.get(k));
+
+ // parentage
+ assertEquals("B is parent of C: " + nodeB, nodeB, nodeC.getParent());
+ }
+
+ @SuppressWarnings("unchecked")
+ private Node<Object, Object> genericize(Node node)
+ {
+ return (Node<Object, Object>) node;
+ }
+
+ public void testMoveWithChildren()
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ TransactionManager tm = tmTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ nodeA.put(k, vA);
+ Node<Object, Object> nodeB = rootNode.addChild(B);
+ nodeB.put(k, vB);
+ Node<Object, Object> nodeC = nodeA.addChild(C);
+ nodeC.put(k, vC);
+ Node<Object, Object> nodeD = nodeC.addChild(D);
+ nodeD.put(k, vD);
+ Node<Object, Object> nodeE = nodeD.addChild(E);
+ nodeE.put(k, vE);
+
+ assertTrue(rootNode.hasChild(A));
+ assertTrue(rootNode.hasChild(B));
+ assertFalse(rootNode.hasChild(C));
+ assertTrue(nodeA.hasChild(C));
+ assertTrue(nodeC.hasChild(D));
+ assertTrue(nodeD.hasChild(E));
+
+ // test data
+ assertEquals(vA, nodeA.get(k));
+ assertEquals(vB, nodeB.get(k));
+ assertEquals(vC, nodeC.get(k));
+ assertEquals(vD, nodeD.get(k));
+ assertEquals(vE, nodeE.get(k));
+
+ // parentage
+ assertEquals(rootNode, nodeA.getParent());
+ assertEquals(rootNode, nodeB.getParent());
+ assertEquals(nodeA, nodeC.getParent());
+ assertEquals(nodeC, nodeD.getParent());
+ assertEquals(nodeD, nodeE.getParent());
+
+ // move
+ log.info("move " + nodeC + " to " + nodeB);
+ cache.move(nodeC.getFqn(), nodeB.getFqn());
+ //System.out.println("nodeB " + nodeB);
+ //System.out.println("nodeC " + nodeC);
+
+ // child nodes will need refreshing, since existing pointers will be stale.
+ nodeC = nodeB.getChild(C);
+ nodeD = nodeC.getChild(D);
+ nodeE = nodeD.getChild(E);
+
+ assertTrue(rootNode.hasChild(A));
+ assertTrue(rootNode.hasChild(B));
+ assertFalse(rootNode.hasChild(C));
+ assertFalse(nodeA.hasChild(C));
+ assertTrue(nodeB.hasChild(C));
+ assertTrue(nodeC.hasChild(D));
+ assertTrue(nodeD.hasChild(E));
+
+ // test data
+ assertEquals(vA, nodeA.get(k));
+ assertEquals(vB, nodeB.get(k));
+ assertEquals(vC, nodeC.get(k));
+ assertEquals(vD, nodeD.get(k));
+ assertEquals(vE, nodeE.get(k));
+
+ // parentage
+ assertEquals(rootNode, nodeA.getParent());
+ assertEquals(rootNode, nodeB.getParent());
+ assertEquals(nodeB, nodeC.getParent());
+ assertEquals(nodeC, nodeD.getParent());
+ assertEquals(nodeD, nodeE.getParent());
+ }
+
+ public void testTxCommit() throws Exception
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ TransactionManager tm = tmTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ Node<Object, Object> nodeB = nodeA.addChild(B);
+
+ assertEquals(rootNode, nodeA.getParent());
+ assertEquals(nodeA, nodeB.getParent());
+ assertEquals(nodeA, rootNode.getChildren().iterator().next());
+ assertEquals(nodeB, nodeA.getChildren().iterator().next());
+
+ tm.begin();
+ // move node B up to hang off the root
+ cache.move(nodeB.getFqn(), Fqn.ROOT);
+
+ tm.commit();
+
+ nodeB = rootNode.getChild(B);
+
+ assertEquals(rootNode, nodeA.getParent());
+ assertEquals(rootNode, nodeB.getParent());
+
+ assertTrue(rootNode.getChildren().contains(nodeA));
+ assertTrue(rootNode.getChildren().contains(nodeB));
+
+ assertTrue(nodeA.getChildren().isEmpty());
+ }
+
+ public void testTxRollback() throws Exception
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ TransactionManager tm = tmTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ Node<Object, Object> nodeB = nodeA.addChild(B);
+
+ assertEquals(rootNode, nodeA.getParent());
+ assertEquals(nodeA, nodeB.getParent());
+ assertEquals(nodeA, rootNode.getChildren().iterator().next());
+ assertEquals(nodeB, nodeA.getChildren().iterator().next());
+
+
+ tm.begin();
+ // move node B up to hang off the root
+ System.out.println("Before: " + TreeStructureSupport.printTree(cache,
true));
+ cache.move(nodeB.getFqn(), Fqn.ROOT);
+ System.out.println("After: " + TreeStructureSupport.printTree(cache,
true));
+ tm.rollback();
+ System.out.println("Rolled back: " +
TreeStructureSupport.printTree(cache, true));
+
+ nodeA = rootNode.getChild(A);
+ nodeB = nodeA.getChild(B);
+
+ // should revert
+ assertEquals(rootNode, nodeA.getParent());
+ assertEquals(nodeA, nodeB.getParent());
+ assertEquals(nodeA, rootNode.getChildren().iterator().next());
+ assertEquals(nodeB, nodeA.getChildren().iterator().next());
+ }
+
+ /*
+ public void testWithCacheloaders() throws Exception
+ {
+ doCacheLoaderTest(false, false);
+ }
+
+ public void testWithPassivation() throws Exception
+ {
+ doCacheLoaderTest(true, false);
+ }
+
+ public void testWithCacheloadersTx() throws Exception
+ {
+ doCacheLoaderTest(false, true);
+ }
+
+ public void testWithPassivationTx() throws Exception
+ {
+ doCacheLoaderTest(true, true);
+ }
+ */
+
+ /*
+protected void doCacheLoaderTest(boolean pasv, boolean useTx) throws Exception
+{
+TreeCache<Object, Object> cache = cacheTL.get();
+TransactionManager tm = tmTL.get();
+Node<Object, Object> rootNode = cache.getRoot();
+
+cache.destroy();
+cache.getConfiguration().setCacheLoaderConfig(getSingleCacheLoaderConfig(pasv,
"/", DummyInMemoryCacheLoader.class.getName(), "debug=true", false,
false, false, false));
+cache.start();
+
+DummyInMemoryCacheLoader loader = (DummyInMemoryCacheLoader)
cache.getCacheLoaderManager().getCacheLoader();
+
+rootNode.put("key", "value");
+
+if (!pasv)
+{
+Map m = loader.get(Fqn.ROOT);
+assertNotNull("Should not be null", m);
+assertEquals("value", m.get("key"));
+}
+
+Node<Object, Object> nodeA = rootNode.addChild(A);
+nodeA.put(k, vA);
+Node<Object, Object> nodeB = rootNode.addChild(B);
+nodeB.put(k, vB);
+Node<Object, Object> nodeC = nodeA.addChild(C);
+nodeC.put(k, vC);
+Node<Object, Object> nodeD = nodeC.addChild(D);
+nodeD.put(k, vD);
+Node<Object, Object> nodeE = nodeD.addChild(E);
+nodeE.put(k, vE);
+cache.evict(Fqn.ROOT, true);
+
+// move
+if (useTx) tm.begin();
+cache.move(nodeC.getFqn(), nodeB.getFqn());
+if (useTx) tm.commit();
+
+// after eviction, the node objects we hold are probably stale.
+nodeA = rootNode.getChild(A);
+nodeB = rootNode.getChild(B);
+nodeC = nodeB.getChild(C);
+log.info("nodeC get child B ");
+nodeD = nodeC.getChild(D);
+log.info("nodeD get child E ");
+nodeE = nodeD.getChild(E);
+
+Fqn old_C = C;
+Fqn old_D = Fqn.fromRelativeFqn(old_C, D);
+Fqn old_E = Fqn.fromRelativeFqn(old_D, E);
+
+// test data
+assertEquals(vA, nodeA.get(k));
+assertEquals(vB, nodeB.get(k));
+assertEquals(vC, nodeC.get(k));
+assertEquals(vD, nodeD.get(k));
+assertEquals(vE, nodeE.get(k));
+
+// parentage
+assertEquals(rootNode, nodeA.getParent());
+assertEquals(rootNode, nodeB.getParent());
+assertEquals(nodeB, nodeC.getParent());
+assertEquals(nodeC, nodeD.getParent());
+assertEquals(nodeD, nodeE.getParent());
+
+
+if (pasv) cache.evict(Fqn.ROOT, true);
+
+//now inspect the loader.
+assertEquals(vA, loader.get(nodeA.getFqn()).get(k));
+assertEquals(vB, loader.get(nodeB.getFqn()).get(k));
+assertEquals(vC, loader.get(nodeC.getFqn()).get(k));
+assertEquals(vD, loader.get(nodeD.getFqn()).get(k));
+assertEquals(vE, loader.get(nodeE.getFqn()).get(k));
+
+assertNull(loader.get(old_C));
+assertNull(loader.get(old_D));
+assertNull(loader.get(old_E));
+
+}
+ */
+
+ public void testLocksDeepMove() throws Exception
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ TransactionManager tm = tmTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ Node<Object, Object> nodeB = nodeA.addChild(B);
+ Node<Object, Object> nodeD = nodeB.addChild(D);
+ Node<Object, Object> nodeC = rootNode.addChild(C);
+ Node<Object, Object> nodeE = nodeC.addChild(E);
+ assertNoLocks();
+ tm.begin();
+
+ cache.move(nodeC.getFqn(), nodeB.getFqn());
+
+ checkLocksDeep();
+
+
+ tm.commit();
+
+ assertNoLocks();
+ }
+
+ public void testLocks() throws Exception
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ TransactionManager tm = tmTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ Node<Object, Object> nodeB = nodeA.addChild(B);
+ Node<Object, Object> nodeC = rootNode.addChild(C);
+ assertNoLocks();
+ tm.begin();
+
+ cache.move(nodeC.getFqn(), nodeB.getFqn());
+
+ checkLocks();
+
+ tm.commit();
+ assertNoLocks();
+ }
+
+ public void testConcurrency() throws InterruptedException
+ {
+ final TreeCache<Object, Object> cache = cacheTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ final int N = 3;// number of threads
+ final int loops = 1 << 6;// number of loops
+ // tests a tree structure as such:
+ // /a
+ // /b
+ // /c
+ // /d
+ // /e
+ // /x
+ // /y
+
+ // N threads constantly move /x and /y around to hang off either /a ~ /e randomly.
+
+ final Fqn FQN_A = A, FQN_B = B, FQN_C = C, FQN_D = D, FQN_E = E, FQN_X =
Fqn.fromString("/x"), FQN_Y = Fqn.fromString("/y");
+
+ // set up the initial structure.
+ final Node[] NODES = {
+ rootNode.addChild(FQN_A), rootNode.addChild(FQN_B),
+ rootNode.addChild(FQN_C), rootNode.addChild(FQN_D), rootNode.addChild(FQN_E)
+ };
+
+ final Node<Object, Object> NODE_X = genericize(NODES[0]).addChild(FQN_X);
+ final Node<Object, Object> NODE_Y = genericize(NODES[1]).addChild(FQN_Y);
+
+ Thread[] movers = new Thread[N];
+ final CountDownLatch latch = new CountDownLatch(1);
+ final Random r = new Random();
+
+ for (int i = 0; i < N; i++)
+ {
+ movers[i] = new Thread("Mover-" + i)
+ {
+ public void run()
+ {
+ try
+ {
+ latch.await();
+ }
+ catch (InterruptedException e)
+ {
+ }
+
+ for (int counter = 0; counter < loops; counter++)
+ {
+
+ System.out.println(getName() + ": Attempt " + counter);
+ try
+ {
+ cache.move(NODE_X.getFqn(),
NODES[r.nextInt(NODES.length)].getFqn());
+ }
+ catch (NodeNotExistsException e)
+ {
+ // this may happen ...
+ }
+ TestingUtil.sleepRandom(250);
+ try
+ {
+ cache.move(NODE_Y.getFqn(),
NODES[r.nextInt(NODES.length)].getFqn());
+ }
+ catch (NodeNotExistsException e)
+ {
+ // this may happen ...
+ }
+ TestingUtil.sleepRandom(250);
+ }
+ }
+ };
+ movers[i].start();
+ }
+
+ latch.countDown();
+
+ for (Thread t : movers)
+ {
+ t.join();
+ }
+
+ assertNoLocks();
+ boolean found_x = false, found_x_again = false;
+ for (Node erased : NODES)
+ {
+ Node<Object, Object> n = genericize(erased);
+ if (!found_x)
+ {
+ found_x = n.hasChild(FQN_X);
+ }
+ else
+ {
+ found_x_again = found_x_again || n.hasChild(FQN_X);
+ }
+ }
+ boolean found_y = false, found_y_again = false;
+ for (Node erased : NODES)
+ {
+ Node<Object, Object> n = genericize(erased);
+ if (!found_y)
+ {
+ found_y = n.hasChild(FQN_Y);
+ }
+ else
+ {
+ found_y_again = found_y_again || n.hasChild(FQN_Y);
+ }
+ }
+
+ assertTrue("Should have found x", found_x);
+ assertTrue("Should have found y", found_y);
+ assertFalse("Should have only found x once", found_x_again);
+ assertFalse("Should have only found y once", found_y_again);
+ }
+
+ public void testMoveInSamePlace()
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ Node<Object, Object> rootNode = cache.getRoot();
+
+ final Fqn FQN_X = Fqn.fromString("/x");
+ // set up the initial structure.
+ Node aNode = rootNode.addChild(A);
+ Node xNode = aNode.addChild(FQN_X);
+ assertEquals(aNode.getChildren().size(), 1);
+
+ System.out.println("Before: " + TreeStructureSupport.printTree(cache,
true));
+
+ cache.move(xNode.getFqn(), aNode.getFqn());
+
+ System.out.println("After: " + TreeStructureSupport.printTree(cache,
true));
+
+ assertEquals(aNode.getChildren().size(), 1);
+
+ assertNoLocks();
+ }
+
+ protected CacheLoaderConfig getSingleCacheLoaderConfig(boolean passivation, String
preload, String cacheloaderClass, String properties, boolean async, boolean
fetchPersistentState, boolean shared, boolean purgeOnStartup) throws Exception
+ {
+ String xml =
+ " <loaders passivation=\"" + passivation +
"\" shared=\"" + shared + "\">\n" +
+ " <preload>\n" +
+ " <node fqn=\"" + preload +
"\"/>\n" +
+ " </preload>\n" +
+ " <loader class=\"" + cacheloaderClass +
"\" async=\"" + async + "\"
fetchPersistentState=\"" + fetchPersistentState + "\"\n" +
+ " purgeOnStartup=\"" +
purgeOnStartup + "\">\n" +
+ " <properties>\n" +
+ properties +
+ " </properties>\n" +
+ " </loader>\n" +
+ " </loaders>";
+ Element element = XmlConfigHelper.stringToElementInCoreNS(xml);
+ LoadersElementParser elementParser = new LoadersElementParser();
+ return elementParser.parseLoadersElement(element);
+ }
+
+ protected void checkLocks()
+ {
+ TreeCache<Object, Object> tree = cacheTL.get();
+ Cache<Object, Object> cache = tree.getCache();
+ ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
+ LockManager lm = cr.getComponent(LockManager.class);
+ InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
+
+// assert !TreeStructureSupport.isLocked(cache, A);
+// assert !TreeStructureSupport.isLocked(cache, Fqn.ROOT);
+
+ assert TreeStructureSupport.isLocked(cache, C);
+ assert TreeStructureSupport.isLocked(cache, A_B);
+ assert TreeStructureSupport.isLocked(cache, A_B_C);
+ }
+
+ protected void checkLocksDeep()
+ {
+ TreeCache<Object, Object> tree = cacheTL.get();
+ Cache<Object, Object> cache = tree.getCache();
+ ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
+ LockManager lm = cr.getComponent(LockManager.class);
+ InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
+
+// assert !TreeStructureSupport.isLocked(cache, A);
+// assert !TreeStructureSupport.isLocked(cache, Fqn.ROOT);
+// assert !TreeStructureSupport.isLocked(cache, A_B_D);
+
+ // /a/b, /c, /c/e, /a/b/c and /a/b/c/e should all be locked.
+ assert TreeStructureSupport.isLocked(cache, A_B);
+ assert TreeStructureSupport.isLocked(cache, C);
+ assert TreeStructureSupport.isLocked(cache, C_E);
+ assert TreeStructureSupport.isLocked(cache, A_B_C);
+ assert TreeStructureSupport.isLocked(cache, A_B_C_E);
+ }
+
+ protected void assertNoLocks()
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache.getCache());
+ LockManager lm = cr.getComponent(LockManager.class);
+ InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
+ LockAssert.assertNoLocks(lm, icc);
+ }
+
+ public void testNonexistentSource()
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ cache.put(A_B_C, "k", "v");
+ assert "v".equals(cache.get(A_B_C, "k"));
+ assert 1 == cache.getNode(A_B).getChildren().size();
+ assert cache.getNode(A_B).getChildrenNames().contains(C.getLastElement());
+ assert !cache.getNode(A_B).getChildrenNames().contains(D.getLastElement());
+
+ cache.move(D, A_B);
+
+ assert "v".equals(cache.get(A_B_C, "k"));
+ assert 1 == cache.getNode(A_B).getChildren().size();
+ assert cache.getNode(A_B).getChildrenNames().contains(C.getLastElement());
+ assert !cache.getNode(A_B).getChildrenNames().contains(D.getLastElement());
+ }
+
+ public void testNonexistentTarget()
+ {
+ TreeCache<Object, Object> cache = cacheTL.get();
+ cache.put(A_B_C, "k", "v");
+ assert "v".equals(cache.get(A_B_C, "k"));
+ assert 1 == cache.getNode(A_B).getChildren().size();
+ assert cache.getNode(A_B).getChildrenNames().contains(C.getLastElement());
+ assert null == cache.getNode(D);
+
+ System.out.println(TreeStructureSupport.printTree(cache, true));
+
+ cache.move(A_B, D);
+
+ System.out.println(TreeStructureSupport.printTree(cache, true));
+
+ assert null == cache.getNode(A_B_C);
+ assert null == cache.getNode(A_B);
+ assert null != cache.getNode(D);
+ assert null != cache.getNode(D_B);
+ assert null != cache.getNode(D_B_C);
+ assert "v".equals(cache.get(D_B_C, "k"));
+ }
+}
Added:
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeReplicatedMoveTest.java
===================================================================
---
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeReplicatedMoveTest.java
(rev 0)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/NodeReplicatedMoveTest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -0,0 +1,159 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at
gnu.org.
+ */
+package org.jboss.starobrno.tree.api;
+
+import org.jboss.starobrno.UnitTestCacheFactory;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.tree.Fqn;
+import org.jboss.starobrno.tree.Node;
+import org.jboss.starobrno.tree.TreeCache;
+import org.jboss.starobrno.tree.TreeCacheImpl;
+import org.jboss.starobrno.util.TestingUtil;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.transaction.TransactionManager;
+
+@Test(groups = {"functional", "jgroups", "pessimistic"},
testName = "api.NodeReplicatedMoveTest")
+public class NodeReplicatedMoveTest
+{
+ private class NodeReplicatedMoveTestTL
+ {
+ protected TreeCache<Object, Object> cache1;
+ protected TreeCache<Object, Object> cache2;
+ protected TransactionManager tm;
+ }
+
+ protected ThreadLocal<NodeReplicatedMoveTestTL> threadLocal = new
ThreadLocal<NodeReplicatedMoveTestTL>();
+
+ protected static final Fqn A = Fqn.fromString("/a"), B =
Fqn.fromString("/b"), C = Fqn.fromString("/c"), D =
Fqn.fromString("/d"), E = Fqn.fromString("/e");
+ protected static final Object k = "key", vA = "valueA", vB =
"valueB", vC = "valueC", vD = "valueD", vE =
"valueE";
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws Exception
+ {
+ NodeReplicatedMoveTestTL tl = new NodeReplicatedMoveTestTL();
+ threadLocal.set(tl);
+ Configuration c = new Configuration();
+ c.setInvocationBatchingEnabled(true);
+ c.setCacheMode(Configuration.CacheMode.REPL_SYNC);
+ c.setSyncCommitPhase(true);
+ c.setSyncRollbackPhase(true);
+ // start a single cache instance
+ tl.cache1 = new TreeCacheImpl<Object, Object>(new
UnitTestCacheFactory<Object, Object>().createCache(c.clone()));
+ tl.cache2 = new TreeCacheImpl<Object, Object>(new
UnitTestCacheFactory<Object, Object>().createCache(c.clone()));
+ tl.tm = tl.cache1.getConfiguration().getRuntimeConfig().getTransactionManager();
+
+ TestingUtil.blockUntilViewsReceived(10000, tl.cache1.getCache(),
tl.cache2.getCache());
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ NodeReplicatedMoveTestTL tl = threadLocal.get();
+ if (tl != null)
+ {
+ TestingUtil.killTreeCaches(tl.cache1, tl.cache2);
+ threadLocal.set(null);
+ }
+ }
+
+
+
+ public void testReplicatability()
+ {
+ NodeReplicatedMoveTestTL tl = threadLocal.get();
+ Node<Object, Object> rootNode = tl.cache1.getRoot();
+
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ Node<Object, Object> nodeB = nodeA.addChild(B);
+
+ nodeA.put(k, vA);
+ nodeB.put(k, vB);
+
+ assertEquals(vA, tl.cache1.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache1.getRoot().getChild(A).getChild(B).get(k));
+
+ assertEquals(vA, tl.cache2.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache2.getRoot().getChild(A).getChild(B).get(k));
+
+ // now move...
+ tl.cache1.move(nodeB.getFqn(), Fqn.ROOT);
+
+ assertEquals(vA, tl.cache1.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache1.getRoot().getChild(B).get(k));
+
+ assertEquals(vA, tl.cache2.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache2.getRoot().getChild(B).get(k));
+ }
+
+ public void testReplTxCommit() throws Exception
+ {
+ NodeReplicatedMoveTestTL tl = threadLocal.get();
+ Node<Object, Object> rootNode = tl.cache1.getRoot();
+ Fqn A_B = Fqn.fromRelativeFqn(A, B);
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ Node<Object, Object> nodeB = nodeA.addChild(B);
+
+ nodeA.put(k, vA);
+ nodeB.put(k, vB);
+
+ assertEquals(vA, tl.cache1.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache1.getRoot().getChild(A).getChild(B).get(k));
+
+ assertEquals(vA, tl.cache2.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache2.getRoot().getChild(A).getChild(B).get(k));
+
+ // now move...
+ tl.tm.begin();
+ tl.cache1.move(nodeB.getFqn(), Fqn.ROOT);
+
+ assertEquals(vA, tl.cache1.get(A, k));
+ assertNull(tl.cache1.get(A_B, k));
+ assertEquals(vB, tl.cache1.get(B, k));
+ tl.tm.commit();
+
+ assertEquals(vA, tl.cache1.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache1.getRoot().getChild(B).get(k));
+ assertEquals(vA, tl.cache2.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache2.getRoot().getChild(B).get(k));
+
+ }
+
+ public void testReplTxRollback() throws Exception
+ {
+ NodeReplicatedMoveTestTL tl = threadLocal.get();
+ Node<Object, Object> rootNode = tl.cache1.getRoot();
+ Node<Object, Object> nodeA = rootNode.addChild(A);
+ Node<Object, Object> nodeB = nodeA.addChild(B);
+
+ nodeA.put(k, vA);
+ nodeB.put(k, vB);
+
+ assertEquals(vA, tl.cache1.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache1.getRoot().getChild(A).getChild(B).get(k));
+ assertEquals(vA, tl.cache2.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache2.getRoot().getChild(A).getChild(B).get(k));
+
+ // now move...
+ tl.tm.begin();
+ tl.cache1.move(nodeB.getFqn(), Fqn.ROOT);
+
+ assertEquals(vA, tl.cache1.get(A, k));
+ assertEquals(vB, tl.cache1.get(B, k));
+
+ tl.tm.rollback();
+
+ assertEquals(vA, tl.cache1.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache1.getRoot().getChild(A).getChild(B).get(k));
+ assertEquals(vA, tl.cache2.getRoot().getChild(A).get(k));
+ assertEquals(vB, tl.cache2.getRoot().getChild(A).getChild(B).get(k));
+ }
+}
Added: core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTest.java
(rev 0)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at
gnu.org.
+ */
+
+package org.jboss.starobrno.tree.api;
+
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.UnitTestCacheFactory;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.tree.Fqn;
+import org.jboss.starobrno.tree.Node;
+import org.jboss.starobrno.tree.TreeCache;
+import org.jboss.starobrno.tree.TreeCacheImpl;
+import org.jboss.starobrno.util.TestingUtil;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author <a href="mailto:manik AT jboss DOT org">Manik Surtani (manik
AT jboss DOT org)</a>
+ */
+@Test(groups = {"functional", "jgroups", "pessimistic"},
sequential = true, testName = "api.SyncReplTest")
+public class SyncReplTest
+{
+ private CacheSPI<Object, Object> c1, c2;
+ private TreeCache<Object, Object> cache1, cache2;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp()
+ {
+ System.out.println("*** In setUp()");
+ Configuration c = new Configuration();
+ c.setCacheMode(Configuration.CacheMode.REPL_SYNC);
+ c.setInvocationBatchingEnabled(true);
+ c.setFetchInMemoryState(false);
+
+ c1 = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object,
Object>().createCache(c.clone());
+ c2 = (CacheSPI<Object, Object>) new UnitTestCacheFactory<Object,
Object>().createCache(c.clone());
+
+ TestingUtil.blockUntilViewsReceived(new Cache[]{c1, c2}, 5000);
+
+ cache1 = new TreeCacheImpl<Object, Object>(c1);
+ cache2 = new TreeCacheImpl<Object, Object>(c2);
+
+ System.out.println("*** Finished setUp()");
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ TestingUtil.killCaches(c1, c2);
+ cache1 = null;
+ cache2 = null;
+ }
+
+ public void testBasicOperation()
+ {
+ assertClusterSize("Should only be 2 caches in the cluster!!!", 2);
+
+ Fqn f = Fqn.fromString("/test/data");
+ String k = "key", v = "value";
+
+ assertNull("Should be null", cache1.getRoot().getChild(f));
+ assertNull("Should be null", cache2.getRoot().getChild(f));
+
+ Node<Object, Object> node = cache1.getRoot().addChild(f);
+
+ assertNotNull("Should not be null", node);
+
+ node.put(k, v);
+
+ assertEquals(v, node.get(k));
+ assertEquals(v, cache1.get(f, k));
+ assert v.equals(cache2.get(f, k));
+ }
+
+ public void testSyncRepl()
+ {
+ assertClusterSize("Should only be 2 caches in the cluster!!!", 2);
+
+ Fqn fqn = Fqn.fromString("/JSESSIONID/1010.10.5:3000/1234567890/1");
+ cache1.getConfiguration().setSyncCommitPhase(true);
+ cache2.getConfiguration().setSyncCommitPhase(true);
+
+
+ cache1.put(fqn, "age", 38);
+ assertEquals("Value should be set", 38, cache1.get(fqn,
"age"));
+ assertEquals("Value should have replicated", 38, cache2.get(fqn,
"age"));
+ }
+
+ public void testPutMap()
+ {
+ assertClusterSize("Should only be 2 caches in the cluster!!!", 2);
+
+ Fqn fqn = Fqn.fromString("/JSESSIONID/10.10.10.5:3000/1234567890/1");
+ Fqn fqn1 = Fqn.fromString("/JSESSIONID/10.10.10.5:3000/1234567890/2");
+
+ Map<Object, Object> map = new HashMap<Object, Object>();
+ map.put("1", "1");
+ map.put("2", "2");
+ cache1.getInvocationContext().getOptionOverrides().setSuppressLocking(true);
+ cache1.getRoot().addChild(fqn).putAll(map);
+ cache1.getInvocationContext().getOptionOverrides().setSuppressLocking(true);
+ assertEquals("Value should be set", "1", cache1.get(fqn,
"1"));
+
+ map = new HashMap<Object, Object>();
+ map.put("3", "3");
+ map.put("4", "4");
+ cache1.getInvocationContext().getOptionOverrides().setSuppressLocking(true);
+ cache1.getRoot().addChild(fqn1).putAll(map);
+
+ cache1.getInvocationContext().getOptionOverrides().setSuppressLocking(true);
+ assertEquals("Value should be set", "2", cache1.get(fqn,
"2"));
+ }
+
+
+ private void assertClusterSize(String message, int size)
+ {
+ assertClusterSize(message, size, cache1);
+ assertClusterSize(message, size, cache2);
+ }
+
+ private void assertClusterSize(String message, int size, TreeCache c)
+ {
+ assertEquals(message, size, c.getMembers().size());
+ }
+}
Added: core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTxTest.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTxTest.java
(rev 0)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/SyncReplTxTest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -0,0 +1,117 @@
+/*
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at
gnu.org.
+ */
+
+package org.jboss.starobrno.tree.api;
+
+import org.jboss.cache.transaction.DummyTransactionManagerLookup;
+import org.jboss.starobrno.Cache;
+import org.jboss.starobrno.CacheSPI;
+import org.jboss.starobrno.UnitTestCacheFactory;
+import org.jboss.starobrno.config.Configuration;
+import org.jboss.starobrno.tree.Fqn;
+import org.jboss.starobrno.tree.Node;
+import org.jboss.starobrno.tree.TreeCache;
+import org.jboss.starobrno.tree.TreeCacheImpl;
+import org.jboss.starobrno.util.TestingUtil;
+import static org.testng.AssertJUnit.*;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.transaction.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:manik AT jboss DOT org">Manik Surtani (manik
AT jboss DOT org)</a>
+ */
+@Test(groups = {"functional", "jgroups", "transaction",
"pessimistic"}, sequential = true, testName = "api.SyncReplTxTest")
+public class SyncReplTxTest
+{
+ private List<CacheSPI<Object, Object>> flatCaches;
+ private List<TreeCache<Object, Object>> caches;
+
+ @BeforeMethod(alwaysRun = true)
+ public void setUp() throws CloneNotSupportedException
+ {
+ System.out.println("*** In setUp()");
+ caches = new ArrayList<TreeCache<Object, Object>>();
+ flatCaches = new ArrayList<CacheSPI<Object, Object>>();
+ Configuration c = new Configuration();
+ c.setCacheMode(Configuration.CacheMode.REPL_SYNC);
+ c.setFetchInMemoryState(false);
+ c.setInvocationBatchingEnabled(true);
+ c.setSyncCommitPhase(true);
+ c.setSyncRollbackPhase(true);
+ c.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
+
+ CacheSPI<Object, Object> cache1 = (CacheSPI<Object, Object>) new
UnitTestCacheFactory<Object, Object>().createCache(c.clone());
+ CacheSPI<Object, Object> cache2 = (CacheSPI<Object, Object>) new
UnitTestCacheFactory<Object, Object>().createCache(c.clone());
+
+ flatCaches.add(cache1);
+ flatCaches.add(cache2);
+
+ TestingUtil.blockUntilViewsReceived(caches.toArray(new Cache[0]), 10000);
+
+ caches.add(new TreeCacheImpl<Object, Object>(cache1));
+ caches.add(new TreeCacheImpl<Object, Object>(cache2));
+
+ System.out.println("*** Finished setUp()");
+ }
+
+ @AfterMethod(alwaysRun = true)
+ public void tearDown()
+ {
+ System.out.println("*** In tearDown()");
+ TestingUtil.killTreeCaches(caches);
+ caches = null;
+ System.out.println("*** Finished tearDown()");
+ }
+
+ private TransactionManager beginTransaction(Cache<Object, Object> cache) throws
NotSupportedException, SystemException
+ {
+ TransactionManager mgr =
cache.getConfiguration().getRuntimeConfig().getTransactionManager();
+ mgr.begin();
+ return mgr;
+ }
+
+ public void testBasicOperation() throws SystemException, NotSupportedException,
HeuristicMixedException, HeuristicRollbackException, RollbackException
+ {
+ assertClusterSize("Should only be 2 caches in the cluster!!!", 2);
+
+ Fqn f = Fqn.fromString("/test/data");
+ String k = "key", v = "value";
+
+ assertNull("Should be null", caches.get(0).getRoot().getChild(f));
+ assertNull("Should be null", caches.get(1).getRoot().getChild(f));
+
+ Node<Object, Object> node = caches.get(0).getRoot().addChild(f);
+
+ assertNotNull("Should not be null", node);
+
+ TransactionManager tm = beginTransaction(caches.get(0).getCache());
+ node.put(k, v);
+ tm.commit();
+
+ assertEquals(v, node.get(k));
+ assertEquals(v, caches.get(0).get(f, k));
+ assertEquals("Should have replicated", v, caches.get(1).get(f, k));
+ }
+
+ private void assertClusterSize(String message, int size)
+ {
+ for (Cache<Object, Object> c : flatCaches)
+ {
+ assertClusterSize(message, size, c);
+ }
+ }
+
+ private void assertClusterSize(String message, int size, Cache<Object, Object>
c)
+ {
+ assertEquals(message, size, c.getMembers().size());
+ }
+}
\ No newline at end of file
Modified:
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java
===================================================================
---
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java 2008-11-28
01:42:18 UTC (rev 7226)
+++
core/branches/flat/src/test/java/org/jboss/starobrno/tree/api/TreeCacheAPITest.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -44,7 +44,7 @@
@AfterMethod(alwaysRun = true)
public void tearDown()
{
- if (cache != null) TestingUtil.killCaches(cache.getCache());
+ TestingUtil.killTreeCaches(cache);
cache = null;
}
Modified: core/branches/flat/src/test/java/org/jboss/starobrno/util/TestingUtil.java
===================================================================
--- core/branches/flat/src/test/java/org/jboss/starobrno/util/TestingUtil.java 2008-11-28
01:42:18 UTC (rev 7226)
+++ core/branches/flat/src/test/java/org/jboss/starobrno/util/TestingUtil.java 2008-11-28
03:39:39 UTC (rev 7227)
@@ -17,12 +17,14 @@
import org.jboss.starobrno.interceptors.InterceptorChain;
import org.jboss.starobrno.interceptors.base.CommandInterceptor;
import org.jboss.starobrno.lock.LockManager;
+import org.jboss.starobrno.tree.TreeCache;
import org.jgroups.JChannel;
import javax.transaction.TransactionManager;
import java.io.File;
import java.lang.reflect.Field;
import java.util.Arrays;
+import java.util.Collection;
import java.util.List;
import java.util.Random;
@@ -412,6 +414,24 @@
f.delete();
}
+ public static void killTreeCaches(Collection treeCaches)
+ {
+ if (treeCaches != null) killTreeCaches((TreeCache[]) treeCaches.toArray(new
TreeCache[]{}));
+ }
+
+ public static void killCaches(Collection caches)
+ {
+ if (caches != null) killCaches((Cache[]) caches.toArray(new Cache[]{}));
+ }
+
+ public static void killTreeCaches(TreeCache... treeCaches)
+ {
+ for (TreeCache tc: treeCaches)
+ {
+ if (tc != null) killCaches(tc.getCache());
+ }
+ }
+
/**
* Kills a cache - stops it, clears any data in any cache loaders, and rolls back any
associated txs
*/