Author: mreutegg
Date: Tue Oct 23 12:22:25 2012
New Revision: 1401267
URL: http://svn.apache.org/viewvc?rev=1401267&view=rev
Log:
OAK-169: Support orderable nodes
- maintain :childOrder on move and copy
- more tests
- removed OrderedChildrenEditor again
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictHandlerWrapper.java
(with props)
Removed:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/OrderedChildrenEditor.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MergingNodeStateDiff.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MergingNodeStateDiff.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MergingNodeStateDiff.java?rev=1401267&r1=1401266&r2=1401267&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MergingNodeStateDiff.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/MergingNodeStateDiff.java
Tue Oct 23 12:22:25 2012
@@ -17,11 +17,15 @@
package org.apache.jackrabbit.oak.core;
import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.api.Type;
+import org.apache.jackrabbit.oak.plugins.commit.ConflictHandlerWrapper;
+import org.apache.jackrabbit.oak.plugins.memory.MemoryPropertyBuilder;
import org.apache.jackrabbit.oak.spi.commit.ConflictHandler;
import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.PropertyBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -51,7 +55,7 @@ class MergingNodeStateDiff implements No
static void merge(NodeState fromState, NodeState toState, final
NodeBuilder target,
final ConflictHandler conflictHandler) {
toState.compareAgainstBaseState(fromState, new MergingNodeStateDiff(
- checkNotNull(target), conflictHandler));
+ checkNotNull(target), new
ChildOrderConflictHandler(conflictHandler)));
}
//------------------------------------------------------< NodeStateDiff
>---
@@ -188,7 +192,7 @@ class MergingNodeStateDiff implements No
switch (resolution) {
case OURS:
if (n != null) {
- target.removeNode(name);
+ removeChild(target, name);
}
break;
case THEIRS:
@@ -204,9 +208,102 @@ class MergingNodeStateDiff implements No
for (PropertyState property : state.getProperties()) {
child.setProperty(property);
}
+ PropertyState childOrder =
target.getProperty(TreeImpl.OAK_CHILD_ORDER);
+ if (childOrder != null) {
+ PropertyBuilder<String> builder = MemoryPropertyBuilder.create(
+ Type.STRING, childOrder);
+ builder.addValue(name);
+ target.setProperty(builder.getPropertyState(true));
+ }
for (ChildNodeEntry entry : state.getChildNodeEntries()) {
addChild(child, entry.getName(), entry.getNodeState());
}
}
+ private static void removeChild(NodeBuilder target, String name) {
+ target.removeNode(name);
+ PropertyState childOrder =
target.getProperty(TreeImpl.OAK_CHILD_ORDER);
+ if (childOrder != null) {
+ PropertyBuilder<String> builder = MemoryPropertyBuilder.create(
+ Type.STRING, childOrder);
+ builder.removeValue(name);
+ target.setProperty(builder.getPropertyState(true));
+ }
+ }
+
+ /**
+ * <code>ChildOrderConflictHandler</code> ignores conflicts on the
+ * {@link TreeImpl#OAK_CHILD_ORDER} property. All other conflicts are
forwarded
+ * to the wrapped handler.
+ */
+ private static class ChildOrderConflictHandler extends
ConflictHandlerWrapper {
+
+ ChildOrderConflictHandler(ConflictHandler delegate) {
+ super(delegate);
+ }
+
+ @Override
+ public Resolution addExistingProperty(NodeBuilder parent,
+ PropertyState ours,
+ PropertyState theirs) {
+ if (isChildOrderProperty(ours)) {
+ // two sessions concurrently called orderBefore() on a Tree
+ // that was previously unordered.
+ return Resolution.THEIRS;
+ } else {
+ return handler.addExistingProperty(parent, ours, theirs);
+ }
+ }
+
+ @Override
+ public Resolution changeDeletedProperty(NodeBuilder parent,
+ PropertyState ours) {
+ if (isChildOrderProperty(ours)) {
+ // orderBefore() on trees that were deleted
+ return Resolution.THEIRS;
+ } else {
+ return handler.changeDeletedProperty(parent, ours);
+ }
+ }
+
+ @Override
+ public Resolution changeChangedProperty(NodeBuilder parent,
+ PropertyState ours,
+ PropertyState theirs) {
+ if (isChildOrderProperty(ours)) {
+ // concurrent orderBefore(), other changes win
+ return Resolution.THEIRS;
+ } else {
+ return handler.changeChangedProperty(parent, ours, theirs);
+ }
+ }
+
+ @Override
+ public Resolution deleteDeletedProperty(NodeBuilder parent,
+ PropertyState ours) {
+ if (isChildOrderProperty(ours)) {
+ // concurrent remove of ordered trees
+ return Resolution.THEIRS;
+ } else {
+ return handler.deleteDeletedProperty(parent, ours);
+ }
+ }
+
+ @Override
+ public Resolution deleteChangedProperty(NodeBuilder parent,
+ PropertyState theirs) {
+ if (isChildOrderProperty(theirs)) {
+ // remove trees that were reordered by another session
+ return Resolution.THEIRS;
+ } else {
+ return handler.deleteChangedProperty(parent, theirs);
+ }
+ }
+
+ //----------------------------< internal
>----------------------------------
+
+ private static boolean isChildOrderProperty(PropertyState p) {
+ return TreeImpl.OAK_CHILD_ORDER.equals(p.getName());
+ }
+ }
}
\ No newline at end of file
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java?rev=1401267&r1=1401266&r2=1401267&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/RootImpl.java
Tue Oct 23 12:22:25 2012
@@ -163,14 +163,23 @@ public class RootImpl implements Root {
purgePendingChanges();
source.moveTo(destParent, destName);
- return branch.move(sourcePath, destPath);
+ boolean success = branch.move(sourcePath, destPath);
+ if (success) {
+ getTree(getParentPath(sourcePath)).updateChildOrder();
+ getTree(getParentPath(destPath)).updateChildOrder();
+ }
+ return success;
}
@Override
public boolean copy(String sourcePath, String destPath) {
checkLive();
purgePendingChanges();
- return branch.copy(sourcePath, destPath);
+ boolean success = branch.copy(sourcePath, destPath);
+ if (success) {
+ getTree(getParentPath(destPath)).updateChildOrder();
+ }
+ return success;
}
@Override
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java?rev=1401267&r1=1401266&r2=1401267&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/TreeImpl.java
Tue Oct 23 12:22:25 2012
@@ -21,15 +21,12 @@ package org.apache.jackrabbit.oak.core;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.collect.Iterables;
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.TreeLocation;
@@ -41,6 +38,13 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.PropertyBuilder;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -483,6 +487,30 @@ public class TreeImpl implements Tree, P
return (canRead(child)) ? child : null;
}
+ /**
+ * Update the child order with children that have been removed or added.
+ * Added children are appended to the end of the {@link #OAK_CHILD_ORDER}
+ * property.
+ */
+ void updateChildOrder() {
+ if (!hasOrderableChildren()) {
+ return;
+ }
+ Set<String> names = Sets.newLinkedHashSet();
+ for (String name : getOrderedChildNames()) {
+ if (getNodeBuilder().hasChildNode(name)) {
+ names.add(name);
+ }
+ }
+ for (String name : getNodeBuilder().getChildNodeNames()) {
+ names.add(name);
+ }
+ PropertyBuilder<String> builder = MemoryPropertyBuilder.create(
+ Type.STRING, OAK_CHILD_ORDER);
+ builder.setValues(names);
+ getNodeBuilder().setProperty(builder.getPropertyState(true));
+ }
+
//------------------------------------------------------------< private
>---
private TreeImpl internalGetChild(String childName) {
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictHandlerWrapper.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictHandlerWrapper.java?rev=1401267&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictHandlerWrapper.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictHandlerWrapper.java
Tue Oct 23 12:22:25 2012
@@ -0,0 +1,95 @@
+/*
+ * 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.oak.plugins.commit;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.commit.ConflictHandler;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * This {@link ConflictHandler} implementation wraps another conflict handler
+ * and forwards all calls to the wrapped handler. Sub classes may override
+ * methods of this class and intercept calls they are interested in.
+ */
+public class ConflictHandlerWrapper implements ConflictHandler {
+
+ protected final ConflictHandler handler;
+
+ public ConflictHandlerWrapper(ConflictHandler handler) {
+ this.handler = handler;
+ }
+
+ @Override
+ public Resolution addExistingProperty(NodeBuilder parent,
+ PropertyState ours,
+ PropertyState theirs) {
+ return handler.addExistingProperty(parent, ours, theirs);
+ }
+
+ @Override
+ public Resolution changeDeletedProperty(NodeBuilder parent,
+ PropertyState ours) {
+ return handler.changeDeletedProperty(parent, ours);
+ }
+
+ @Override
+ public Resolution changeChangedProperty(NodeBuilder parent,
+ PropertyState ours,
+ PropertyState theirs) {
+ return handler.changeChangedProperty(parent, ours, theirs);
+ }
+
+ @Override
+ public Resolution deleteDeletedProperty(NodeBuilder parent,
+ PropertyState ours) {
+ return handler.deleteDeletedProperty(parent, ours);
+ }
+
+ @Override
+ public Resolution deleteChangedProperty(NodeBuilder parent,
+ PropertyState theirs) {
+ return handler.deleteChangedProperty(parent, theirs);
+ }
+
+ @Override
+ public Resolution addExistingNode(NodeBuilder parent,
+ String name,
+ NodeState ours,
+ NodeState theirs) {
+ return handler.addExistingNode(parent, name, ours, theirs);
+ }
+
+ @Override
+ public Resolution changeDeletedNode(NodeBuilder parent,
+ String name,
+ NodeState ours) {
+ return handler.changeDeletedNode(parent, name, ours);
+ }
+
+ @Override
+ public Resolution deleteChangedNode(NodeBuilder parent,
+ String name,
+ NodeState theirs) {
+ return handler.deleteChangedNode(parent, name, theirs);
+ }
+
+ @Override
+ public Resolution deleteDeletedNode(NodeBuilder parent, String name) {
+ return handler.deleteDeletedNode(parent, name);
+ }
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictHandlerWrapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ConflictHandlerWrapper.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java?rev=1401267&r1=1401266&r2=1401267&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/RootTest.java
Tue Oct 23 12:22:25 2012
@@ -23,7 +23,6 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.commit.ConflictValidator;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import static org.apache.jackrabbit.oak.OakAssert.assertSequence;
@@ -49,7 +48,6 @@ public class RootTest {
}
@Test
- @Ignore("OAK-169")
public void copyOrderableNodes() throws Exception {
ContentSession s = repository.login(null, null);
try {
@@ -64,13 +62,15 @@ public class RootTest {
r.copy("/node3", "/c/node3");
c = r.getTree("/").getChild("c");
assertSequence(c.getChildren(), "node1", "node2", "node3");
+ r.commit();
+ c = r.getTree("/").getChild("c");
+ assertSequence(c.getChildren(), "node1", "node2", "node3");
} finally {
s.close();
}
}
@Test
- @Ignore("OAK-169")
public void moveOrderableNodes() throws Exception {
ContentSession s = repository.login(null, null);
try {
@@ -85,6 +85,9 @@ public class RootTest {
r.move("/node3", "/c/node3");
c = r.getTree("/").getChild("c");
assertSequence(c.getChildren(), "node1", "node2", "node3");
+ r.commit();
+ c = r.getTree("/").getChild("c");
+ assertSequence(c.getChildren(), "node1", "node2", "node3");
} finally {
s.close();
}
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java?rev=1401267&r1=1401266&r2=1401267&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/api/TreeTest.java
Tue Oct 23 12:22:25 2012
@@ -90,35 +90,236 @@ public class TreeTest {
}
@Test
- public void concurrentAddChildOrderable() throws Exception {
+ public void concurrentOrderBefore() throws Exception {
ContentSession s1 = repository.login(null, null);
try {
Root r1 = s1.getLatestRoot();
Tree t1 = r1.getTree("/");
- t1.addChild("node1").orderBefore(null);
+ t1.addChild("node1");
t1.addChild("node2");
t1.addChild("node3");
r1.commit();
+ t1 = r1.getTree("/");
+
ContentSession s2 = repository.login(null, null);
try {
Root r2 = s2.getLatestRoot();
Tree t2 = r2.getTree("/");
+ t1.getChild("node2").orderBefore("node1");
+ t1.getChild("node3").orderBefore(null);
+ r1.commit();
t1 = r1.getTree("/");
- // node4 from s1
+ assertSequence(t1.getChildren(), "node2", "node1", "node3");
+
+ t2.getChild("node3").orderBefore("node1");
+ t2.getChild("node2").orderBefore(null);
+ r2.commit();
+ t2 = r2.getTree("/");
+ // other session wins
+ assertSequence(t2.getChildren(), "node2", "node1", "node3");
+
+ // try again on current root
+ t2.getChild("node3").orderBefore("node1");
+ t2.getChild("node2").orderBefore(null);
+ r2.commit();
+ t2 = r2.getTree("/");
+ assertSequence(t2.getChildren(), "node3", "node1", "node2");
+
+ } finally {
+ s2.close();
+ }
+ } finally {
+ s1.close();
+ }
+ }
+
+ @Test
+ public void concurrentOrderBeforeWithAdd() throws Exception {
+ ContentSession s1 = repository.login(null, null);
+ try {
+ Root r1 = s1.getLatestRoot();
+ Tree t1 = r1.getTree("/");
+ t1.addChild("node1");
+ t1.addChild("node2");
+ t1.addChild("node3");
+ r1.commit();
+ t1 = r1.getTree("/");
+
+ ContentSession s2 = repository.login(null, null);
+ try {
+ Root r2 = s2.getLatestRoot();
+ Tree t2 = r2.getTree("/");
+
+ t1.getChild("node2").orderBefore("node1");
+ t1.getChild("node3").orderBefore(null);
t1.addChild("node4");
r1.commit();
+ t1 = r1.getTree("/");
+ assertSequence(t1.getChildren(), "node2", "node1", "node3",
"node4");
- // node5 from s2
- t2.addChild("node5");
- try {
- r2.commit();
- // commit must fail
- } catch (CommitFailedException e) {
- }
+ t2.getChild("node3").orderBefore("node1");
+ r2.commit();
+ t2 = r2.getTree("/");
+ // other session wins
+ assertSequence(t2.getChildren(), "node2", "node1", "node3",
"node4");
- r1 = s1.getLatestRoot();
+ // try again on current root
+ t2.getChild("node3").orderBefore("node1");
+ r2.commit();
+ t2 = r2.getTree("/");
+ assertSequence(t2.getChildren(), "node2", "node3", "node1",
"node4");
+
+ } finally {
+ s2.close();
+ }
+ } finally {
+ s1.close();
+ }
+ }
+
+ @Test
+ public void concurrentOrderBeforeWithRemove() throws Exception {
+ ContentSession s1 = repository.login(null, null);
+ try {
+ Root r1 = s1.getLatestRoot();
+ Tree t1 = r1.getTree("/");
+ t1.addChild("node1");
+ t1.addChild("node2");
+ t1.addChild("node3");
+ t1.addChild("node4");
+ r1.commit();
+ t1 = r1.getTree("/");
+
+ ContentSession s2 = repository.login(null, null);
+ try {
+ Root r2 = s2.getLatestRoot();
+ Tree t2 = r2.getTree("/");
+
+ t1.getChild("node2").orderBefore("node1");
+ t1.getChild("node3").orderBefore(null);
+ t1.getChild("node4").remove();
+ r1.commit();
+ t1 = r1.getTree("/");
+ assertSequence(t1.getChildren(), "node2", "node1", "node3");
+
+ t2.getChild("node3").orderBefore("node1");
+ r2.commit();
+ t2 = r2.getTree("/");
+ // other session wins
+ assertSequence(t2.getChildren(), "node2", "node1", "node3");
+
+ // try again on current root
+ t2.getChild("node3").orderBefore("node1");
+ r2.commit();
+ t2 = r2.getTree("/");
+ assertSequence(t2.getChildren(), "node2", "node3", "node1");
+
+ } finally {
+ s2.close();
+ }
+ } finally {
+ s1.close();
+ }
+ }
+
+ @Test
+ public void concurrentOrderBeforeRemoved() throws Exception {
+ ContentSession s1 = repository.login(null, null);
+ try {
+ Root r1 = s1.getLatestRoot();
+ Tree t1 = r1.getTree("/");
+ t1.addChild("node1");
+ t1.addChild("node2");
+ t1.addChild("node3");
+ r1.commit();
+ t1 = r1.getTree("/");
+
+ ContentSession s2 = repository.login(null, null);
+ try {
+ Root r2 = s2.getLatestRoot();
+ Tree t2 = r2.getTree("/");
+
+ t1.getChild("node2").orderBefore("node1");
+ t1.getChild("node3").remove();
+ r1.commit();
t1 = r1.getTree("/");
+ assertSequence(t1.getChildren(), "node2", "node1");
+
+ t2.getChild("node3").orderBefore("node1");
+ r2.commit();
+ t2 = r2.getTree("/");
+ assertSequence(t2.getChildren(), "node2", "node1");
+
+ } finally {
+ s2.close();
+ }
+ } finally {
+ s1.close();
+ }
+ }
+
+ @Test
+ public void concurrentOrderBeforeTargetRemoved() throws Exception {
+ ContentSession s1 = repository.login(null, null);
+ try {
+ Root r1 = s1.getLatestRoot();
+ Tree t1 = r1.getTree("/");
+ t1.addChild("node1").orderBefore(null);
+ t1.addChild("node2");
+ t1.addChild("node3");
+ t1.addChild("node4");
+ r1.commit();
+ t1 = r1.getTree("/");
+
+ ContentSession s2 = repository.login(null, null);
+ try {
+ Root r2 = s2.getLatestRoot();
+ Tree t2 = r2.getTree("/");
+
+ t1.getChild("node2").orderBefore("node1");
+ t1.getChild("node3").remove();
+ r1.commit();
+ t1 = r1.getTree("/");
+ assertSequence(t1.getChildren(), "node2", "node1", "node4");
+
+ t2.getChild("node4").orderBefore("node3");
+ r2.commit();
+ t2 = r2.getTree("/");
+ assertSequence(t2.getChildren(), "node2", "node1", "node4");
+
+ } finally {
+ s2.close();
+ }
+ } finally {
+ s1.close();
+ }
+ }
+
+ @Test
+ public void concurrentAddChildOrderable() throws Exception {
+ ContentSession s1 = repository.login(null, null);
+ try {
+ Root r1 = s1.getLatestRoot();
+ Tree t1 = r1.getTree("/");
+ t1.addChild("node1").orderBefore(null);
+ t1.addChild("node2");
+ r1.commit();
+ ContentSession s2 = repository.login(null, null);
+ try {
+ Root r2 = s2.getLatestRoot();
+ Tree t2 = r2.getTree("/");
+
+ t1 = r1.getTree("/");
+ // node3 from s1
+ t1.addChild("node3");
+ r1.commit();
+
+ // node4 from s2
+ t2.addChild("node4");
+ r2.commit();
+
+ t1 = s1.getLatestRoot().getTree("/");
assertSequence(
t1.getChildren(), "node1", "node2", "node3", "node4");
} finally {
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java?rev=1401267&r1=1401266&r2=1401267&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
Tue Oct 23 12:22:25 2012
@@ -16,9 +16,6 @@
*/
package org.apache.jackrabbit.oak.jcr;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static
org.apache.jackrabbit.oak.plugins.index.IndexConstants.DEFAULT_INDEX_HOME;
-
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -27,7 +24,6 @@ import javax.jcr.Repository;
import org.apache.jackrabbit.mk.api.MicroKernel;
import org.apache.jackrabbit.oak.Oak;
-import org.apache.jackrabbit.oak.core.OrderedChildrenEditor;
import org.apache.jackrabbit.oak.plugins.commit.AnnotatingConflictHandler;
import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
import org.apache.jackrabbit.oak.plugins.index.lucene.LuceneHook;
@@ -49,6 +45,9 @@ import org.apache.jackrabbit.oak.spi.lif
import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static
org.apache.jackrabbit.oak.plugins.index.IndexConstants.DEFAULT_INDEX_HOME;
+
public class Jcr {
private final Oak oak;
@@ -75,7 +74,6 @@ public class Jcr {
with(new PropertyIndexHook());
with(new LuceneReindexHook(DEFAULT_INDEX_HOME));
with(new LuceneHook(DEFAULT_INDEX_HOME));
- with(new OrderedChildrenEditor());
with(new AnnotatingConflictHandler());
with(new PropertyIndexProvider());
Modified:
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java?rev=1401267&r1=1401266&r2=1401267&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
(original)
+++
jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/run/Main.java
Tue Oct 23 12:22:25 2012
@@ -25,7 +25,6 @@ import org.apache.jackrabbit.mk.api.Micr
import org.apache.jackrabbit.mk.core.MicroKernelImpl;
import org.apache.jackrabbit.oak.Oak;
import org.apache.jackrabbit.oak.api.ContentRepository;
-import org.apache.jackrabbit.oak.core.OrderedChildrenEditor;
import org.apache.jackrabbit.oak.http.OakServlet;
import org.apache.jackrabbit.oak.jcr.RepositoryImpl;
import org.apache.jackrabbit.oak.plugins.commit.ConflictValidatorProvider;
@@ -207,8 +206,7 @@ public class Main {
new ValidatingHook(createDefaultValidatorProvider()),
new PropertyIndexHook(),
new LuceneReindexHook(DEFAULT_INDEX_HOME),
- new LuceneHook(DEFAULT_INDEX_HOME),
- new OrderedChildrenEditor());
+ new LuceneHook(DEFAULT_INDEX_HOME));
}
private static ValidatorProvider createDefaultValidatorProvider() {