Author: manik.surtani(a)jboss.com
Date: 2008-07-07 15:38:22 -0400 (Mon, 07 Jul 2008)
New Revision: 6193
Added:
core/trunk/src/test/java/org/jboss/cache/api/mvcc/NodeMoveMvccTestBase.java
Modified:
core/trunk/src/main/java/org/jboss/cache/Cache.java
core/trunk/src/main/java/org/jboss/cache/Fqn.java
core/trunk/src/main/java/org/jboss/cache/commands/legacy/write/PessMoveCommand.java
core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java
core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java
core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java
core/trunk/src/test/java/org/jboss/cache/FqnTest.java
core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveMvccTest.java
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveMvccTest.java
core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveOptimisticTest.java
Log:
Improved various mvcc move implementation
Modified: core/trunk/src/main/java/org/jboss/cache/Cache.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/Cache.java 2008-07-07 19:34:48 UTC (rev
6192)
+++ core/trunk/src/main/java/org/jboss/cache/Cache.java 2008-07-07 19:38:22 UTC (rev
6193)
@@ -419,6 +419,13 @@
* /a/e
* </pre>
* No-op if the node to be moved is the root node.
+ * <p/>
+ * <b>Note</b>: As of 3.0.0 and when using MVCC locking, more specific
behaviour is defined as follows:
+ * <ul>
+ * <li>A no-op if the node is moved unto itself. E.g., <tt>move(fqn,
fqn.getParent())</tt> will not do anything.</li>
+ * <li>If a target node does not exist it will be created silently, to be more
consistent with other APIs such as <tt>put()</tt> on a nonexistent
node.</li>
+ * <li>If the source node does not exist this is a no-op, to be more consistent
with other APIs such as <tt>get()</tt> on a nonexistent node.</li>
+ * </ul>
*
* @param nodeToMove the Fqn of the node to move.
* @param newParent new location under which to attach the node being moved.
Modified: core/trunk/src/main/java/org/jboss/cache/Fqn.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/Fqn.java 2008-07-07 19:34:48 UTC (rev 6192)
+++ core/trunk/src/main/java/org/jboss/cache/Fqn.java 2008-07-07 19:38:22 UTC (rev 6193)
@@ -670,4 +670,18 @@
{
return FqnComparator.INSTANCE.compare(this, Fqn);
}
+
+ /**
+ * Creates a new Fqn whose ancestor has been replaced with the new ancestor passed
in.
+ *
+ * @param newAncestor
+ * @return a new Fqn
+ */
+ public Fqn replaceAncestor(Fqn oldAncestor, Fqn newAncestor)
+ {
+ if (!isChildOf(oldAncestor))
+ throw new IllegalArgumentException("Old ancestor must be an ancestor of the
current Fqn!");
+ Fqn subFqn = this.getSubFqn(oldAncestor.size(), size());
+ return Fqn.fromRelativeFqn(newAncestor, subFqn);
+ }
}
\ No newline at end of file
Modified:
core/trunk/src/main/java/org/jboss/cache/commands/legacy/write/PessMoveCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/legacy/write/PessMoveCommand.java 2008-07-07
19:34:48 UTC (rev 6192)
+++
core/trunk/src/main/java/org/jboss/cache/commands/legacy/write/PessMoveCommand.java 2008-07-07
19:38:22 UTC (rev 6193)
@@ -1,8 +1,11 @@
package org.jboss.cache.commands.legacy.write;
import org.jboss.cache.Fqn;
+import org.jboss.cache.NodeNotExistsException;
+import org.jboss.cache.NodeSPI;
import org.jboss.cache.commands.legacy.ReversibleCommand;
import org.jboss.cache.commands.write.MoveCommand;
+import org.jboss.cache.invocation.InvocationContext;
/**
* A version of {@link org.jboss.cache.commands.write.MoveCommand} which can be rolled
back, for use with
@@ -22,6 +25,65 @@
super(from, to);
}
+ /**
+ * Moves a node, from <tt>fqn</tt> to <tt>to</tt>, and returns
null.
+ *
+ * @param ctx invocation context
+ * @return null
+ */
+ @Override
+ public Object perform(InvocationContext ctx)
+ {
+ move(fqn, to, false, ctx);
+ return null;
+ }
+
+ private void adjustFqn(NodeSPI node, Fqn newBase)
+ {
+ Fqn newFqn = Fqn.fromRelativeElements(newBase, node.getFqn().getLastElement());
+ node.setFqn(newFqn);
+ }
+
+ private void move(Fqn toMoveFqn, Fqn newParentFqn, boolean skipNotifications,
InvocationContext ctx)
+ {
+ // the actual move algorithm.
+ // ctx *could* be null if this is a rollback!!! Sucks big time.
+ NodeSPI newParent = ctx == null ? dataContainer.peek(newParentFqn) :
ctx.lookUpNode(newParentFqn);
+ if (newParent == null || newParent.isDeleted())
+ {
+ throw new NodeNotExistsException("New parent node " + newParentFqn +
" does not exist when attempting to move node!!");
+ }
+
+ // ctx *could* be null if this is a rollback!!! Sucks big time.
+ NodeSPI node = ctx == null ? dataContainer.peek(toMoveFqn) :
ctx.lookUpNode(toMoveFqn);
+
+ if (node == null || node.isDeleted())
+ {
+ throw new NodeNotExistsException("Node " + toMoveFqn + " does not
exist when attempting to move node!!");
+ }
+
+ if (trace) log.trace("Moving " + fqn + " to sit under " + to);
+
+ NodeSPI oldParent = node.getParentDirect();
+ Object nodeName = toMoveFqn.getLastElement();
+
+ // now that we have the parent and target nodes:
+ // first correct the pointers at the pruning point
+ oldParent.removeChildDirect(nodeName);
+ newParent.addChild(nodeName, node);
+ // parent pointer is calculated on the fly using Fqns.
+
+ // notify
+ if (!skipNotifications)
+ notifier.notifyNodeMoved(toMoveFqn, Fqn.fromRelativeElements(newParentFqn,
toMoveFqn.getLastElement()), true, ctx);
+
+ // now adjust Fqns of node and all children.
+ adjustFqn(node, newParent.getFqn());
+
+ if (!skipNotifications)
+ notifier.notifyNodeMoved(toMoveFqn, Fqn.fromRelativeElements(newParentFqn,
toMoveFqn.getLastElement()), false, ctx);
+ }
+
public void rollback()
{
move(Fqn.fromRelativeElements(to, fqn.getLastElement()), fqn.getParent(), true,
null);
Modified: core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java 2008-07-07
19:34:48 UTC (rev 6192)
+++ core/trunk/src/main/java/org/jboss/cache/commands/write/MoveCommand.java 2008-07-07
19:38:22 UTC (rev 6193)
@@ -4,7 +4,6 @@
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.DataContainer;
import org.jboss.cache.Fqn;
-import org.jboss.cache.NodeNotExistsException;
import org.jboss.cache.NodeSPI;
import org.jboss.cache.commands.Visitor;
import org.jboss.cache.commands.WriteCommand;
@@ -13,21 +12,22 @@
import org.jboss.cache.notifications.Notifier;
import org.jboss.cache.transaction.GlobalTransaction;
+import java.util.Map;
+
/**
* Implements functionality defined by {@link
org.jboss.cache.Cache#move(org.jboss.cache.Fqn, org.jboss.cache.Fqn)}
*
* @author Mircea.Markus(a)jboss.com
* @since 2.2
*/
-// TODO: 2.2.0: Make sure this is properly intercepted, i.e., locked and loaded!!
public class MoveCommand extends AbstractDataCommand implements WriteCommand
{
public static final int METHOD_ID = 36;
- private static final Log log = LogFactory.getLog(MoveCommand.class);
- private static final boolean trace = log.isTraceEnabled();
+ protected static final Log log = LogFactory.getLog(MoveCommand.class);
+ protected static final boolean trace = log.isTraceEnabled();
/* dependencies */
- private Notifier notifier;
+ protected Notifier notifier;
/* params */
protected Fqn to;
@@ -67,59 +67,57 @@
*/
public Object perform(InvocationContext ctx)
{
- move(fqn, to, false, ctx);
- return null;
- }
-
- private void adjustFqn(NodeSPI node, Fqn newBase)
- {
- Fqn newFqn = Fqn.fromRelativeElements(newBase, node.getFqn().getLastElement());
- node.setFqn(newFqn);
- }
-
- public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
- {
- return visitor.visitMoveCommand(ctx, this);
- }
-
- protected void move(Fqn toMoveFqn, Fqn newParentFqn, boolean skipNotifications,
InvocationContext ctx)
- {
- // the actual move algorithm.
- // ctx *could* be null if this is a rollback!!! Sucks big time.
- NodeSPI newParent = ctx == null ? dataContainer.peek(newParentFqn) :
ctx.lookUpNode(newParentFqn);
- if (newParent == null || newParent.isDeleted())
+ if (to.equals(fqn.getParent()))
{
- throw new NodeNotExistsException("New parent node " + newParentFqn +
" does not exist when attempting to move node!!");
+ if (log.isDebugEnabled()) log.debug("Attempting to move " + fqn +
" onto itself. Nothing to do.");
+ return null;
}
- // ctx *could* be null if this is a rollback!!! Sucks big time.
- NodeSPI node = ctx == null ? dataContainer.peek(toMoveFqn) :
ctx.lookUpNode(toMoveFqn);
+ NodeSPI node = ctx.lookUpNode(fqn);
if (node == null || node.isDeleted())
{
- throw new NodeNotExistsException("Node " + toMoveFqn + " does not
exist when attempting to move node!!");
+ if (trace) log.trace("Node " + fqn + " does not exist when
attempting to move node! Not doing anything.");
+ return null;
}
if (trace) log.trace("Moving " + fqn + " to sit under " + to);
- NodeSPI oldParent = node.getParentDirect();
- Object nodeName = toMoveFqn.getLastElement();
+ // the actual move algorithm.
+ NodeSPI newNode = ctx.lookUpNode(Fqn.fromRelativeElements(to,
fqn.getLastElement()));
+ Fqn newNodeFqn = newNode.getFqn();
- // now that we have the parent and target nodes:
- // first correct the pointers at the pruning point
- oldParent.removeChildDirect(nodeName);
- newParent.addChild(nodeName, node);
- // parent pointer is calculated on the fly using Fqns.
+ // at this stage all child node objects we need have been created and are available
in the ctx.
+ // we just need to mark old ones as deleted, new ones as created, and move data
across.
+ notifier.notifyNodeMoved(fqn, newNodeFqn, true, ctx);
+ moveRecursively(node, newNode, ctx);
+ notifier.notifyNodeMoved(fqn, newNodeFqn, false, ctx);
+ return null;
+ }
- // notify
- if (!skipNotifications)
- notifier.notifyNodeMoved(toMoveFqn, Fqn.fromRelativeElements(newParentFqn,
toMoveFqn.getLastElement()), true, ctx);
+ private void moveRecursively(NodeSPI oldNode, NodeSPI newNode, InvocationContext ctx)
+ {
+ if (trace) log.trace("Moving " + oldNode.getFqn() + " to " +
newNode.getFqn());
+ // start deep.
+ Map<Object, NodeSPI> children = oldNode.getChildrenMapDirect();
+ if (children != null && !children.isEmpty())
+ {
+ for (NodeSPI child : children.values())
+ {
+ Fqn childFqn = child.getFqn();
+ Fqn newChildFqn = childFqn.replaceAncestor(oldNode.getFqn(),
newNode.getFqn());
+ moveRecursively(ctx.lookUpNode(childFqn), ctx.lookUpNode(newChildFqn), ctx);
+ }
+ }
- // now adjust Fqns of node and all children.
- adjustFqn(node, newParent.getFqn());
+ // now swap the data for the current node.
+ newNode.putAllDirect(oldNode.getDataDirect());
+ oldNode.markAsDeleted(true);
+ }
- if (!skipNotifications)
- notifier.notifyNodeMoved(toMoveFqn, Fqn.fromRelativeElements(newParentFqn,
toMoveFqn.getLastElement()), false, ctx);
+ public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
+ {
+ return visitor.visitMoveCommand(ctx, this);
}
public Fqn getTo()
Modified:
core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java 2008-07-07
19:34:48 UTC (rev 6192)
+++
core/trunk/src/main/java/org/jboss/cache/interceptors/MVCCLockingInterceptor.java 2008-07-07
19:38:22 UTC (rev 6193)
@@ -298,16 +298,23 @@
{
// nodes we need to get WLs for:
// node we are moving FROM (and it's parent and children.) Same as
removeNode.
- List<Fqn> children = addNodeAndParentForRemoval(ctx, command.getFqn(),
true);
+ List<Fqn> nodeAndChildren = addNodeAndParentForRemoval(ctx, command.getFqn(),
true);
+ Fqn newParent = command.getTo();
+ Fqn oldParent = command.getFqn().getParent();
+
// now lock the new parent.
- getWrappedNode(ctx, command.getTo(), true, true, false);
+ getWrappedNode(ctx, newParent, true, true, false);
- // the children list contains all child nodes, including the node itself.
- // now obtain locks on the new places these children will occupy.
- for (Fqn f : children)
+ if (!oldParent.equals(newParent) && nodeAndChildren != null)
{
- getWrappedNode(ctx, Fqn.fromRelativeFqn(command.getTo(), f), true, true, true);
+ // the nodeAndChildren list contains all child nodes, including the node
itself.
+ // now obtain locks on the new places these new nodes will occupy.
+ for (Fqn f : nodeAndChildren)
+ {
+ Fqn newChildFqn = f.replaceAncestor(oldParent, newParent);
+ getWrappedNode(ctx, newChildFqn, true, true, true);
+ }
}
// now pass up the chain.
Modified: core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java 2008-07-07 19:34:48
UTC (rev 6192)
+++ core/trunk/src/main/java/org/jboss/cache/mvcc/NodeReference.java 2008-07-07 19:38:22
UTC (rev 6193)
@@ -294,4 +294,23 @@
"delegate=" + delegate +
'}';
}
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ NodeReference that = (NodeReference) o;
+
+ if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null)
return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return (delegate != null ? delegate.hashCode() : 0);
+ }
}
Modified: core/trunk/src/test/java/org/jboss/cache/FqnTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/FqnTest.java 2008-07-07 19:34:48 UTC (rev
6192)
+++ core/trunk/src/test/java/org/jboss/cache/FqnTest.java 2008-07-07 19:38:22 UTC (rev
6193)
@@ -432,6 +432,24 @@
System.out.println("-- " + msg);
}
+ public void testReplacingDirectAncestor()
+ {
+ Fqn fqn = Fqn.fromString("/a/b/c");
+ Fqn newParent = Fqn.fromString("/hot/dog");
+ Fqn expectedNewChild = Fqn.fromString("/hot/dog/c");
+
+ assert expectedNewChild.equals(fqn.replaceAncestor(fqn.getParent(), newParent));
+ }
+
+ public void testReplacingindirectAncestor()
+ {
+ Fqn fqn = Fqn.fromString("/a/b/c");
+ Fqn newParent = Fqn.fromString("/hot/dog");
+ Fqn expectedNewChild = Fqn.fromString("/hot/dog/b/c");
+
+ assert expectedNewChild.equals(fqn.replaceAncestor(fqn.getParent().getParent(),
newParent));
+ }
+
public void testDifferentFactories()
{
Fqn[] fqns = new Fqn[7];
Modified: core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java 2008-07-07 19:34:48
UTC (rev 6192)
+++ core/trunk/src/test/java/org/jboss/cache/api/NodeMoveAPITest.java 2008-07-07 19:38:22
UTC (rev 6193)
@@ -69,7 +69,6 @@
// to be overridden
}
- @Test(groups = {"functional"})
public void testBasicMove()
{
nodeA = rootNode.addChild(A);
@@ -134,7 +133,6 @@
return (Node<Object, Object>) node;
}
- @Test(groups = {"functional"})
public void testMoveWithChildren()
{
nodeA = rootNode.addChild(A);
@@ -203,7 +201,6 @@
assertEquals(nodeD, nodeE.getParent());
}
- @Test(groups = {"functional"})
public void testTxCommit() throws Exception
{
nodeA = rootNode.addChild(A);
@@ -231,7 +228,6 @@
assertTrue(nodeA.getChildren().isEmpty());
}
- @Test(groups = {"functional"})
public void testTxRollback() throws Exception
{
nodeA = rootNode.addChild(A);
@@ -248,7 +244,7 @@
cache.move(nodeB.getFqn(), Fqn.ROOT);
// need to think of a way to test the same with optimistically locked nodes
- if (!isOptimistic())
+ if (nodeLockingScheme == NodeLockingScheme.PESSIMISTIC)
{
assertEquals(rootNode, nodeA.getParent());
assertEquals(rootNode, nodeB.getParent());
@@ -270,25 +266,21 @@
assertEquals(nodeB, nodeA.getChildren().iterator().next());
}
- @Test(groups = {"functional"})
public void testWithCacheloaders() throws Exception
{
doCacheLoaderTest(false, false);
}
- @Test(groups = {"functional"})
public void testWithPassivation() throws Exception
{
doCacheLoaderTest(true, false);
}
- @Test(groups = {"functional"})
public void testWithCacheloadersTx() throws Exception
{
doCacheLoaderTest(false, true);
}
- @Test(groups = {"functional"})
public void testWithPassivationTx() throws Exception
{
doCacheLoaderTest(true, true);
@@ -296,7 +288,6 @@
protected void doCacheLoaderTest(boolean pasv, boolean useTx) throws Exception
{
-// cache.stop();
cache.destroy();
cache.getConfiguration().setCacheLoaderConfig(getSingleCacheLoaderConfig(pasv,
"/", DummyInMemoryCacheLoader.class.getName(), null, false, false, false,
false));
cache.start();
@@ -372,27 +363,26 @@
}
- @Test(groups = {"functional"})
public void testLocksDeepMove() throws Exception
{
nodeA = rootNode.addChild(A);
nodeB = nodeA.addChild(B);
nodeD = nodeB.addChild(D);
nodeC = rootNode.addChild(C);
+ nodeE = nodeC.addChild(E);
assertEquals(0, cache.getNumberOfLocksHeld());
tm.begin();
cache.move(nodeC.getFqn(), nodeB.getFqn());
- // nodeC should have a RL, nodeA should have a RL, nodeB should have a WL,
nodeD should have a WL
- assertEquals("ROOT should have a RL, nodeC should have a RL, nodeA should have
a RL, nodeB should have a WL, nodeD should have a WL", 5,
cache.getNumberOfLocksHeld());
+ checkLocksDeep();
+
tm.commit();
assertEquals(0, cache.getNumberOfLocksHeld());
}
- @Test(groups = {"functional"})
public void testLocks() throws Exception
{
nodeA = rootNode.addChild(A);
@@ -414,17 +404,18 @@
assertEquals("ROOT should have a RL, nodeC should have a RL, nodeA should have
a RL, nodeB should have a WL", 4, cache.getNumberOfLocksHeld());
}
+ protected void checkLocksDeep()
+ {
+ assertEquals("ROOT should have a RL, nodeC should have a RL, nodeA should have
a RL, nodeB should have a WL, nodeD should have a WL", 6,
cache.getNumberOfLocksHeld());
+ }
+
protected void assertNoLocks()
{
assertEquals(0, cache.getNumberOfLocksHeld());
}
- @Test(groups = {"functional"})
public void testConcurrency() throws InterruptedException
{
- // FIXME: investigate intermittent failure when in isOptimistic() mode.
- if (isOptimistic()) return;
-
final int N = 3;// number of threads
final int loops = 1 << 6;// number of loops
// tests a tree structure as such:
@@ -536,7 +527,6 @@
assertFalse("Should have only found y once", found_y_again);
}
- @Test(groups = {"functional"})
public void testMoveInSamePlace()
{
final Fqn<String> FQN_X = Fqn.fromString("/x");
@@ -546,6 +536,8 @@
assertEquals(aNode.getChildren().size(), 1);
cache.move(xNode.getFqn(), aNode.getFqn());
assertEquals(aNode.getChildren().size(), 1);
+
+ assert 0 == cache.getNumberOfLocksHeld();
}
protected CacheLoaderConfig getSingleCacheLoaderConfig(boolean passivation, String
preload, String cacheloaderClass, String properties, boolean async, boolean
fetchPersistentState, boolean shared, boolean purgeOnStartup) throws Exception
@@ -569,6 +561,6 @@
protected boolean isOptimistic()
{
- return nodeLockingScheme == NodeLockingScheme.OPTIMISTIC;
+ return false;
}
}
Added: core/trunk/src/test/java/org/jboss/cache/api/mvcc/NodeMoveMvccTestBase.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/api/mvcc/NodeMoveMvccTestBase.java
(rev 0)
+++ core/trunk/src/test/java/org/jboss/cache/api/mvcc/NodeMoveMvccTestBase.java 2008-07-07
19:38:22 UTC (rev 6193)
@@ -0,0 +1,104 @@
+package org.jboss.cache.api.mvcc;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.api.NodeMoveAPITest;
+import org.jboss.cache.config.Configuration.NodeLockingScheme;
+import org.jboss.cache.factories.ComponentRegistry;
+import org.jboss.cache.invocation.InvocationContextContainer;
+import org.jboss.cache.lock.LockManager;
+import org.jboss.cache.util.TestingUtil;
+import org.testng.annotations.Test;
+
+@Test(groups = {"functional", "mvcc"})
+public abstract class NodeMoveMvccTestBase extends NodeMoveAPITest
+{
+ Fqn A_B = Fqn.fromRelativeFqn(A, B);
+ Fqn A_B_C = Fqn.fromRelativeFqn(A_B, C);
+ Fqn A_B_C_E = Fqn.fromRelativeFqn(A_B_C, E);
+ Fqn A_B_D = Fqn.fromRelativeFqn(A_B, D);
+ Fqn C_E = Fqn.fromRelativeFqn(C, E);
+ Fqn D_B = Fqn.fromRelativeFqn(D, B);
+ Fqn D_B_C = Fqn.fromRelativeFqn(D_B, C);
+
+
+ public NodeMoveMvccTestBase()
+ {
+ nodeLockingScheme = NodeLockingScheme.MVCC;
+ }
+
+ @Override
+ protected void checkLocks()
+ {
+ ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
+ LockManager lm = cr.getComponent(LockManager.class);
+ InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
+
+ LockAssert.assertNotLocked(A, lm, icc);
+ LockAssert.assertNotLocked(Fqn.ROOT, lm, icc);
+ LockAssert.assertLocked(C, lm, icc);
+ LockAssert.assertLocked(A_B, lm, icc);
+ LockAssert.assertLocked(A_B_C, lm, icc);
+ }
+
+ @Override
+ protected void checkLocksDeep()
+ {
+ ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
+ LockManager lm = cr.getComponent(LockManager.class);
+ InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
+
+ LockAssert.assertNotLocked(A, lm, icc);
+ LockAssert.assertNotLocked(Fqn.ROOT, lm, icc);
+ LockAssert.assertNotLocked(A_B_D, lm, icc);
+
+ // /a/b, /c, /c/e, /a/b/c and /a/b/c/e should all be locked.
+ LockAssert.assertLocked(A_B, lm, icc);
+ LockAssert.assertLocked(C, lm, icc);
+ LockAssert.assertLocked(C_E, lm, icc);
+ LockAssert.assertLocked(A_B_C, lm, icc);
+ LockAssert.assertLocked(A_B_C_E, lm, icc);
+ }
+
+ @Override
+ protected void assertNoLocks()
+ {
+ ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
+ LockManager lm = cr.getComponent(LockManager.class);
+ InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
+ LockAssert.assertNoLocks(lm, icc);
+ }
+
+ public void testNonexistentSource()
+ {
+ 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()
+ {
+ 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);
+
+ cache.move(A_B, D);
+
+ 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"));
+ }
+}
Modified:
core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveMvccTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveMvccTest.java 2008-07-07
19:34:48 UTC (rev 6192)
+++
core/trunk/src/test/java/org/jboss/cache/api/mvcc/read_committed/NodeMoveMvccTest.java 2008-07-07
19:38:22 UTC (rev 6193)
@@ -6,52 +6,17 @@
*/
package org.jboss.cache.api.mvcc.read_committed;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.api.NodeMoveAPITest;
-import org.jboss.cache.api.mvcc.LockAssert;
+import org.jboss.cache.api.mvcc.NodeMoveMvccTestBase;
import org.jboss.cache.config.Configuration;
-import org.jboss.cache.config.Configuration.NodeLockingScheme;
-import org.jboss.cache.factories.ComponentRegistry;
-import org.jboss.cache.invocation.InvocationContextContainer;
import org.jboss.cache.lock.IsolationLevel;
-import org.jboss.cache.lock.LockManager;
-import org.jboss.cache.util.TestingUtil;
import org.testng.annotations.Test;
@Test(groups = {"functional", "mvcc"})
-public class NodeMoveMvccTest extends NodeMoveAPITest
+public class NodeMoveMvccTest extends NodeMoveMvccTestBase
{
- public NodeMoveMvccTest()
- {
- nodeLockingScheme = NodeLockingScheme.MVCC;
- }
-
@Override
protected void configure(Configuration c)
{
c.setIsolationLevel(IsolationLevel.READ_COMMITTED);
}
-
- @Override
- protected void checkLocks()
- {
- ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
- LockManager lm = cr.getComponent(LockManager.class);
- InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
-
- LockAssert.assertNotLocked(A, lm, icc);
- LockAssert.assertLocked(Fqn.ROOT, lm, icc);
- LockAssert.assertLocked(C, lm, icc);
- LockAssert.assertLocked(Fqn.fromRelativeFqn(A, B), lm, icc);
- LockAssert.assertLocked(Fqn.fromRelativeFqn(B, C), lm, icc);
- }
-
- @Override
- protected void assertNoLocks()
- {
- ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
- LockManager lm = cr.getComponent(LockManager.class);
- InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
- LockAssert.assertNoLocks(lm, icc);
- }
}
\ No newline at end of file
Modified:
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveMvccTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveMvccTest.java 2008-07-07
19:34:48 UTC (rev 6192)
+++
core/trunk/src/test/java/org/jboss/cache/api/mvcc/repeatable_read/NodeMoveMvccTest.java 2008-07-07
19:38:22 UTC (rev 6193)
@@ -6,52 +6,17 @@
*/
package org.jboss.cache.api.mvcc.repeatable_read;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.api.NodeMoveAPITest;
-import org.jboss.cache.api.mvcc.LockAssert;
+import org.jboss.cache.api.mvcc.NodeMoveMvccTestBase;
import org.jboss.cache.config.Configuration;
-import org.jboss.cache.config.Configuration.NodeLockingScheme;
-import org.jboss.cache.factories.ComponentRegistry;
-import org.jboss.cache.invocation.InvocationContextContainer;
import org.jboss.cache.lock.IsolationLevel;
-import org.jboss.cache.lock.LockManager;
-import org.jboss.cache.util.TestingUtil;
import org.testng.annotations.Test;
@Test(groups = {"functional", "mvcc"})
-public class NodeMoveMvccTest extends NodeMoveAPITest
+public class NodeMoveMvccTest extends NodeMoveMvccTestBase
{
- public NodeMoveMvccTest()
- {
- nodeLockingScheme = NodeLockingScheme.MVCC;
- }
-
@Override
protected void configure(Configuration c)
{
c.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
}
-
- @Override
- protected void checkLocks()
- {
- ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
- LockManager lm = cr.getComponent(LockManager.class);
- InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
-
- LockAssert.assertNotLocked(A, lm, icc);
- LockAssert.assertLocked(Fqn.ROOT, lm, icc);
- LockAssert.assertLocked(C, lm, icc);
- LockAssert.assertLocked(Fqn.fromRelativeFqn(A, B), lm, icc);
- LockAssert.assertLocked(Fqn.fromRelativeFqn(Fqn.fromRelativeFqn(A, B), C), lm,
icc);
- }
-
- @Override
- protected void assertNoLocks()
- {
- ComponentRegistry cr = TestingUtil.extractComponentRegistry(cache);
- LockManager lm = cr.getComponent(LockManager.class);
- InvocationContextContainer icc =
cr.getComponent(InvocationContextContainer.class);
- LockAssert.assertNoLocks(lm, icc);
- }
}
Modified:
core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveOptimisticTest.java
===================================================================
---
core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveOptimisticTest.java 2008-07-07
19:34:48 UTC (rev 6192)
+++
core/trunk/src/test/java/org/jboss/cache/api/optimistic/NodeMoveOptimisticTest.java 2008-07-07
19:38:22 UTC (rev 6193)
@@ -18,13 +18,27 @@
nodeLockingScheme = NodeLockingScheme.OPTIMISTIC;
}
+ @Override
+ protected boolean isOptimistic()
+ {
+ return true;
+ }
+
+ @Override
public void testLocks()
{
// no op
}
+ @Override
public void testLocksDeepMove()
{
// no op
}
+
+ @Override
+ public void testConcurrency()
+ {
+ // no op
+ }
}