Index: src/main/java/org/apache/jackrabbit/core/state/ChangeLog.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/ChangeLog.java (revision 788664)
+++ src/main/java/org/apache/jackrabbit/core/state/ChangeLog.java (working copy)
@@ -160,6 +160,18 @@
}
/**
+ * Returns a flag indicating whether a given item state is marked as
+ * modified in this log.
+ *
+ * @param id the id of the item.
+ * @return true if the item state is marked as modified in this
+ * log; false otherwise.
+ */
+ public boolean isModified(ItemId id) {
+ return modifiedStates.containsKey(id);
+ }
+
+ /**
* Return a node references object given its id. Returns
* null if the node reference is not in the modified
* section.
Index: src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (revision 788664)
+++ src/main/java/org/apache/jackrabbit/core/state/LocalItemStateManager.java (working copy)
@@ -411,9 +411,7 @@
cache.cache(local);
}
}
- if (local != null) {
- dispatcher.notifyStateCreated(created);
- }
+ dispatcher.notifyStateCreated(created);
}
/**
Index: src/main/java/org/apache/jackrabbit/core/state/NodeStateMerger.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/NodeStateMerger.java (revision 788664)
+++ src/main/java/org/apache/jackrabbit/core/state/NodeStateMerger.java (working copy)
@@ -102,7 +102,7 @@
for (ChildNodeEntry cne : state.getAddedChildNodeEntries()) {
- if (context.isAdded(cne.getId())) {
+ if (context.isAdded(cne.getId()) || context.isModified(cne.getId())) {
// a new child node entry has been added to this state;
// check for name collisions with other state
if (overlayedState.hasChildNodeEntry(cne.getName())) {
@@ -117,13 +117,17 @@
}
added.add(cne);
+ } else {
+ // externally added
}
}
for (ChildNodeEntry cne : state.getRemovedChildNodeEntries()) {
- if (context.isDeleted(cne.getId())) {
+ if (context.isDeleted(cne.getId()) || context.isModified(cne.getId())) {
// a child node entry has been removed from this node state
removed.add(cne);
+ } else {
+ // externally removed
}
}
@@ -148,14 +152,6 @@
PropertyId propId =
new PropertyId(state.getNodeId(), name);
if (context.isAdded(propId)) {
- // a new property name has been added to this state;
- // check for name collisions
- if (overlayedState.hasPropertyName(name)
- || overlayedState.hasChildNodeEntry(name)) {
- // conflicting names
- return false;
- }
-
added.add(name);
}
}
@@ -195,6 +191,7 @@
static interface MergeContext {
boolean isAdded(ItemId id);
boolean isDeleted(ItemId id);
+ boolean isModified(ItemId id);
boolean allowsSameNameSiblings(NodeId id);
}
}
Index: src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java (revision 788664)
+++ src/main/java/org/apache/jackrabbit/core/state/SessionItemStateManager.java (working copy)
@@ -787,9 +787,23 @@
// local state was created
ItemState transientState = transientStore.get(created.getId());
if (transientState != null) {
- // underlying state has been permanently created
- transientState.pull();
- transientState.setStatus(ItemState.STATUS_EXISTING);
+ if (transientState.hasOverlayedState()) {
+ // underlying state has been permanently created
+ transientState.pull();
+ transientState.setStatus(ItemState.STATUS_EXISTING);
+ } else {
+ // this is a notification from another session
+ try {
+ ItemState local = stateMgr.getItemState(created.getId());
+ transientState.connect(local);
+ // update mod count
+ transientState.setModCount(local.getModCount());
+ transientState.setStatus(ItemState.STATUS_EXISTING_MODIFIED);
+ } catch (ItemStateException e) {
+ // something went wrong, mark as stale
+ transientState.setStatus(ItemState.STATUS_STALE_MODIFIED);
+ }
+ }
visibleState = transientState;
}
}
@@ -823,6 +837,12 @@
return atticStore.contains(id);
}
+ public boolean isModified(ItemId id) {
+ ItemState is = transientStore.get(id);
+ return is != null
+ && is.getStatus() == ItemState.STATUS_EXISTING_MODIFIED;
+ }
+
public boolean allowsSameNameSiblings(NodeId id) {
NodeState ns;
try {
@@ -867,6 +887,13 @@
if (transientState != null) {
transientState.setStatus(ItemState.STATUS_STALE_DESTROYED);
visibleState = transientState;
+ } else {
+ // check attic
+ transientState = atticStore.get(destroyed.getId());
+ if (transientState != null) {
+ atticStore.remove(destroyed.getId());
+ transientState.onDisposed();
+ }
}
}
dispatcher.notifyStateDestroyed(visibleState);
Index: src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (revision 788664)
+++ src/main/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java (working copy)
@@ -618,6 +618,10 @@
return local.deleted(id);
}
+ public boolean isModified(ItemId id) {
+ return local.isModified(id);
+ }
+
public boolean allowsSameNameSiblings(NodeId id) {
NodeState ns;
try {
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentAddRemoveMoveTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentAddRemoveMoveTest.java (revision 0)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentAddRemoveMoveTest.java (revision 0)
@@ -0,0 +1,179 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.Node;
+
+public final class ConcurrentAddRemoveMoveTest extends ConcurrentModificationBase {
+
+ /**
+ * {@inheritDoc}
+ */
+ public void setUp() throws Exception {
+ super.setUp();
+ testRootNode.addNode("A").addNode("B");
+ testRootNode.addNode("C");
+ testRootNode.getSession().save();
+ }
+
+ public void testAddWithMoveFrom() throws Exception {
+ testRootNode.getNode("A").addNode("D");
+ session.move(testRoot + "/A/B", testRoot + "/C/B");
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ public void testAddWithMoveTo() throws Exception {
+ testRootNode.getNode("A").addNode("D");
+ session.move(testRoot + "/C", testRoot + "/A/C");
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ public void testRemoveWithMoveFrom() throws Exception {
+ Node d = testRootNode.getNode("A").addNode("D");
+ superuser.save();
+ d.remove();
+ session.move(testRoot + "/A/B", testRoot + "/C/B");
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ public void testRemoveWithMoveTo() throws Exception {
+ Node d = testRootNode.getNode("A").addNode("D");
+ superuser.save();
+ d.remove();
+ session.move(testRoot + "/C", testRoot + "/A/C");
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ public void testMoveFromWithAdd() throws Exception {
+ superuser.move(testRoot + "/A/B", testRoot + "/C/B");
+ session.getNode(testRoot).getNode("A").addNode("D");
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ public void testMoveToWithAdd() throws Exception {
+ superuser.move(testRoot + "/C", testRoot + "/A/C");
+ session.getNode(testRoot).getNode("A").addNode("D");
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ public void testMoveFromWithRemove() throws Exception {
+ Node d = session.getNode(testRoot).getNode("A").addNode("D");
+ session.save();
+
+ superuser.move(testRoot + "/A/B", testRoot + "/C/B");
+ d.remove();
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ public void testMoveToWithRemove() throws Exception {
+ Node d = session.getNode(testRoot).getNode("A").addNode("D");
+ session.save();
+
+ superuser.move(testRoot + "/C", testRoot + "/A/C");
+ d.remove();
+
+ testRootNode.getSession().save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ //-------------------------< concurrent add >-------------------------------
+
+ public void testAddAdd() throws Exception {
+ testRootNode.getNode("A").addNode("D");
+ session.getNode(testRoot).getNode("A").addNode("E");
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+
+ //-------------------------< concurrent remove >----------------------------
+
+ public void testRemoveRemove() throws Exception {
+ Node d = testRootNode.getNode("A").addNode("D");
+ superuser.save();
+ d.remove();
+ session.getNode(testRoot).getNode("A").getNode("B").remove();
+
+ superuser.save();
+
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw exception");
+ }
+ }
+}
Property changes on: src\test\java\org\apache\jackrabbit\core\ConcurrentAddRemoveMoveTest.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentAddRemovePropertyTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentAddRemovePropertyTest.java (revision 0)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentAddRemovePropertyTest.java (revision 0)
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.Node;
+import javax.jcr.InvalidItemStateException;
+
+/**
+ * ConcurrentAddRemovePropertyTest checks if concurrently adding
+ * and removing properties does not throw an InvalidItemStateException.
+ */
+public class ConcurrentAddRemovePropertyTest extends ConcurrentModificationBase {
+
+ public void testAdd() throws Exception {
+ Node n = testRootNode.addNode(nodeName1);
+ superuser.save();
+ n.setProperty(propertyName1, "foo");
+ session.getNode(testRoot).getNode(nodeName1).setProperty(propertyName2, "bar");
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ }
+
+ public void testAddSameName() throws Exception {
+ Node n = testRootNode.addNode(nodeName1);
+ superuser.save();
+ n.setProperty(propertyName1, "foo");
+ session.getNode(testRoot).getNode(nodeName1).setProperty(propertyName1, "bar");
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ assertEquals("bar", n.getProperty(propertyName1).getString());
+ }
+
+ public void testRemove() throws Exception {
+ Node n = testRootNode.addNode(nodeName1);
+ n.setProperty(propertyName1, "foo");
+ n.setProperty(propertyName2, "bar");
+ superuser.save();
+ n.getProperty(propertyName1).remove();
+ session.getNode(testRoot).getNode(nodeName1).getProperty(propertyName2).remove();
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ }
+
+ public void testRemoveSameName() throws Exception {
+ Node n = testRootNode.addNode(nodeName1);
+ n.setProperty(propertyName1, "foo");
+ superuser.save();
+ n.getProperty(propertyName1).remove();
+ session.getNode(testRoot).getNode(nodeName1).getProperty(propertyName1).remove();
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ }
+}
Property changes on: src\test\java\org\apache\jackrabbit\core\ConcurrentAddRemovePropertyTest.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentMixinModificationTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentMixinModificationTest.java (revision 0)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentMixinModificationTest.java (revision 0)
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.Node;
+import javax.jcr.InvalidItemStateException;
+
+/**
+ * ConcurrentMixinModificationTest checks if concurrent
+ * modifications of mixins trigger an InvalidItemStateException.
+ */
+public class ConcurrentMixinModificationTest extends ConcurrentModificationBase {
+
+ public void testMixin() throws Exception {
+ Node n = testRootNode.addNode(nodeName1);
+ superuser.save();
+ n.addMixin(mixReferenceable);
+ session.getNode(testRoot).getNode(nodeName1).addMixin(mixLockable);
+ superuser.save();
+ try {
+ session.save();
+ fail("InvalidItemStateException expected");
+ } catch (InvalidItemStateException e) {
+ // expected
+ }
+ }
+}
Property changes on: src\test\java\org\apache\jackrabbit\core\ConcurrentMixinModificationTest.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentModificationBase.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentModificationBase.java (revision 0)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentModificationBase.java (revision 0)
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.test.AbstractJCRTest;
+
+/**
+ * ConcurrentModificationBase is a base class for concurrent
+ * modification tests.
+ */
+public abstract class ConcurrentModificationBase extends AbstractJCRTest {
+
+ protected Session session;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ session = helper.getSuperuserSession();
+ }
+
+ protected void tearDown() throws Exception {
+ if (session != null) {
+ session.logout();
+ session = null;
+ }
+ super.tearDown();
+ }
+}
Property changes on: src\test\java\org\apache\jackrabbit\core\ConcurrentModificationBase.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentModificationWithSNSTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentModificationWithSNSTest.java (revision 0)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentModificationWithSNSTest.java (revision 0)
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.InvalidItemStateException;
+import javax.jcr.Node;
+
+/**
+ * ConcurrentModificationWithSNSTest checks if interleaving node
+ * modifications with same name siblings do not throw InvalidItemStateException.
+ */
+public class ConcurrentModificationWithSNSTest extends ConcurrentModificationBase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ testRootNode.addNode("A");
+ testRootNode.addNode("A");
+ testRootNode.addNode("A");
+ superuser.save();
+ }
+
+ public void testAddAdd() throws Exception {
+ testRootNode.addNode("A");
+ session.getNode(testRoot).addNode("A");
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ }
+
+ public void testAddRemove() throws Exception {
+ testRootNode.addNode("A");
+ session.getNode(testRoot).getNode("A[2]").remove();
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ }
+
+ public void testRemoveAdd() throws Exception {
+ testRootNode.getNode("A[2]").remove();
+ session.getNode(testRoot).addNode("A");
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ }
+
+ public void testRemoveRemove() throws Exception {
+ testRootNode.getNode("A[1]").remove();
+ session.getNode(testRoot).getNode("A[3]").remove();
+ superuser.save();
+ try {
+ session.save();
+ } catch (InvalidItemStateException e) {
+ fail("must not throw InvalidItemStateException");
+ }
+ }
+
+ public void testSNSNotAllowed() throws Exception {
+ cleanUpTestRoot(superuser);
+ Node f = testRootNode.addNode("folder", "nt:folder");
+ superuser.save();
+ f.addNode("A", "nt:folder");
+ session.getNode(f.getPath()).addNode("A", "nt:folder");
+ superuser.save();
+ try {
+ session.save();
+ fail("InvalidItemStateException expected");
+ } catch (InvalidItemStateException e) {
+ // expected
+ }
+ }
+}
Property changes on: src\test\java\org\apache\jackrabbit\core\ConcurrentModificationWithSNSTest.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentMoveTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentMoveTest.java (revision 0)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentMoveTest.java (revision 0)
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.InvalidItemStateException;
+
+/**
+ * ConcurrentMoveTest...
+ */
+public class ConcurrentMoveTest extends ConcurrentModificationBase {
+
+ protected String srcAbsPath;
+
+ protected String destAbsPath1;
+
+ protected String destAbsPath2;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ srcAbsPath = testRootNode.addNode("A").getPath();
+ destAbsPath1 = testRootNode.addNode("B").getPath() + "/D";
+ destAbsPath2 = testRootNode.addNode("C").getPath() + "/D";
+ superuser.save();
+ }
+
+ public void testMove() throws Exception {
+ superuser.move(srcAbsPath, destAbsPath1);
+ session.move(srcAbsPath, destAbsPath2);
+ superuser.save();
+ try {
+ session.save();
+ fail("InvalidItemStateException expected");
+ } catch (InvalidItemStateException e) {
+ // expected
+ }
+ }
+}
Property changes on: src\test\java\org\apache\jackrabbit\core\ConcurrentMoveTest.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentNodeModificationTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentNodeModificationTest.java (revision 788664)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentNodeModificationTest.java (working copy)
@@ -120,11 +120,21 @@
state = "adding property to subnode " + i;
n1.setProperty("testprop", "xxx");
if (i % 10 == 0) {
- state = "saving pending subnodes";
+ state = "saving pending (added) subnodes";
session.save();
}
randomSleep();
}
+
+ for (int i = 0; i < NUM_NODES; i++) {
+ state = "removing subnode " + i;
+ n.getNode("x" + identity + i).remove();
+ if (i % 10 == 0) {
+ state = "saving pending (removed) subnodes";
+ session.save();
+ }
+ randomSleep();
+ }
session.save();
} catch (Exception e) {
log.println("Exception while " + state + ": " + e.getMessage());
Index: src/test/java/org/apache/jackrabbit/core/ConcurrentReorderTest.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/ConcurrentReorderTest.java (revision 0)
+++ src/test/java/org/apache/jackrabbit/core/ConcurrentReorderTest.java (revision 0)
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core;
+
+import javax.jcr.InvalidItemStateException;
+
+/**
+ * ConcurrentReorderTest checks if a reorder interleaved with
+ * a modification by another session throws an InvalidItemStateException.
+ */
+public class ConcurrentReorderTest extends ConcurrentModificationBase {
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ testRootNode.addNode("A");
+ testRootNode.addNode("B");
+ testRootNode.addNode("C");
+ superuser.save();
+ }
+
+ public void testReorderWithAdd() throws Exception {
+ testRootNode.orderBefore("C", "A");
+ session.getNode(testRoot).addNode("D");
+ session.save();
+ try {
+ superuser.save();
+ fail("must throw InvalidItemStateException");
+ } catch (InvalidItemStateException e) {
+ // expected
+ }
+ }
+
+ public void testAddWithReorder() throws Exception {
+ testRootNode.addNode("D");
+ session.getNode(testRoot).orderBefore("C", "A");
+ session.save();
+ try {
+ superuser.save();
+ fail("must throw InvalidItemStateException");
+ } catch (InvalidItemStateException e) {
+ // expected
+ }
+ }
+}
Property changes on: src\test\java\org\apache\jackrabbit\core\ConcurrentReorderTest.java
___________________________________________________________________
Added: svn:eol-style
+ native
Index: src/test/java/org/apache/jackrabbit/core/TestAll.java
===================================================================
--- src/test/java/org/apache/jackrabbit/core/TestAll.java (revision 788664)
+++ src/test/java/org/apache/jackrabbit/core/TestAll.java (working copy)
@@ -42,6 +42,14 @@
suite.addTestSuite(InvalidDateTest.class);
suite.addTestSuite(SessionGarbageCollectedTest.class);
+ // test related to NodeStateMerger
+ suite.addTestSuite(ConcurrentAddRemoveMoveTest.class);
+ suite.addTestSuite(ConcurrentAddRemovePropertyTest.class);
+ suite.addTestSuite(ConcurrentMixinModificationTest.class);
+ suite.addTestSuite(ConcurrentModificationWithSNSTest.class);
+ suite.addTestSuite(ConcurrentMoveTest.class);
+ suite.addTestSuite(ConcurrentReorderTest.class);
+
return suite;
}
}