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 ch...@apache.org on 2013/02/22 13:40:03 UTC

svn commit: r1449018 - in /jackrabbit/oak/trunk/oak-mongomk/src: main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java

Author: chetanm
Date: Fri Feb 22 12:40:03 2013
New Revision: 1449018

URL: http://svn.apache.org/r1449018
Log:
OAK-619 - Lock-free MongoMK implementation

 Adding initial support for node deletion. Deleted nodes have '_deleted' set to true in versioned manner and retrieval logic check for this property for finding valid nodes.

 This impl though would not work well for deletion of deep node hierarchies.

Modified:
    jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java
    jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java

Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java?rev=1449018&r1=1449017&r2=1449018&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/prototype/MongoMK.java Fri Feb 22 12:40:03 2013
@@ -216,6 +216,10 @@ public class MongoMK implements MicroKer
         List<Map<String, Object>> list = store.query(DocumentStore.Collection.NODES, from, to, limit);
         Node.Children c = new Node.Children(path, rev);
         for (Map<String, Object> e : list) {
+            //Filter out deleted children
+            if(isDeleted(e,rev)){
+                continue;
+            }
             // TODO put the whole node in the cache
             String id = e.get("_id").toString();
             String p = id.substring(2);
@@ -230,6 +234,9 @@ public class MongoMK implements MicroKer
         if (map == null) {
             return null;
         }
+        if(isDeleted(map,rev)){
+            return null;
+        }
         Node n = new Node(path, rev);
         Long w = writeCountIncrements.get(path);
         long writeCount = w == null ? 0 : w;
@@ -366,6 +373,7 @@ public class MongoMK implements MicroKer
             case '-':
                 // TODO support remove operations
                 commit.removeNode(path);
+                markAsDeleted(path,commit,rev);
                 break;
             case '^':
                 t.read(':');
@@ -466,8 +474,38 @@ public class MongoMK implements MicroKer
         }
         applyCommit(commit);
         return rev.toString();
-    }    
-    
+    }
+
+    private void markAsDeleted(String path, Commit commit, Revision rev) {
+        UpdateOp op = commit.getUpdateOperationForNode(path);
+        op.addMapEntry("_deleted", rev.toString(), "true");
+        op.increment("_writeCount", 1);
+
+        //TODO Would cause issue with large number of children. Need to be
+        //relooked
+        Node.Children c  = readChildren(path,rev,Integer.MAX_VALUE);
+        for(String childPath : c.children){
+            markAsDeleted(childPath,commit, rev);
+        }
+    }
+
+    private boolean isDeleted(Map<String, Object> nodeProps,Revision rev){
+        Map<String,String> valueMap = (Map<String, String>) nodeProps.get("_deleted");
+        if(valueMap != null){
+            for (Map.Entry<String,String> e : valueMap.entrySet()) {
+                //TODO What if multiple revisions are there?. Should we sort them and then
+                //determine include revision based on that
+                Revision propRev = Revision.fromString(e.getKey());
+                if (includeRevision(propRev, rev)) {
+                     if("true".equals(e.getValue())){
+                         return true;
+                     }
+                }
+            }
+        }
+        return false;
+    }
+
     private void applyCommit(Commit commit) {
         headRevision = commit.getRevision();
         if (commit.isEmpty()) {

Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java?rev=1449018&r1=1449017&r2=1449018&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/prototype/SimpleTest.java Fri Feb 22 12:40:03 2013
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.mongomk.prototype;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
 import org.apache.jackrabbit.mongomk.prototype.DocumentStore.Collection;
@@ -64,10 +65,9 @@ public class SimpleTest {
 
     @Test
     public void commit() {
-        MongoMK mk = new MongoMK();
-
-        String rev;
-        rev = mk.commit("/", "+\"test\":{\"name\": \"Hello\"}", null, null);
+        MongoMK mk = createMK();
+        
+        String rev = mk.commit("/", "+\"test\":{\"name\": \"Hello\"}", null, null);
         String test = mk.getNodes("/test", rev, 0, 0, Integer.MAX_VALUE, null);
         assertEquals("{\"name\":\"Hello\",\":childNodeCount\":0}", test);
         
@@ -89,7 +89,34 @@ public class SimpleTest {
         System.out.println(test);
         mk.dispose();
     }
-    
+
+    @Test
+    public void testDeletion(){
+        MongoMK mk = createMK();
+
+        String rev = mk.commit("/", "+\"testDel\":{\"name\": \"Hello\"}", null, null);
+        rev = mk.commit("/testDel", "+\"a\":{\"name\": \"World\"}", null, null);
+        rev = mk.commit("/testDel", "+\"b\":{\"name\": \"!\"}", null, null);
+        rev = mk.commit("/testDel", "+\"c\":{\"name\": \"!\"}", null, null);
+
+        Children c = mk.readChildren("/testDel",
+                Revision.fromString(rev), Integer.MAX_VALUE);
+        assertEquals(3,c.children.size());
+
+        rev = mk.commit("/testDel", "-\"c\"", null, null);
+        c = mk.readChildren("/testDel", Revision.fromString(rev), Integer.MAX_VALUE);
+        assertEquals(2,c.children.size());
+
+        rev = mk.commit("/", "-\"testDel\"", null, null);
+        Node n = mk.getNode("/testDel",Revision.fromString(rev));
+        assertNull(n);
+    }
+
+    private MongoMK createMK() {
+        return new MongoMK();
+//        return new MongoMK(MongoUtils.getConnection().getDB(),0);
+    }
+
     // TODO run Damians tests
     
 }