Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ChildOrderConflictHandler.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ChildOrderConflictHandler.java (date 1392290482000) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/commit/ChildOrderConflictHandler.java (revision ) @@ -92,7 +92,20 @@ } } - parent.setProperty(merged.getPropertyState()); + PropertyState propertyState = merged.getPropertyState(); + dump("o: ", ours); + dump("t: ", theirs); + dump("m: ", propertyState); + parent.setProperty(propertyState); + } + + private static void dump(String m, PropertyState propertyState) { + Iterable vs = propertyState.getValue(Type.STRINGS); + String s = ""; + for (String v : vs) { + s += v + ", "; + } + System.out.println(m + s); } @Override Index: oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddIT.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddIT.java (date 1392290482000) +++ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddIT.java (revision ) @@ -16,21 +16,27 @@ */ package org.apache.jackrabbit.oak.jcr; +import static com.google.common.collect.Iterators.transform; import static org.apache.jackrabbit.commons.JcrUtils.in; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; +import javax.annotation.Nullable; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; +import com.google.common.base.Function; import com.google.common.collect.Iterators; +import com.google.common.collect.Sets; import org.junit.Assume; import org.junit.Test; @@ -40,9 +46,9 @@ */ public class ConcurrentAddIT extends AbstractRepositoryTest { - private static final int NUM_WORKERS = 10; + private static final int NUM_WORKERS = 100; - private static final int NODES_PER_WORKER = 100; + private static final int NODES_PER_WORKER = 2; public ConcurrentAddIT(NodeStoreFixture fixture) { super(fixture); @@ -79,18 +85,16 @@ public void addNodesSameParent() throws Exception { // takes too long with RDBDocumentStore Assume.assumeTrue(fixture != NodeStoreFixture.DOCUMENT_JDBC); - // FIXME enable again once OAK-1420 is fixed - Assume.assumeTrue(fixture != NodeStoreFixture.DOCUMENT_NS); List exceptions = Collections.synchronizedList( new ArrayList()); // use nt:unstructured to force conflicts on :childOrder property Node test = getAdminSession().getRootNode().addNode("test", "nt:unstructured"); + getAdminSession().save(); List worker = new ArrayList(); for (int i = 0; i < NUM_WORKERS; i++) { worker.add(new Thread(new Worker( createAdminSession(), test.getPath(), exceptions))); } - getAdminSession().save(); for (Thread t : worker) { t.start(); } @@ -101,9 +105,34 @@ fail(e.toString()); } getAdminSession().refresh(false); - assertEquals(NODES_PER_WORKER * NUM_WORKERS, Iterators.size(test.getNodes())); + int size = Iterators.size(test.getNodes()); + if (size != NODES_PER_WORKER * NUM_WORKERS) { + HashSet nodes = Sets.newHashSet(transform(test.getNodes(), + new Function() { + @Nullable + @Override + public String apply(Node node) { + try { + return node.getName(); + } catch (RepositoryException e) { + return null; - } + } + } + })); + for (int w = 1; w <= NUM_WORKERS; w++) { + for (int n = 0; n < NODES_PER_WORKER; n++) { + String name = "worker-" + w + "-node-" + n; + if (!nodes.contains(name)) { + System.out.println(name); + } + } + } + + assertEquals(NODES_PER_WORKER * NUM_WORKERS, size); + } + } + private static final class Worker implements Runnable { private static final AtomicInteger WORKER_ID = new AtomicInteger(); @@ -118,14 +147,18 @@ this.exceptions = exceptions; } + Random r = new Random(); + @Override public void run() { try { - s.refresh(false); Node n = s.getNode(path); for (int i = 0; i < NODES_PER_WORKER; i++) { n.addNode(id + "-node-" + i); s.save(); + try { + Thread.sleep(r.nextInt(20)); + } catch (InterruptedException e) { } } } catch (RepositoryException e) { exceptions.add(e); Index: oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java (date 1392290482000) +++ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java (revision ) @@ -41,7 +41,7 @@ * Users of this class must call clear to close the session associated with * this instance and clean up the repository when done. */ -@RunWith(Parallelized.class) +@RunWith(Parameterized.class) @Ignore("This abstract base class does not have any tests") public abstract class AbstractRepositoryTest { @@ -57,11 +57,11 @@ @Parameterized.Parameters public static Collection fixtures() { Object[][] fixtures = new Object[][] { - {NodeStoreFixture.MK_IMPL}, - {NodeStoreFixture.DOCUMENT_MK}, +// {NodeStoreFixture.MK_IMPL}, +// {NodeStoreFixture.DOCUMENT_MK}, {NodeStoreFixture.DOCUMENT_NS}, - {NodeStoreFixture.SEGMENT_MK}, - {NodeStoreFixture.DOCUMENT_JDBC}, +// {NodeStoreFixture.SEGMENT_MK}, +// {NodeStoreFixture.DOCUMENT_JDBC}, }; return Arrays.asList(fixtures); }