jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r1104316 - /jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java
Date Tue, 17 May 2011 15:11:42 GMT
Author: stefan
Date: Tue May 17 15:11:42 2011
New Revision: 1104316

URL: http://svn.apache.org/viewvc?rev=1104316&view=rev
Log:
MicroKernel prototype (WIP)

Modified:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java?rev=1104316&r1=1104315&r2=1104316&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java
(original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java
Tue May 17 15:11:42 2011
@@ -23,8 +23,11 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
 
 /**
  *
@@ -154,10 +157,15 @@ public class CommitBuilder {
     }
 
     public String /* new revId */ doCommit() throws Exception {
+        if (staged.isEmpty()) {
+            // nothing to commit
+            return baseRevId;
+        }
+
         String currentHead = rep.getHeadRevision();
         if (!currentHead.equals(baseRevId)) {
             // update base revision to new head
-            this.baseRevId = currentHead;
+            baseRevId = currentHead;
             // clear staging area
             staged.clear();
             // replay change log on new base revision
@@ -168,69 +176,19 @@ public class CommitBuilder {
             }
         }
 
-        ArrayList<String> orderedPaths = new ArrayList<String>(staged.keySet());
-        Collections.sort(orderedPaths, new Comparator<String>() {
-            public int compare(String path1, String path2) {
-                // paths should be ordered by depth, descending
-                int result = getDepth(path2) - getDepth(path1);
-                return (result != 0) ? result : 1;
-            }
-
-            int getDepth(String path) {
-                return PathUtil.getDepth(path);
-            }
-        });
-        // iterate over staged entries in depth-descending order
-        String rootNodeId = null;
-        for (String path : orderedPaths) {
-            // persist node
-                String id = store.putNode(staged.get(path));
-            if (PathUtil.denotesRoot(path)) {
-                rootNodeId = id;
-            } else {
-                staged.get(PathUtil.getParentPath(path)).getChildNodeEntries().put(PathUtil.getName(path),
id);
-            }
-        }
-        if (rootNodeId == null) {
-            throw new Exception("internal error: inconsistent staging area content");
-        }
+        String rootNodeId = persistStagedNodes();
 
         String newRevId;
         store.lockHead();
         try {
             currentHead = rep.getHeadRevision();
             if (!currentHead.equals(baseRevId)) {
-                // recursively merge root of currentHead with new root (rootNodeId)
-/*
-                Node baseNode = rep.getNode(baseRevId, "/");
-                Node theirNode = rep.getNode(currentHead, "/");
-                Node ourNode = rep.getStore().getNode(rootNodeId);
-                NodeDelta theirChanges = new NodeDelta(baseNode, theirNode);
-                NodeDelta ourChanges = new NodeDelta(baseNode, ourNode);
-                if (!theirChanges.conflictsWith(ourChanges)) {
-                    // merge
-                    MutableNode mergedNode = new MutableNode(theirNode);
-
-                    mergedNode.getProperties().putAll(ourChanges.getAddedProperties());
-                    mergedNode.getProperties().putAll(ourChanges.getChangedProperties());
-                    for (String name : ourChanges.getRemovedProperties().keySet()) {
-                        mergedNode.getProperties().remove(name);
-                    }
-
-                    mergedNode.getChildNodeEntries().putAll(ourChanges.getAddedChildNodes());
-                    mergedNode.getChildNodeEntries().putAll(ourChanges.getChangedChildNodes());
-                    for (String name : ourChanges.getRemovedChildNodes().keySet()) {
-                        mergedNode.getChildNodeEntries().remove(name);
-                    }
-                    // persist merged root node
-                    rootNodeId = store.putNode(mergedNode);
-                    baseRevId = currentHead;
-                } else {
-                    // todo merge and/or traverse
-                }
-                // todo persist merged tree
-                rootNodeId = ...
-*/
+                Node baseRoot = rep.getNode(baseRevId, "/");
+                Node theirRoot = rep.getNode(currentHead, "/");
+                Node ourRoot = rep.getStore().getNode(rootNodeId);
+
+                rootNodeId = mergeTree(baseRoot, ourRoot, theirRoot);
+
                 baseRevId = currentHead;
             }
 
@@ -294,6 +252,88 @@ public class CommitBuilder {
         }
     }
 
+    String /* new id of root node */ persistStagedNodes() throws Exception {
+        // sort paths in in depth-descending order
+        ArrayList<String> orderedPaths = new ArrayList<String>(staged.keySet());
+        Collections.sort(orderedPaths, new Comparator<String>() {
+            public int compare(String path1, String path2) {
+                // paths should be ordered by depth, descending
+                int result = getDepth(path2) - getDepth(path1);
+                return (result != 0) ? result : 1;
+            }
+
+            int getDepth(String path) {
+                return PathUtil.getDepth(path);
+            }
+        });
+        // iterate over staged entries in depth-descending order
+        String rootNodeId = null;
+        for (String path : orderedPaths) {
+            // persist node
+            String id = store.putNode(staged.get(path));
+            if (PathUtil.denotesRoot(path)) {
+                rootNodeId = id;
+            } else {
+                staged.get(PathUtil.getParentPath(path)).getChildNodeEntries().put(PathUtil.getName(path),
id);
+            }
+        }
+        if (rootNodeId == null) {
+            throw new Exception("internal error: inconsistent staging area content");
+        }
+        return rootNodeId;
+    }
+
+    String /* id of merged root node */ mergeTree(Node baseRoot, Node ourRoot, Node theirRoot)
throws Exception {
+        // we're going to use the staging area for the merge process,
+        // clear it first
+        staged.clear();
+
+        // recursively merge 'our' changes with 'their' changes...
+        mergeNode(baseRoot, ourRoot, theirRoot, "/");
+
+        return persistStagedNodes();
+    }
+
+    void mergeNode(Node baseNode, Node ourNode, Node theirNode, String path) throws Exception
{
+        NodeDelta theirChanges = new NodeDelta(baseNode, theirNode);
+        NodeDelta ourChanges = new NodeDelta(baseNode, ourNode);
+        if (!theirChanges.conflictsWith(ourChanges)) {
+            // merge non-conflicting changes
+            MutableNode mergedNode = new MutableNode(theirNode);
+            staged.put(path, mergedNode);
+
+            mergedNode.getProperties().putAll(ourChanges.getAddedProperties());
+            mergedNode.getProperties().putAll(ourChanges.getChangedProperties());
+            for (String name : ourChanges.getRemovedProperties().keySet()) {
+                mergedNode.getProperties().remove(name);
+            }
+
+            mergedNode.getChildNodeEntries().putAll(ourChanges.getAddedChildNodes());
+            mergedNode.getChildNodeEntries().putAll(ourChanges.getChangedChildNodes());
+            for (String name : ourChanges.getRemovedChildNodes().keySet()) {
+                mergedNode.getChildNodeEntries().remove(name);
+            }
+            // we're done!
+        } else {
+            // todo resolve/report merge conflict
+
+            MutableNode mergedNode = new MutableNode(theirNode);
+            staged.put(path, mergedNode);
+
+            // identify mutually changed child nodes and merge those
+            Set<String> mutuallyChangedChildNodes = new HashSet<String>(theirChanges.getChangedChildNodes().keySet());
+            mutuallyChangedChildNodes.retainAll(ourChanges.getChangedChildNodes().keySet());
+
+            for (String name : mutuallyChangedChildNodes) {
+                Node baseChild = store.getNode(baseNode.getChildNodeEntries().get(name));
+                Node ourChild = store.getNode(ourNode.getChildNodeEntries().get(name));
+                Node theirChild = store.getNode(theirNode.getChildNodeEntries().get(name));
+                // recurse
+                mergeNode(baseChild, ourChild, theirChild, PathUtil.concat(path, name));
+            }
+        }
+    }
+
     //--------------------------------------------------------< inner classes >
     abstract class Change {
         abstract void apply() throws Exception;



Mime
View raw message