Return-Path: X-Original-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Delivered-To: apmail-jackrabbit-oak-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A04FC10737 for ; Tue, 3 Dec 2013 08:38:35 +0000 (UTC) Received: (qmail 49789 invoked by uid 500); 3 Dec 2013 08:38:31 -0000 Delivered-To: apmail-jackrabbit-oak-commits-archive@jackrabbit.apache.org Received: (qmail 49711 invoked by uid 500); 3 Dec 2013 08:38:27 -0000 Mailing-List: contact oak-commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: oak-dev@jackrabbit.apache.org Delivered-To: mailing list oak-commits@jackrabbit.apache.org Received: (qmail 48782 invoked by uid 99); 3 Dec 2013 08:38:23 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Dec 2013 08:38:23 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 03 Dec 2013 08:38:19 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 7940523888E4; Tue, 3 Dec 2013 08:37:58 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1547314 - in /jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr: ConcurrentAddNodesClusterIT.java OakMongoMKRepositoryStub.java Date: Tue, 03 Dec 2013 08:37:58 -0000 To: oak-commits@jackrabbit.apache.org From: mreutegg@apache.org X-Mailer: svnmailer-1.0.9 Message-Id: <20131203083758.7940523888E4@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: mreutegg Date: Tue Dec 3 08:37:58 2013 New Revision: 1547314 URL: http://svn.apache.org/r1547314 Log: OAK-1254: Parallel execution of SimpleSearchTest fails with MongoMK - add standalone test to reproduce exception Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java (with props) Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakMongoMKRepositoryStub.java Added: 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=1547314&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java (added) +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java Tue Dec 3 08:37:58 2013 @@ -0,0 +1,182 @@ +/* + * 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.jcr; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.PropertyType; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; + +import org.apache.jackrabbit.oak.plugins.index.IndexConstants; +import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider; +import org.apache.jackrabbit.oak.plugins.mongomk.MongoMK; +import org.apache.jackrabbit.oak.plugins.mongomk.util.MongoConnection; +import org.junit.After; +import org.junit.Assume; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Concurrently add nodes with multiple sessions on multiple cluster nodes. + */ +@Ignore("OAK-1254") +public class ConcurrentAddNodesClusterIT { + + private static final int NUM_CLUSTER_NODES = 3; + private static final int NODE_COUNT = 100; + private static final String PROP_NAME = "testcount"; + + private List mks = new ArrayList(); + private List workers = new ArrayList(); + + @BeforeClass + public static void mongoDBAvailable() { + Assume.assumeTrue(OakMongoMKRepositoryStub.isMongoDBAvailable()); + } + + @Before + 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 + public void after() throws Exception { + for (MongoMK mk : mks) { + mk.dispose(); + } + dropDB(); + } + + @Test + public void addNodes() throws Exception { + Map exceptions = Collections.synchronizedMap(new HashMap()); + for (int i = 0; i < mks.size(); i++) { + MongoMK mk = mks.get(i); + Repository repo = new Jcr(mk).createRepository(); + workers.add(new Thread(new Worker(repo, exceptions), "Worker-" + (i + 1))); + } + for (Thread t : workers) { + t.start(); + } + for (Thread t : workers) { + t.join(); + } + for (Map.Entry entry : exceptions.entrySet()) { + // System.out.println("exception in thread " + entry.getKey()); + throw entry.getValue(); + } + } + + private static MongoConnection createConnection() throws Exception { + return OakMongoMKRepositoryStub.createConnection( + ConcurrentAddNodesClusterIT.class.getSimpleName()); + } + + private static void dropDB() throws Exception { + MongoConnection con = createConnection(); + try { + con.getDB().dropDatabase(); + } finally { + con.close(); + } + } + + private static void initRepository() throws Exception { + MongoConnection con = createConnection(); + MongoMK mk = new MongoMK.Builder() + .setMongoDB(con.getDB()) + .setClusterId(1).open(); + Session session = new Jcr(mk).createRepository().login( + new SimpleCredentials("admin", "admin".toCharArray())); + session.logout(); + mk.dispose(); // closes connection as well + } + + + private static void ensureIndex(Node root, String propertyName) + throws RepositoryException { + Node indexDef = root.getNode(IndexConstants.INDEX_DEFINITIONS_NAME); + if (indexDef.hasNode(propertyName)) { + return; + } + Node index = indexDef.addNode(propertyName, IndexConstants.INDEX_DEFINITIONS_NODE_TYPE); + index.setProperty(IndexConstants.TYPE_PROPERTY_NAME, + PropertyIndexEditorProvider.TYPE); + index.setProperty(IndexConstants.REINDEX_PROPERTY_NAME, + true); + index.setProperty(IndexConstants.PROPERTY_NAMES, + new String[] { propertyName }, PropertyType.NAME); + try { + root.getSession().save(); + } catch (RepositoryException e) { + // created by other thread -> ignore + } + } + + private static final class Worker implements Runnable { + + private final Repository repo; + private final Map exceptions; + + Worker(Repository repo, Map exceptions) { + this.repo = repo; + this.exceptions = exceptions; + } + + @Override + public void run() { + try { + Session session = repo.login(new SimpleCredentials( + "admin", "admin".toCharArray())); + 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(); + } + } catch (Exception e) { + exceptions.put(Thread.currentThread().getName(), e); + } + } + } +} Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ConcurrentAddNodesClusterIT.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Rev URL Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakMongoMKRepositoryStub.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakMongoMKRepositoryStub.java?rev=1547314&r1=1547313&r2=1547314&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakMongoMKRepositoryStub.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/OakMongoMKRepositoryStub.java Tue Dec 3 08:37:58 2013 @@ -117,8 +117,7 @@ public class OakMongoMKRepositoryStub ex public static boolean isMongoDBAvailable() { MongoConnection connection = null; try { - connection = new MongoConnection(HOST, PORT, DB); - connection.getDB().command(new BasicDBObject("ping", 1)); + connection = createConnection(DB); return true; } catch (Exception e) { return false; @@ -129,6 +128,20 @@ public class OakMongoMKRepositoryStub ex } } + static MongoConnection createConnection(String db) throws Exception { + boolean success = false; + MongoConnection con = new MongoConnection(HOST, PORT, db); + try { + con.getDB().command(new BasicDBObject("ping", 1)); + success = true; + } finally { + if (!success) { + con.close(); + } + } + return con; + } + /** * Returns the configured repository instance. *