You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by mr...@apache.org on 2013/12/03 11:35:08 UTC

svn commit: r1547337 - /jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java

Author: mreutegg
Date: Tue Dec  3 10:35:08 2013
New Revision: 1547337

URL: http://svn.apache.org/r1547337
Log:
OAK-1254: Parallel execution of SimpleSearchTest fails with MongoMK
- add another test with interleaving writes but without concurrent execution

Modified:
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java?rev=1547337&r1=1547336&r2=1547337&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java Tue Dec  3 10:35:08 2013
@@ -16,11 +16,16 @@
  */
 package org.apache.jackrabbit.oak.jcr;
 
+import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
 
 import javax.jcr.Node;
 import javax.jcr.PropertyType;
@@ -48,7 +53,9 @@ public class ConcurrentAddNodesClusterIT
 
     private static final int NUM_CLUSTER_NODES = 3;
     private static final int NODE_COUNT = 100;
+    private static final int LOOP_COUNT = 10;
     private static final String PROP_NAME = "testcount";
+    private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
 
     private List<MongoMK> mks = new ArrayList<MongoMK>();
     private List<Thread> workers = new ArrayList<Thread>();
@@ -62,12 +69,6 @@ public class ConcurrentAddNodesClusterIT
     public void before() throws Exception {
         dropDB();
         initRepository();
-        for (int i = 0; i < NUM_CLUSTER_NODES; i++) {
-            MongoMK mk = new MongoMK.Builder()
-                    .setMongoDB(createConnection().getDB())
-                    .setClusterId(i + 1).open();
-            mks.add(mk);
-        }
     }
 
     @After
@@ -79,8 +80,15 @@ public class ConcurrentAddNodesClusterIT
     }
 
     @Test
-    public void addNodes() throws Exception {
-        Map<String, Exception> exceptions = Collections.synchronizedMap(new HashMap<String, Exception>());
+    public void addNodesConcurrent() throws Exception {
+        for (int i = 0; i < NUM_CLUSTER_NODES; i++) {
+            MongoMK mk = new MongoMK.Builder()
+                    .setMongoDB(createConnection().getDB())
+                    .setClusterId(i + 1).open();
+            mks.add(mk);
+        }
+        Map<String, Exception> exceptions = Collections.synchronizedMap(
+                new HashMap<String, Exception>());
         for (int i = 0; i < mks.size(); i++) {
             MongoMK mk = mks.get(i);
             Repository repo = new Jcr(mk).createRepository();
@@ -98,6 +106,50 @@ public class ConcurrentAddNodesClusterIT
         }
     }
 
+    @Test
+    public void addNodes() throws Exception {
+        for (int i = 0; i < 2; i++) {
+            MongoMK mk = new MongoMK.Builder()
+                    .setMongoDB(createConnection().getDB())
+                    .setAsyncDelay(0)
+                    .setClusterId(i + 1).open();
+            mks.add(mk);
+        }
+        final MongoMK mk1 = mks.get(0);
+        final MongoMK mk2 = mks.get(1);
+        Repository r1 = new Jcr(mk1).createRepository();
+        Repository r2 = new Jcr(mk2).createRepository();
+
+        Session s1 = r1.login(new SimpleCredentials("admin", "admin".toCharArray()));
+        Session s2 = r2.login(new SimpleCredentials("admin", "admin".toCharArray()));
+
+        ensureIndex(s1.getRootNode(), PROP_NAME);
+        syncMKs(1);
+        ensureIndex(s2.getRootNode(), PROP_NAME);
+
+        Map<String, Exception> exceptions = Collections.synchronizedMap(
+                new HashMap<String, Exception>());
+        createNodes(s1, "testroot-1", 1, 1, exceptions);
+        syncMKs(1);
+        createNodes(s2, "testroot-2", 1, 1, exceptions);
+
+        for (Map.Entry<String, Exception> entry : exceptions.entrySet()) {
+            throw entry.getValue();
+        }
+    }
+
+    private void syncMKs(int delay) {
+        EXECUTOR.schedule(new Callable<Object>() {
+            @Override
+            public Object call() throws Exception {
+                for (MongoMK mk : mks) {
+                    runBackgroundOps(mk);
+                }
+                return null;
+            }
+        }, delay, TimeUnit.SECONDS);
+    }
+
     private static MongoConnection createConnection() throws Exception {
         return OakMongoMKRepositoryStub.createConnection(
                 ConcurrentAddNodesClusterIT.class.getSimpleName());
@@ -144,7 +196,13 @@ public class ConcurrentAddNodesClusterIT
         }
     }
 
-    private static final class Worker implements Runnable {
+    private static void runBackgroundOps(MongoMK mk) throws Exception {
+        Method m = MongoMK.class.getDeclaredMethod("runBackgroundOperations");
+        m.setAccessible(true);
+        m.invoke(mk);
+    }
+
+    private final class Worker implements Runnable {
 
         private final Repository repo;
         private final Map<String, Exception> exceptions;
@@ -162,21 +220,30 @@ public class ConcurrentAddNodesClusterIT
                 ensureIndex(session.getRootNode(), PROP_NAME);
 
                 String nodeName = "testroot-" + Thread.currentThread().getName();
-                Node root = session.getRootNode().addNode(nodeName, "nt:unstructured");
-                for (int i = 0; i < NODE_COUNT; i++) {
-                    Node node = root.addNode(PROP_NAME + i, "nt:unstructured");
-                    for (int j = 0; j < NODE_COUNT; j++) {
-                        Node child = node.addNode("node" + j, "nt:unstructured");
-                        child.setProperty(PROP_NAME, j);
-                    }
-                    if (!exceptions.isEmpty()) {
-                        break;
-                    }
-                    session.save();
-                }
+                createNodes(session, nodeName, LOOP_COUNT, NODE_COUNT, exceptions);
             } catch (Exception e) {
                 exceptions.put(Thread.currentThread().getName(), e);
             }
         }
     }
+
+    private void createNodes(Session session,
+                             String nodeName,
+                             int loopCount,
+                             int nodeCount,
+                             Map<String, Exception> exceptions)
+            throws RepositoryException {
+        Node root = session.getRootNode().addNode(nodeName, "nt:unstructured");
+        for (int i = 0; i < loopCount; i++) {
+            Node node = root.addNode("testnode" + i, "nt:unstructured");
+            for (int j = 0; j < nodeCount; j++) {
+                Node child = node.addNode("node" + j, "nt:unstructured");
+                child.setProperty(PROP_NAME, j);
+            }
+            if (!exceptions.isEmpty()) {
+                break;
+            }
+            session.save();
+        }
+    }
 }