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 2012/05/16 10:30:52 UTC

svn commit: r1339056 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: plugins/memory/MemoryNodeStateBuilder.java plugins/memory/MemoryNodeStore.java plugins/memory/ModifiedNodeState.java spi/state/DefaultNodeStateDiff.java

Author: jukka
Date: Wed May 16 08:30:51 2012
New Revision: 1339056

URL: http://svn.apache.org/viewvc?rev=1339056&view=rev
Log:
OAK-68: Extension point for commit validation

Add rebase handling to the in-memory draft

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/DefaultNodeStateDiff.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java?rev=1339056&r1=1339055&r2=1339056&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStateBuilder.java Wed May 16 08:30:51 2012
@@ -46,10 +46,14 @@ public class MemoryNodeStateBuilder impl
 
     @Override
     public NodeState getNodeState() {
-        return new ModifiedNodeState(
-                base,
-                new HashMap<String, PropertyState>(properties),
-                new HashMap<String, NodeState>(nodes));
+        if (properties.isEmpty() && nodes.isEmpty()) {
+            return base; // shortcut
+        } else {
+            return new ModifiedNodeState(
+                    base,
+                    new HashMap<String, PropertyState>(properties),
+                    new HashMap<String, NodeState>(nodes));
+        }
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java?rev=1339056&r1=1339055&r2=1339056&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/MemoryNodeStore.java Wed May 16 08:30:51 2012
@@ -57,14 +57,22 @@ public class MemoryNodeStore extends Abs
 
     @Override
     public void setRoot(NodeState newRoot) throws CommitFailedException {
-        while (true) {
-            NodeState oldRoot = getRoot();
-            NodeState setRoot = commitHook.beforeCommit(this, oldRoot, newRoot);
-            if (root.compareAndSet(oldRoot, setRoot)) {
-                return;
-            } else {
-                // TODO: try to rebase the changes in newRoot
-            }
+        NodeState oldRoot;
+        do {
+            oldRoot = root.get();
+            newRoot = rebase(newRoot, oldRoot);
+        } while (!root.compareAndSet(
+                oldRoot, commitHook.beforeCommit(this, oldRoot, newRoot)));
+    }
+
+    NodeState rebase(NodeState state, NodeState base)
+            throws CommitFailedException {
+        if (state instanceof ModifiedNodeState) {
+            return ((ModifiedNodeState) state).rebase(this, base);
+        } else if (state.equals(base)) {
+            return state;
+        } else {
+            throw new CommitFailedException("Failed to rebase changes");
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java?rev=1339056&r1=1339055&r2=1339056&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/ModifiedNodeState.java Wed May 16 08:30:51 2012
@@ -16,14 +16,17 @@
  */
 package org.apache.jackrabbit.oak.plugins.memory;
 
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
 import org.apache.commons.collections.IteratorUtils;
 import org.apache.commons.collections.Predicate;
 import org.apache.commons.collections.PredicateUtils;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
+import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.ProxyNodeState;
 
@@ -42,6 +45,64 @@ public class ModifiedNodeState extends P
         this.nodes = nodes;
     }
 
+    NodeState getBase() {
+        return delegate;
+    }
+
+    ModifiedNodeState rebase(MemoryNodeStore store, NodeState base)
+            throws CommitFailedException {
+        if (delegate.equals(base)) {
+            return this;
+        } else if (nodes.isEmpty()) {
+            return this; // shortcut
+        } else {
+            return new ModifiedNodeState(
+                    base, properties, rebaseChildren(store, base));
+        }
+    }
+
+    private Map<String, NodeState> rebaseChildren(
+            final MemoryNodeStore store, NodeState base)
+            throws CommitFailedException {
+        // TODO: better conflict resolution
+        final Map<String, NodeState> rebasedNodes =
+                new HashMap<String, NodeState>(nodes);
+        final Map<String, CommitFailedException> failures =
+                new HashMap<String, CommitFailedException>();
+        store.compare(delegate, base, new DefaultNodeStateDiff() {
+            @Override
+            public void childNodeAdded(String name, NodeState after) {
+                rebaseChild(name, after);
+            }
+            @Override
+            public void childNodeChanged(
+                    String name, NodeState before, NodeState after) {
+                rebaseChild(name, after);
+            }
+            @Override
+            public void childNodeDeleted(String name, NodeState before) {
+                rebaseChild(name, MemoryNodeState.EMPTY_NODE);
+            }
+            private void rebaseChild(String name, NodeState base) {
+                NodeState child = nodes.get(name);
+                if (child != null) {
+                    try {
+                        rebasedNodes.put(name, store.rebase(child, base));
+                    } catch (CommitFailedException e) {
+                        failures.put(name, e);
+                    }
+                }
+            }
+        });
+        if (failures.isEmpty()) {
+            return rebasedNodes;
+        } else {
+            throw new CommitFailedException("Failed to rebase changes");
+        }
+    }
+
+    //---------------------------------------------------------< NodeState >--
+
     @Override
     public PropertyState getProperty(String name) {
         if (properties.containsKey(name)) {

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/DefaultNodeStateDiff.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/DefaultNodeStateDiff.java?rev=1339056&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/DefaultNodeStateDiff.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/DefaultNodeStateDiff.java Wed May 16 08:30:51 2012
@@ -0,0 +1,62 @@
+/*
+ * 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.spi.state;
+
+import org.apache.jackrabbit.oak.api.PropertyState;
+
+/**
+ * Node state diff handler that by default does nothing. Useful as a base
+ * class for more complicated diff handlers that can safely ignore one or
+ * more types of changes.
+ */
+public class DefaultNodeStateDiff implements NodeStateDiff {
+
+    public static final NodeStateDiff INSTANCE = new DefaultNodeStateDiff();
+
+    @Override
+    public void propertyAdded(PropertyState after) {
+        // do nothing
+    }
+
+    @Override
+    public void propertyChanged(PropertyState before, PropertyState after) {
+        // do nothing
+    }
+
+    @Override
+    public void propertyDeleted(PropertyState before) {
+        // do nothing
+    }
+
+    @Override
+    public void childNodeAdded(String name, NodeState after) {
+        // do nothing
+    }
+
+    @Override
+    public void childNodeChanged(String name, NodeState before, NodeState after) {
+        // do nothing
+    }
+
+    @Override
+    public void childNodeDeleted(String name, NodeState before) {
+        // do nothing
+    }
+
+}