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 th...@apache.org on 2014/01/23 10:05:44 UTC

svn commit: r1560611 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ oak-jcr/src/t...

Author: thomasm
Date: Thu Jan 23 09:05:44 2014
New Revision: 1560611

URL: http://svn.apache.org/r1560611
Log:
OAK-759 MongoMK: read from a secondary member when possible (allow tests to use replica sets; a shell script to start a replica set with 3 nodes; a first manual failover test)

Added:
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/FailoverTest.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/MongoConnection.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/setup.txt
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NodeStoreFixture.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/MongoConnection.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/MongoConnection.java?rev=1560611&r1=1560610&r2=1560611&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/MongoConnection.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/MongoConnection.java Thu Jan 23 09:05:44 2014
@@ -16,11 +16,13 @@
  */
 package org.apache.jackrabbit.oak.plugins.mongomk.util;
 
+import java.net.UnknownHostException;
+
 import com.google.common.base.Objects;
 import com.mongodb.DB;
 import com.mongodb.MongoClient;
 import com.mongodb.MongoClientOptions;
-import com.mongodb.ServerAddress;
+import com.mongodb.MongoClientURI;
 
 /**
  * The {@code MongoConnection} abstracts connection to the {@code MongoDB}.
@@ -31,6 +33,20 @@ public class MongoConnection {
     private final MongoClient mongo;
 
     /**
+     * Constructs a new connection using the specified MongoDB connection string.
+     * See also http://docs.mongodb.org/manual/reference/connection-string/
+     * 
+     * @param uri the MongoDB URI
+     * @throws UnknownHostException
+     */
+    public MongoConnection(String uri) throws UnknownHostException  {
+        MongoClientOptions.Builder builder = MongoConnection.getDefaultBuilder();
+        MongoClientURI mongoURI = new MongoClientURI(uri, builder);
+        mongo = new MongoClient(mongoURI);
+        db = mongo.getDB(mongoURI.getDatabase());
+    }
+    
+    /**
      * Constructs a new {@code MongoConnection}.
      *
      * @param host The host address.
@@ -39,10 +55,7 @@ public class MongoConnection {
      * @throws Exception If an error occurred while trying to connect.
      */
     public MongoConnection(String host, int port, String database) throws Exception {
-        MongoClientOptions options = getDefaultBuilder().build();
-        ServerAddress serverAddress = new ServerAddress(host, port);
-        mongo = new MongoClient(serverAddress, options);
-        db = mongo.getDB(database);
+        this("mongodb://" + host + ":" + port + "/" + database);
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/setup.txt
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/setup.txt?rev=1560611&r1=1560610&r2=1560611&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/setup.txt (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/setup.txt Thu Jan 23 09:05:44 2014
@@ -83,3 +83,41 @@ du -h .
 db.printShardingStatus()
 exit
 
+
+=== Testing with a local Replica Set
+
+# within the mongodb directory:
+
+cd <mongodb/bin>
+
+# create a replica set with 2 replicas and 1 arbiter:
+# see also http://docs.mongodb.org/manual/tutorial/deploy-replica-set/
+
+killall mongod
+rm -rf db1; mkdir db1
+rm -rf db2; mkdir db2
+rm -rf db3; mkdir db3
+./mongod --replSet test --dbpath db1 --port 27017 > db1/log.txt &
+./mongod --replSet test --dbpath db2 --port 27018 > db2/log.txt &
+./mongod --replSet test --dbpath db3 --port 27019 > db3/log.txt &
+while ! nc -vz localhost 27017; do sleep 1; done
+while ! nc -vz localhost 27018; do sleep 1; done
+while ! nc -vz localhost 27019; do sleep 1; done
+./mongo --eval "rs.initiate({_id:'test', members:[ \
+  {_id:0, host:'localhost:27017'}, \
+  {_id:1, host:'localhost:27018'}, \
+  {_id:2, host:'localhost:27019', arbiterOnly:true}, \
+]});"
+
+# display configuration:
+
+./mongo
+rs.config()
+
+# display processes:
+
+ps -ef | grep "./mongod "
+
+# kill the one on port 27017:
+
+ps -l | grep "mongod" | grep "port 27017" | awk '{print $2}' | xargs kill -9

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NodeStoreFixture.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NodeStoreFixture.java?rev=1560611&r1=1560610&r2=1560611&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NodeStoreFixture.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/NodeStoreFixture.java Thu Jan 23 09:05:44 2014
@@ -57,12 +57,9 @@ public abstract class NodeStoreFixture {
         
         @Override
         public NodeStore createNodeStore(int clusterNodeId) {
-            String host = "localhost";
-            int port = 27017;
-            String db = "oak";
             MongoConnection connection;
             try {
-                connection = new MongoConnection(host, port, db);
+                connection = new MongoConnection("mongodb://localhost:27017/oak");
                 DB mongoDB = connection.getDB();
                 MongoMK mk = new MongoMK.Builder()
                                 .setMongoDB(mongoDB).open();
@@ -83,36 +80,8 @@ public abstract class NodeStoreFixture {
             }
         }
     };
-
-    public static final NodeStoreFixture MONGO_NS = new NodeStoreFixture() {
-        @Override
-        public NodeStore createNodeStore() {
-            return new MongoMK.Builder().getNodeStore();
-        }
-        
-        @Override
-        public NodeStore createNodeStore(int clusterNodeId) {
-            String host = "localhost";
-            int port = 27017;
-            String db = "oak";
-            MongoConnection connection;
-            try {
-                connection = new MongoConnection(host, port, db);
-                DB mongoDB = connection.getDB();
-                return new MongoMK.Builder()
-                                .setMongoDB(mongoDB).getNodeStore();
-            } catch (Exception e) {
-                return null;
-            }
-        }
-
-        @Override
-        public void dispose(NodeStore nodeStore) {
-            if (nodeStore instanceof MongoNodeStore) {
-                ((MongoNodeStore) nodeStore).dispose();
-            }
-        }
-    };
+    
+    public static final NodeStoreFixture MONGO_NS = createMongoFixture("mongodb://localhost:27017/oak");
 
     public static final NodeStoreFixture MONGO_JDBC = new NodeStoreFixture() {
         @Override
@@ -149,6 +118,35 @@ public abstract class NodeStoreFixture {
         public void dispose(NodeStore nodeStore) {
         }
     };
+    
+    public static NodeStoreFixture createMongoFixture(final String uri) {
+        return new NodeStoreFixture() {
+            @Override
+            public NodeStore createNodeStore() {
+                return new MongoMK.Builder().getNodeStore();
+            }
+            
+            @Override
+            public NodeStore createNodeStore(int clusterNodeId) {
+                MongoConnection connection;
+                try {
+                    connection = new MongoConnection(uri);
+                    DB mongoDB = connection.getDB();
+                    return new MongoMK.Builder()
+                                    .setMongoDB(mongoDB).getNodeStore();
+                } catch (Exception e) {
+                    return null;
+                }
+            }
+
+            @Override
+            public void dispose(NodeStore nodeStore) {
+                if (nodeStore instanceof MongoNodeStore) {
+                    ((MongoNodeStore) nodeStore).dispose();
+                }
+            }
+        };
+    }
 
     /**
      * Creates a new empty {@link NodeStore} instance. An implementation must

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java?rev=1560611&r1=1560610&r2=1560611&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/AbstractClusterTest.java Thu Jan 23 09:05:44 2014
@@ -36,11 +36,15 @@ import org.junit.Before;
  */
 public class AbstractClusterTest {
 
-    protected NodeStoreFixture fixture = NodeStoreFixture.MONGO_MK;
+    protected NodeStoreFixture fixture = getFixture();
     protected NodeStore ns1, ns2;
     protected Repository r1, r2;
     protected Session s1, s2;
     
+    protected NodeStoreFixture getFixture() {
+        return NodeStoreFixture.MONGO_NS;
+    }
+    
     @After
     public void logout() {
         if (s1 != null) {

Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/FailoverTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/FailoverTest.java?rev=1560611&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/FailoverTest.java (added)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/cluster/FailoverTest.java Thu Jan 23 09:05:44 2014
@@ -0,0 +1,76 @@
+/*
+ * 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.cluster;
+
+import org.apache.jackrabbit.oak.jcr.NodeStoreFixture;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ * Tests the behavior of Oak when facing MongoDB failover.
+ */
+@Ignore("OAK-759")
+public class FailoverTest extends AbstractClusterTest {
+    
+    @Override
+    protected NodeStoreFixture getFixture() {
+        return NodeStoreFixture.createMongoFixture(
+                "mongodb://localhost:27017,localhost:27018,localhost:27019/oak");
+    }
+
+    @Test 
+    @SuppressWarnings("unused") 
+    public void test() throws Exception {
+        if (s1 == null) {
+            return;
+        }
+        if (s1.getRootNode().hasNode("test")) {
+            s1.getRootNode().getNode("test").remove();
+        }
+        for (int i = 0; i < 100; i++) {
+            String nodeName = "test" + i;
+            System.out.println("testing with " + nodeName);
+            s1.getRootNode().addNode(nodeName);
+            s1.save();
+            for (int x : seconds(5)) {
+                s2.refresh(false);
+                if (s2.getRootNode().hasNode(nodeName)) {
+                    break;
+                }
+            }
+            s2.getRootNode().getNode(nodeName).remove();
+            s2.save();
+            for (int x : seconds(5)) {
+                s1.refresh(false);
+                if (!s1.getRootNode().hasNode(nodeName)) {
+                    break;
+                }
+            }
+            s1.getRootNode().addNode(nodeName);
+            s1.save();
+            for (int x : seconds(5)) {
+                s2.refresh(false);
+                if (s2.getRootNode().hasNode(nodeName)) {
+                    break;
+                }
+            }
+            s2.getRootNode().getNode(nodeName).remove();
+            s2.save();        
+        }
+    }
+        
+}



Re: svn commit: r1560611 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ oak-jcr/src/t...

Posted by Chetan Mehrotra <ch...@gmail.com>.
On Fri, Apr 25, 2014 at 11:04 PM, Jukka Zitting <ju...@gmail.com> wrote:
> The credentials in any case need to be valid for the database that
> holds the repository, so I don't see why we couldn't use it for this
> purpose.

As per the doc the database name tells mongo driver the name of DB in
which user details are stored. Typically in SQL database the admin
user tables are managed in a dedicated schema. Probably similar scheme
is followed in Mongo side also.

Probably we can modify the logic to use the db name present as part of
url if no db name is explicitly provided via 'oak.mongo.db'


Chetan Mehrotra

Re: svn commit: r1560611 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ oak-jcr/src/t...

Posted by Jukka Zitting <ju...@gmail.com>.
Hi,

On Thu, Jan 23, 2014 at 5:45 AM, Chetan Mehrotra
<ch...@gmail.com> wrote:
> On Thu, Jan 23, 2014 at 2:35 PM,  <th...@apache.org> wrote:
>> +        mongo = new MongoClient(mongoURI);
>> +        db = mongo.getDB(mongoURI.getDatabase());
>
> The database referred in the URI is used by Mongo for determining the
> user database against which credentials if passed needs to be
> validated.

The credentials in any case need to be valid for the database that
holds the repository, so I don't see why we couldn't use it for this
purpose.

BR,

Jukka Zitting

Re: svn commit: r1560611 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ oak-jcr/src/t...

Posted by Chetan Mehrotra <ch...@gmail.com>.
On Thu, Jan 23, 2014 at 2:35 PM,  <th...@apache.org> wrote:
> +        mongo = new MongoClient(mongoURI);
> +        db = mongo.getDB(mongoURI.getDatabase());

The database referred in the URI is used by Mongo for determining the
user database against which credentials if passed needs to be
validated.

------------------
/database
Optional. The name of the database to authenticate if the connection
string includes authentication credentials in the form of
username:password@. If /database is not specified and the connection
string includes credentials, the driver will authenticate to the admin
database.
------------------

So far we do not make use of credentials so database field can be
used. But better to manage it in a separate way.

Chetan Mehrotra
[1] http://docs.mongodb.org/manual/reference/connection-string/

Re: svn commit: r1560611 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/util/ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/ oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/ oak-jcr/src/t...

Posted by Chetan Mehrotra <ch...@gmail.com>.
On Thu, Jan 23, 2014 at 2:35 PM,  <th...@apache.org> wrote:
> +        mongo = new MongoClient(mongoURI);
> +        db = mongo.getDB(mongoURI.getDatabase());

The database referred in the URI is used by Mongo for determining the
user database against which credentials if passed needs to be
validated.

------------------
/database
Optional. The name of the database to authenticate if the connection
string includes authentication credentials in the form of
username:password@. If /database is not specified and the connection
string includes credentials, the driver will authenticate to the admin
database.
------------------

So far we do not make use of credentials so database field can be
used. But better to manage it in a separate way.

Chetan Mehrotra
[1] http://docs.mongodb.org/manual/reference/connection-string/