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 ju...@apache.org on 2013/03/13 09:21:53 UTC

svn commit: r1455835 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment: MongoJournal.java MongoStore.java

Author: jukka
Date: Wed Mar 13 08:21:52 2013
New Revision: 1455835

URL: http://svn.apache.org/r1455835
Log:
OAK-593: Segment-based MK

More careful use of MongoDB write concerns and read preferences

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoJournal.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoStore.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoJournal.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoJournal.java?rev=1455835&r1=1455834&r2=1455835&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoJournal.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoJournal.java Wed Mar 13 08:21:52 2013
@@ -20,6 +20,8 @@ import static com.google.common.base.Pre
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.collect.ImmutableMap.of;
+import static com.mongodb.ReadPreference.nearest;
+import static com.mongodb.ReadPreference.primaryPreferred;
 
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -28,6 +30,8 @@ import com.mongodb.BasicDBObject;
 import com.mongodb.BasicDBObjectBuilder;
 import com.mongodb.DBCollection;
 import com.mongodb.DBObject;
+import com.mongodb.WriteConcern;
+import com.mongodb.WriteResult;
 
 class MongoJournal implements Journal {
 
@@ -35,30 +39,43 @@ class MongoJournal implements Journal {
 
     private final DBCollection journals;
 
+    private final WriteConcern concern;
+
     private final String name;
 
-    MongoJournal(SegmentStore store, DBCollection journals, NodeState root) {
+    MongoJournal(
+            SegmentStore store, DBCollection journals,
+            WriteConcern concern, NodeState root) {
         this.store = checkNotNull(store);
         this.journals = checkNotNull(journals);
+        this.concern = checkNotNull(concern);
         this.name = "root";
 
-        DBObject state = journals.findOne(new BasicDBObject("_id", "root"));
+        DBObject id = new BasicDBObject("_id", "root");
+        DBObject fields = new BasicDBObject("head", 1);
+        DBObject state = journals.findOne(id, fields, primaryPreferred());
         if (state == null) {
             SegmentWriter writer = new SegmentWriter(store);
-            RecordId id = writer.writeNode(root).getRecordId();
+            RecordId head = writer.writeNode(root).getRecordId();
             writer.flush();
-            state = new BasicDBObject(of("_id", "root", "head", id.toString()));
-            journals.insert(state);
+            state = new BasicDBObject(of(
+                    "_id",  "root",
+                    "head", head.toString()));
+            journals.insert(state, concern);
         }
     }
 
-    MongoJournal(SegmentStore store, DBCollection journals, String name) {
+    MongoJournal(
+            SegmentStore store, DBCollection journals,
+            WriteConcern concern, String name) {
         this.store = checkNotNull(store);
         this.journals = checkNotNull(journals);
+        this.concern = checkNotNull(concern);
         this.name = checkNotNull(name);
         checkArgument(!"root".equals(name));
 
-        DBObject state = journals.findOne(new BasicDBObject("_id", name));
+        DBObject id = new BasicDBObject("_id", name);
+        DBObject state = journals.findOne(id, null, primaryPreferred());
         if (state == null) {
             Journal root = store.getJournal("root");
             String head = root.getHead().toString();
@@ -67,20 +84,25 @@ class MongoJournal implements Journal {
                     "parent", "root",
                     "base",   head,
                     "head",   head));
-            journals.insert(state);
+            journals.insert(state, concern);
         }
     }
 
     @Override
     public RecordId getHead() {
-        DBObject state = journals.findOne(new BasicDBObject("_id", name));
+        DBObject id = new BasicDBObject("_id", name);
+        DBObject state = journals.findOne(id, null, nearest());
+        if (state == null) {
+            state = journals.findOne(id, null, primaryPreferred());
+        }
         checkState(state != null);
         return RecordId.fromString(state.get("head").toString());
     }
 
     @Override
     public synchronized boolean setHead(RecordId base, RecordId head) {
-        DBObject state = journals.findOne(new BasicDBObject("_id", name));
+        DBObject id = new BasicDBObject("_id", name);
+        DBObject state = journals.findOne(id, null, primaryPreferred());
         checkState(state != null);
         if (!base.toString().equals(state.get("head"))) {
             return false;
@@ -97,12 +119,15 @@ class MongoJournal implements Journal {
         builder.add("head", head.toString());
         DBObject nextState = builder.get();
 
-        return journals.findAndModify(state, nextState) != null;
+        WriteResult result =
+                journals.update(state, nextState, false, false, concern);
+        return result.getN() != 0;
     }
 
     @Override
-    public void merge() {
-        DBObject state = journals.findOne(new BasicDBObject("_id", name));
+    public synchronized void merge() {
+        DBObject id = new BasicDBObject("_id", name);
+        DBObject state = journals.findOne(id, null, primaryPreferred());
         checkState(state != null);
 
         if (state.containsField("parent")) {
@@ -134,7 +159,8 @@ class MongoJournal implements Journal {
             builder.add("parent", state.get("parent"));
             builder.add("base", base.toString());
             builder.add("head", head.toString());
-            journals.update(state, builder.get());
+            // TODO: concurrent updates?
+            journals.update(state, builder.get(), false, false, concern);
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoStore.java?rev=1455835&r1=1455834&r2=1455835&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MongoStore.java Wed Mar 13 08:21:52 2013
@@ -16,6 +16,9 @@
  */
 package org.apache.jackrabbit.oak.plugins.segment;
 
+import static com.google.common.collect.ImmutableMap.of;
+import static com.mongodb.ReadPreference.nearest;
+import static com.mongodb.ReadPreference.primary;
 import static org.apache.jackrabbit.oak.plugins.memory.MemoryNodeState.EMPTY_NODE;
 
 import java.util.List;
@@ -28,9 +31,12 @@ import com.mongodb.DB;
 import com.mongodb.DBCollection;
 import com.mongodb.DBObject;
 import com.mongodb.Mongo;
+import com.mongodb.WriteConcern;
 
 public class MongoStore implements SegmentStore {
 
+    private final WriteConcern concern = WriteConcern.SAFE; // TODO: MAJORITY?
+
     private final DBCollection segments;
 
     private final DBCollection journals;
@@ -56,9 +62,9 @@ public class MongoStore implements Segme
     @Override
     public Journal getJournal(String name) {
         if ("root".equals(name)) {
-            return new MongoJournal(this, journals, EMPTY_NODE);
+            return new MongoJournal(this, journals, concern, EMPTY_NODE);
         } else {
-            return new MongoJournal(this, journals, name);
+            return new MongoJournal(this, journals, concern, name);
         }
     }
 
@@ -93,11 +99,16 @@ public class MongoStore implements Segme
     }
 
     private Segment findSegment(UUID segmentId) {
-        DBObject segment = segments.findOne(
-                new BasicDBObject("_id", segmentId.toString()));
+        DBObject id = new BasicDBObject("_id", segmentId.toString());
+        DBObject fields = new BasicDBObject(of("data", 1, "uuids", 1));
+
+        DBObject segment = segments.findOne(id, fields, nearest());
         if (segment == null) {
-            throw new IllegalStateException(
-                    "Segment " + segmentId + " not found");
+            segment = segments.findOne(id, fields, primary());
+            if (segment == null) {
+                throw new IllegalStateException(
+                        "Segment " + segmentId + " not found");
+            }
         }
 
         byte[] data = (byte[]) segment.get("data");
@@ -119,7 +130,7 @@ public class MongoStore implements Segme
         segment.put("_id", segmentId.toString());
         segment.put("data", data);
         segment.put("uuids", list);
-        segments.insert(segment);
+        segments.insert(segment, concern);
     }
 
     @Override