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/10/23 21:51:01 UTC

svn commit: r1535136 [1/2] - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/api/ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/ oak-core/src/main/java/org/apac...

Author: jukka
Date: Wed Oct 23 19:51:00 2013
New Revision: 1535136

URL: http://svn.apache.org/r1535136
Log:
OAK-1112: Support user data in local events

Add a message argument to Root.commit() and use it to pass the current
user data (if any) from the committing session to the CommitInfos attached
to locally observed commits.

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreBranch.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/NodeStoreKernel.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.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/mongomk/CommitQueue.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitInfo.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/OakInitializer.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStoreBranch.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeBuilderTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreCacheTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/NodeStoreTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueueTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/JournalTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/MergeTest.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/VersionManagerDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/ReadWriteVersionManager.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionManagerImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionStorage.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/api/Root.java Wed Oct 23 19:51:00 2013
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.oak.api;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 
@@ -104,20 +105,38 @@ public interface Root {
     void refresh();
 
     /**
-     * Atomically persists all changes made to the tree contained in this root to the underlying
-     * store.
+     * Atomically persists all changes made to the tree attached to this root.
+     * Before any changes are actually persisted the passed commit hook is
+     * run and it fail the commit by throwing a {@code CommitFailedException}.
+     * The commit hook is invoked <em>before</em> any other commit hooks that
+     * might be present in this root.
      * <p>
-     * Before any changes are actually persisted the passed commit hooks are run and may fail the
-     * commit by throwing a {@code CommitFailedException}. The commit hooks are run in the order as
-     * passed and <em>before</em> any other commit hook that might be present in this root.
+     * The message string (if given) is passed to the underlying storage
+     * as a part of the internal commit information attached to this commit.
+     * The commit information will be made available to local observers but
+     * will not be visible to observers on other cluster nodes.
      * <p>
-     * After a successful operation the root is automatically {@link #refresh() refreshed}, such
-     * that trees obtained through {@link #getTree(String)} may become non existing.
+     * After a successful operation the root is automatically
+     * {@link #refresh() refreshed}, such that trees previously obtained
+     * through {@link #getTree(String)} may become non existing.
      *
-     * @param hooks  commit hooks to run before any changes are persisted.
-     * @throws CommitFailedException
+     * @param message custom message to be associated with this commit
+     * @param hook commit hook to run before any changes are persisted
+     * @throws CommitFailedException if the commit failed
      */
-    void commit(CommitHook... hooks) throws CommitFailedException;
+    void commit(@Nullable String message, @Nullable CommitHook hook)
+            throws CommitFailedException;
+
+    /**
+     * Atomically persists all changes made to the tree attached to this root.
+     * Calling this method is equivalent to calling the
+     * {@link #commit(String, CommitHook)} method with no user data and an
+     * empty commit hook.
+     *
+     * @throws CommitFailedException if the commit failed
+     */
+    void commit() throws CommitFailedException;
+
 
     /**
      * Determine whether there are changes on this tree
@@ -150,4 +169,5 @@ public interface Root {
      */
     @Nonnull
     ContentSession getContentSession();
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/AbstractRoot.java Wed Oct 23 19:51:00 2013
@@ -19,6 +19,7 @@
 package org.apache.jackrabbit.oak.core;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Lists.newArrayList;
 import static org.apache.jackrabbit.oak.commons.PathUtils.getName;
 import static org.apache.jackrabbit.oak.commons.PathUtils.getParentPath;
 import static org.apache.jackrabbit.oak.commons.PathUtils.isAncestor;
@@ -30,9 +31,9 @@ import java.util.Collections;
 import java.util.List;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 import javax.security.auth.Subject;
 
-import com.google.common.collect.Lists;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.BlobFactory;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -153,7 +154,10 @@ public abstract class AbstractRoot imple
      * the session has been logged out already).
      */
     protected void checkLive() {
+    }
 
+    protected String getUserData() {
+        return null;
     }
 
     //---------------------------------------------------------------< Root >---
@@ -240,14 +244,20 @@ public abstract class AbstractRoot imple
     }
 
     @Override
-    public void commit(final CommitHook... hooks) throws CommitFailedException {
+    public void commit() throws CommitFailedException {
+        commit(null, null);
+    }
+
+    @Override
+    public void commit(@Nullable String message, @Nullable CommitHook hook)
+            throws CommitFailedException {
         checkLive();
         ContentSession session = getContentSession();
-        CommitInfo info = CommitInfo.create(
+        CommitInfo info = new CommitInfo(
                 session.toString(),
                 session.getAuthInfo().getUserID(),
-                System.currentTimeMillis());
-        base = store.merge(builder, getCommitHook(hooks), info);
+                message);
+        base = store.merge(builder, getCommitHook(hook), info);
         secureBuilder.baseChanged();
         modCount = 0;
         if (permissionProvider.hasValue()) {
@@ -256,33 +266,42 @@ public abstract class AbstractRoot imple
     }
 
     /**
-     * Combine the passed {@code hooks}, the globally defined commit hook(s) and the hooks and
-     * validators defined by the various security related configurations.
+     * Combine the passed {@code hook}, the globally defined commit hook(s)
+     * and the hooks and validators defined by the various security related
+     * configurations.
      *
+     * @param hook extra hook to be used for just this commit, or {@code null}
      * @return A commit hook combining repository global commit hook(s) with the pluggable hooks
      *         defined with the security modules and the padded {@code hooks}.
-     * @param hooks
      */
-    private CommitHook getCommitHook(CommitHook[] hooks) {
-        List<CommitHook> commitHooks = Lists.newArrayList(hooks);
-        commitHooks.add(hook);
+    private CommitHook getCommitHook(@Nullable CommitHook extraHook) {
+        List<CommitHook> hooks = newArrayList();
+
+        if (extraHook != null) {
+            hooks.add(extraHook);
+        }
+
+        hooks.add(hook);
+
         List<CommitHook> postValidationHooks = new ArrayList<CommitHook>();
         for (SecurityConfiguration sc : securityProvider.getConfigurations()) {
             for (CommitHook ch : sc.getCommitHooks(workspaceName)) {
                 if (ch instanceof PostValidationHook) {
                     postValidationHooks.add(ch);
                 } else if (ch != EmptyHook.INSTANCE) {
-                    commitHooks.add(ch);
+                    hooks.add(ch);
                 }
             }
+
             List<? extends ValidatorProvider> validators =
                     sc.getValidators(workspaceName, getCommitSubject());
             if (!validators.isEmpty()) {
-                commitHooks.add(new EditorHook(CompositeEditorProvider.compose(validators)));
+                hooks.add(new EditorHook(CompositeEditorProvider.compose(validators)));
             }
         }
-        commitHooks.addAll(postValidationHooks);
-        return CompositeHook.compose(commitHooks);
+        hooks.addAll(postValidationHooks);
+
+        return CompositeHook.compose(hooks);
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ImmutableRoot.java Wed Oct 23 19:51:00 2013
@@ -92,7 +92,12 @@ public final class ImmutableRoot impleme
     }
 
     @Override
-    public void commit(CommitHook... hooks) {
+    public void commit() {
+        commit(null, null);
+    }
+
+    @Override
+    public void commit(String message, CommitHook hooks) {
         throw new UnsupportedOperationException();
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStore.java Wed Oct 23 19:51:00 2013
@@ -27,12 +27,14 @@ import java.util.concurrent.locks.Reentr
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 import com.google.common.cache.Weigher;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
+
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -170,10 +172,11 @@ public class KernelNodeStore implements 
      * an {@code IllegalArgumentException}.
      */
     @Override
-    public NodeState merge(@Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
-            @Nonnull CommitInfo info) throws CommitFailedException {
+    public NodeState merge(
+            @Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
+            @Nullable CommitInfo info) throws CommitFailedException {
         checkArgument(builder instanceof KernelRootBuilder);
-        return ((KernelRootBuilder) builder).merge(checkNotNull(commitHook), checkNotNull(info));
+        return ((KernelRootBuilder) builder).merge(checkNotNull(commitHook), info);
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreBranch.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreBranch.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreBranch.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreBranch.java Wed Oct 23 19:51:00 2013
@@ -25,6 +25,7 @@ import java.io.IOException;
 import java.util.concurrent.locks.Lock;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
@@ -151,9 +152,9 @@ class KernelNodeStoreBranch implements N
 
     @Nonnull
     @Override
-    public NodeState merge(@Nonnull CommitHook hook, @Nonnull CommitInfo info)
+    public NodeState merge(@Nonnull CommitHook hook, @Nullable CommitInfo info)
             throws CommitFailedException {
-        return branchState.merge(checkNotNull(hook), checkNotNull(info));
+        return branchState.merge(checkNotNull(hook), info);
     }
 
     @Override
@@ -201,7 +202,7 @@ class KernelNodeStoreBranch implements N
         abstract void rebase();
 
         @Nonnull
-        abstract NodeState merge(@Nonnull CommitHook hook, @Nonnull CommitInfo info)
+        abstract NodeState merge(@Nonnull CommitHook hook, @Nullable CommitInfo info)
                 throws CommitFailedException;
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/NodeStoreKernel.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/NodeStoreKernel.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/NodeStoreKernel.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/kernel/NodeStoreKernel.java Wed Oct 23 19:51:00 2013
@@ -462,8 +462,7 @@ public class NodeStoreKernel implements 
             revision = new Revision(revision, builder.getNodeState(), message);
         } else {
             try {
-                NodeState newRoot = store.merge(
-                        builder, CONFLICT_HOOK, CommitInfo.EMPTY);
+                NodeState newRoot = store.merge(builder, CONFLICT_HOOK, null);
                 if (!newRoot.equals(head.root)) {
                     revision = new Revision(head, newRoot, message);
                     head = revision;
@@ -498,8 +497,8 @@ public class NodeStoreKernel implements 
         }
 
         try {
-            NodeState newRoot = store.merge(
-                    revision.branch, CONFLICT_HOOK, CommitInfo.EMPTY);
+            NodeState newRoot =
+                    store.merge(revision.branch, CONFLICT_HOOK, null);
             if (!newRoot.equals(head.root)) {
                 head = new Revision(head, newRoot, message);
                 revisions.put(head.id, head);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdate.java Wed Oct 23 19:51:00 2013
@@ -31,7 +31,6 @@ import org.apache.jackrabbit.oak.api.Com
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EditorDiff;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -118,7 +117,7 @@ public class AsyncIndexUpdate implements
                             throw CONCURRENT_UPDATE;
                         }
                     }
-                }, CommitInfo.EMPTY);
+                }, null);
             } catch (CommitFailedException e) {
                 if (e != CONCURRENT_UPDATE) {
                     exception = e;
@@ -143,7 +142,7 @@ public class AsyncIndexUpdate implements
         NodeBuilder builder = store.getRoot().builder();
         preAsyncRunStatus(builder);
         try {
-            store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+            store.merge(builder, EmptyHook.INSTANCE, null);
         } catch (CommitFailedException e) {
             log.warn("Index status update {} failed", name, e);
         }

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=1535136&r1=1535135&r2=1535136&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 Oct 23 19:51:00 2013
@@ -29,8 +29,10 @@ import java.util.concurrent.atomic.Atomi
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import com.google.common.io.ByteStreams;
+
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
@@ -81,11 +83,11 @@ public class MemoryNodeStore implements 
      *                                  this store
      */
     @Override
-    public synchronized NodeState merge(@Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
-            @Nonnull CommitInfo info) throws CommitFailedException {
+    public synchronized NodeState merge(
+            @Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
+            @Nullable CommitInfo info) throws CommitFailedException {
         checkArgument(builder instanceof MemoryNodeBuilder);
         checkNotNull(commitHook);
-        checkNotNull(info);
         rebase(builder);
         NodeStoreBranch branch = new MemoryNodeStoreBranch(this, getRoot());
         branch.setRoot(builder.getNodeState());
@@ -198,7 +200,8 @@ public class MemoryNodeStore implements 
         }
 
         @Override
-        public NodeState merge(@Nonnull CommitHook hook, @Nonnull CommitInfo info)
+        public NodeState merge(
+                @Nonnull CommitHook hook, @Nullable CommitInfo info)
                 throws CommitFailedException {
             // TODO: rebase();
             checkNotMerged();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueue.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueue.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueue.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueue.java Wed Oct 23 19:51:00 2013
@@ -65,7 +65,6 @@ class CommitQueue {
         if (isBranch) {
             removeCommit(c);
         } else {
-            checkArgument(info != null, "Trunk commit must have a CommitInfo");
             afterTrunkCommit(c, info);
         }
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/mongomk/MongoNodeStore.java Wed Oct 23 19:51:00 2013
@@ -376,7 +376,7 @@ public final class MongoNodeStore
 
     void done(@Nonnull Commit c, boolean isBranch) {
         try {
-            commitQueue.done(c, isBranch, CommitInfo.EMPTY);
+            commitQueue.done(c, isBranch, null);
         } finally {
             backgroundOperationLock.readLock().unlock();
         }
@@ -749,7 +749,7 @@ public final class MongoNodeStore
     @Override
     public NodeState merge(@Nonnull NodeBuilder builder,
                            @Nonnull CommitHook commitHook,
-                           @Nonnull CommitInfo info)
+                           @Nullable CommitInfo info)
             throws CommitFailedException {
         // TODO: implement
         return null;

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java Wed Oct 23 19:51:00 2013
@@ -32,6 +32,7 @@ import javax.annotation.Nonnull;
 import com.google.common.base.Objects;
 import com.google.common.collect.Queues;
 import com.google.common.collect.Sets;
+
 import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
@@ -110,19 +111,31 @@ public class ChangeDispatcher {
     }
 
     /**
-     * Call right after changes have been successfully persisted passing the new root
-     * node state resulting from the persist operation.
+     * Call right after changes have been successfully persisted passing
+     * the new root node state resulting from the persist operation.
      * <p>
      * The differences from the root node state passed to the last call to
-     * {@link #beforeCommit(NodeState)} to {@code root} are reported as cluster local
-     * changes to any listener.
-
-     * @param root  root node state just persisted
+     * {@link #beforeCommit(NodeState)} to {@code root} are reported as
+     * cluster local changes to any listener in case non-{@code null}
+     * commit information is provided. If no local commit information is
+     * given, then no local changes are reported and the committed changes
+     * will only show up as an aggregate with any concurrent external changes
+     * reported during the {@link #afterCommit(NodeState)} call.
+     *
+     * @param root root node state just persisted
+     * @param info commit information
      * @throws IllegalStateException  if not inside a local commit
      */
-    public synchronized void localCommit(@Nonnull NodeState root, @Nonnull CommitInfo info) {
+    public synchronized void localCommit(
+            @Nonnull NodeState root, @Nonnull CommitInfo info) {
         checkState(inLocalCommit());
-        internalChange(checkNotNull(root), checkNotNull(info));
+        checkNotNull(root);
+        if (info != null) {
+            add(new ChangeSet(previousRoot, root, info));
+        } else {
+            add(new ChangeSet(previousRoot, root));
+        }
+        previousRoot = root;
     }
 
     /**
@@ -156,16 +169,11 @@ public class ChangeDispatcher {
 
     private synchronized void externalChange(NodeState root) {
         if (!root.equals(previousRoot)) {
-            add(new ChangeSet(previousRoot, root, true, CommitInfo.EMPTY));
+            add(new ChangeSet(previousRoot, root));
             previousRoot = root;
         }
     }
 
-    private synchronized void internalChange(NodeState root, CommitInfo info) {
-        add(new ChangeSet(previousRoot, root, false, info));
-        previousRoot = root;
-    }
-
     private void register(Listener listener) {
         synchronized (listeners) {
             listeners.add(listener);
@@ -235,37 +243,39 @@ public class ChangeDispatcher {
     public static class ChangeSet {
         private final NodeState before;
         private final NodeState after;
-        private final boolean isExternal;
         private final CommitInfo commitInfo;
 
-        ChangeSet(@Nonnull NodeState before, @Nonnull NodeState after, boolean isExternal,
+        /**
+         * Creates an external change set
+         */
+        ChangeSet(@Nonnull NodeState before, @Nonnull NodeState after) {
+            this.before = checkNotNull(before);
+            this.after = checkNotNull(after);
+            this.commitInfo = null;
+        }
+
+        /**
+         * Creates a local change set
+         */
+        ChangeSet(@Nonnull NodeState before, @Nonnull NodeState after,
                 @Nonnull CommitInfo commitInfo) {
             this.before = checkNotNull(before);
             this.after = checkNotNull(after);
-            this.isExternal = isExternal;
             this.commitInfo = checkNotNull(commitInfo);
         }
 
         public boolean isExternal() {
-            return isExternal;
+            return commitInfo == null;
         }
 
         public boolean isLocal(String sessionId) {
-            return !isExternal && Objects.equal(getSessionId(), sessionId);
+            return commitInfo != null
+                    && Objects.equal(commitInfo.getSessionId(), sessionId);
         }
 
-        @Nonnull
-        public String getSessionId() {
-            return commitInfo.getSessionId();
-        }
-
-        @Nonnull
-        public String getUserId() {
-            return commitInfo.getUserId();
-        }
-
-        public long getDate() {
-            return commitInfo.getDate();
+        @CheckForNull
+        public CommitInfo getCommitInfo() {
+            return commitInfo;
         }
 
         /**
@@ -291,33 +301,10 @@ public class ChangeDispatcher {
             return toStringHelper(this)
                 .add("base", before)
                 .add("head", after)
-                .add("external", isExternal)
                 .add("commit info", commitInfo)
                 .toString();
         }
 
-        @Override
-        public boolean equals(Object other) {
-            if (this == other) {
-                return true;
-            }
-            if (other == null || other.getClass() != this.getClass()) {
-                return false;
-            }
-
-            ChangeSet that = (ChangeSet) other;
-            return isExternal == that.isExternal
-                    && commitInfo.equals(that.commitInfo)
-                    && before.equals(that.before)
-                    && after.equals(that.after);
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = before.hashCode();
-            hash = 31 * hash + after.hashCode();
-            hash = 31 * hash + (isExternal ? 1 : 0);
-            return 31 * hash + commitInfo.hashCode();
-        }
     }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeProcessor.java Wed Oct 23 19:51:00 2013
@@ -23,6 +23,7 @@ import static com.google.common.base.Pre
 import static com.google.common.collect.Iterators.emptyIterator;
 import static com.google.common.collect.Iterators.singletonIterator;
 import static com.google.common.collect.Iterators.transform;
+import static com.google.common.collect.Lists.newArrayList;
 import static javax.jcr.observation.Event.NODE_ADDED;
 import static javax.jcr.observation.Event.NODE_REMOVED;
 import static javax.jcr.observation.Event.PROPERTY_ADDED;
@@ -40,7 +41,7 @@ import javax.jcr.observation.EventListen
 
 import com.google.common.base.Function;
 import com.google.common.collect.Iterators;
-import com.google.common.collect.Lists;
+
 import org.apache.jackrabbit.api.jmx.EventListenerMBean;
 import org.apache.jackrabbit.commons.iterator.EventIteratorAdapter;
 import org.apache.jackrabbit.commons.observation.ListenerTracker;
@@ -53,6 +54,7 @@ import org.apache.jackrabbit.oak.core.Im
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher.ChangeSet;
 import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher.Listener;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 import org.apache.jackrabbit.oak.spi.state.RecursingNodeStateDiff;
 import org.apache.jackrabbit.oak.spi.state.VisibleDiff;
@@ -195,7 +197,8 @@ public class ChangeProcessor implements 
                     String path = namePathMapper.getOakPath(filter.getPath());
                     ImmutableTree beforeTree = getTree(changes.getBeforeState(), path);
                     ImmutableTree afterTree = getTree(changes.getAfterState(), path);
-                    EventGeneratingNodeStateDiff diff = new EventGeneratingNodeStateDiff(changes, beforeTree, afterTree);
+                    EventGeneratingNodeStateDiff diff = new EventGeneratingNodeStateDiff(
+                            changes.getCommitInfo(), beforeTree, afterTree);
                     SecureNodeStateDiff.compare(VisibleDiff.wrap(diff), beforeTree, afterTree);
                     if (!stopping) {
                         diff.sendEvents();
@@ -223,22 +226,46 @@ public class ChangeProcessor implements 
     private class EventGeneratingNodeStateDiff extends RecursingNodeStateDiff {
         public static final int EVENT_LIMIT = 8192;
 
-        private final ChangeSet changes;
+        private final String userId;
+        private final String message;
+        private final long timestamp;
+        private final boolean external;
+
         private final Tree beforeTree;
         private final Tree afterTree;
 
         private List<Iterator<Event>> events;
         private int eventCount;
 
-        EventGeneratingNodeStateDiff(ChangeSet changes, Tree beforeTree, Tree afterTree, List<Iterator<Event>> events) {
-            this.changes = changes;
+        EventGeneratingNodeStateDiff(
+                CommitInfo info, Tree beforeTree, Tree afterTree) {
+            if (info != null) {
+                this.userId = info.getUserId();
+                this.message = info.getMessage();
+                this.timestamp = info.getDate();
+                this.external = false;
+            } else {
+                this.userId = CommitInfo.OAK_UNKNOWN;
+                this.message = null;
+                // we can't tell exactly when external changes were committed,
+                // so we just use a rough estimate like this
+                this.timestamp = System.currentTimeMillis();
+                this.external = true;
+            }
             this.beforeTree = beforeTree;
             this.afterTree = afterTree;
-            this.events = events;
+            this.events = newArrayList();
         }
 
-        public EventGeneratingNodeStateDiff(ChangeSet changes, Tree beforeTree, Tree afterTree) {
-            this(changes, beforeTree, afterTree, Lists.<Iterator<Event>>newArrayList());
+        private EventGeneratingNodeStateDiff(
+                EventGeneratingNodeStateDiff parent, String name) {
+            this.userId = parent.userId;
+            this.message = parent.message;
+            this.timestamp = parent.timestamp;
+            this.external = parent.external;
+            this.beforeTree = parent.beforeTree.getChild(name);
+            this.afterTree = parent.afterTree.getChild(name);
+            this.events = parent.events;
         }
 
         public void sendEvents() {
@@ -318,8 +345,8 @@ public class ChangeProcessor implements 
         @Override
         public RecursingNodeStateDiff createChildDiff(String name, NodeState before, NodeState after) {
             if (filterRef.get().includeChildren(afterTree.getPath())) {
-                EventGeneratingNodeStateDiff diff = new EventGeneratingNodeStateDiff(
-                        changes, beforeTree.getChild(name), afterTree.getChild(name), events);
+                EventGeneratingNodeStateDiff diff =
+                        new EventGeneratingNodeStateDiff(this, name);
                 return VisibleDiff.wrap(diff);
             } else {
                 return RecursingNodeStateDiff.EMPTY;
@@ -327,11 +354,9 @@ public class ChangeProcessor implements 
         }
 
         private EventImpl createEvent(int eventType, String path, String id) {
-            // TODO support info
             return new EventImpl(
-                    eventType, namePathMapper.getJcrPath(path), changes.getUserId(),
-                    id, null, changes.getDate(), userDataRef.get(),
-                    changes.isExternal());
+                    eventType, namePathMapper.getJcrPath(path), userId, id,
+                    null /* TODO: info map */, timestamp, message, external);
         }
 
         private Event generatePropertyEvent(int eventType, Tree parent, PropertyState property) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStore.java Wed Oct 23 19:51:00 2013
@@ -26,6 +26,7 @@ import java.io.InputStream;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -111,11 +112,10 @@ public class SegmentNodeStore implements
     public synchronized NodeState merge(
             @Nonnull NodeBuilder builder,
             @Nonnull CommitHook commitHook,
-            @Nonnull CommitInfo info)
+            @Nullable CommitInfo info)
             throws CommitFailedException {
         checkArgument(builder instanceof SegmentNodeBuilder);
         checkNotNull(commitHook);
-        checkNotNull(info);
         SegmentNodeState head = getHead();
         rebase(builder, head.getChildNode(ROOT)); // TODO: can we avoid this?
         SegmentNodeStoreBranch branch = new SegmentNodeStoreBranch(

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreBranch.java Wed Oct 23 19:51:00 2013
@@ -25,6 +25,7 @@ import java.util.Random;
 import java.util.UUID;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.commons.PathUtils;
@@ -182,10 +183,10 @@ class SegmentNodeStoreBranch implements 
     }
 
     @Override @Nonnull
-    public synchronized NodeState merge(@Nonnull CommitHook hook, @Nonnull CommitInfo info)
+    public synchronized NodeState merge(
+            @Nonnull CommitHook hook, @Nullable CommitInfo info)
             throws CommitFailedException {
         checkNotNull(hook);
-        checkNotNull(info);
         if (base != head) {
             try {
                 long timeout = optimisticMerge(hook, info);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentNodeStoreService.java Wed Oct 23 19:51:00 2013
@@ -23,9 +23,11 @@ import java.util.Dictionary;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import com.google.common.base.Preconditions;
 import com.mongodb.Mongo;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.ConfigurationPolicy;
@@ -166,8 +168,9 @@ public class SegmentNodeStoreService imp
 
     @Nonnull
     @Override
-    public NodeState merge(@Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
-            @Nonnull CommitInfo info) throws CommitFailedException {
+    public NodeState merge(
+            @Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
+            @Nullable CommitInfo info) throws CommitFailedException {
         return getDelegate().merge(builder, commitHook, info);
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitInfo.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitInfo.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitInfo.java Wed Oct 23 19:51:00 2013
@@ -20,40 +20,44 @@
 package org.apache.jackrabbit.oak.spi.commit;
 
 import static com.google.common.base.Objects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
 
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 /**
  * Commit info instances associate some meta data with a commit.
  */
 public class CommitInfo {
+
     public static final String OAK_UNKNOWN = "oak:unknown";
-    public static final CommitInfo EMPTY = new CommitInfo(OAK_UNKNOWN, OAK_UNKNOWN, 0);
 
     private final String sessionId;
+
     private final String userId;
-    private final long date;
+
+    private final String message;
+
+    private final long date = System.currentTimeMillis();
 
     /**
-     * Factory method for creating a new {@code CommitInfo} instance.
-     * Both string arguments default to {@link #OAK_UNKNOWN} if {@code null}.
+     * Creates a commit info for the given session and user.
      *
-     * @param sessionId  id of the committing session
-     * @param userId  id of the committing user
-     * @param date  time stamp
-     * @return  a fresh {@code CommitInfo} instance
+     * @param sessionId session identifier
+     * @param userId user identifier, or {@code null} for an unknown user
+     * @param message message attached to this commit, or {@code null}
      */
-    public static CommitInfo create(String sessionId, String userId, long date) {
-        return new CommitInfo(
-                sessionId == null ? OAK_UNKNOWN : sessionId,
-                userId == null ? OAK_UNKNOWN : userId,
-                date);
-    }
-
-    private CommitInfo(@Nonnull String sessionId, @Nonnull String userId, long date) {
-        this.sessionId = sessionId;
-        this.userId = userId;
-        this.date = date;
+    public CommitInfo(
+            @Nonnull String sessionId, @Nullable String userId,
+            @Nullable String message) {
+        this.sessionId = checkNotNull(sessionId);
+        if (userId != null) {
+            this.userId = userId;
+        } else {
+            this.userId = OAK_UNKNOWN;
+        }
+        this.message = message;
     }
 
     /**
@@ -73,6 +77,14 @@ public class CommitInfo {
     }
 
     /**
+     * @return message attached to this commit
+     */
+    @CheckForNull
+    public String getMessage() {
+        return message;
+    }
+
+    /**
      * @return  time stamp
      */
     public long getDate() {
@@ -84,29 +96,9 @@ public class CommitInfo {
         return toStringHelper(this)
                 .add("sessionId", sessionId)
                 .add("userId", userId)
+                .add("userData", message)
                 .add("date", date)
                 .toString();
     }
 
-    @Override
-    public boolean equals(Object other) {
-        if (this == other) {
-            return true;
-        }
-        if (other == null || other.getClass() != this.getClass()) {
-            return false;
-        }
-
-        CommitInfo that = (CommitInfo) other;
-        return date == that.date
-                && sessionId.equals(that.sessionId)
-                && userId.equals(that.userId);
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = sessionId.hashCode();
-        hash = 31 * hash + userId.hashCode();
-        return 31 * hash + (int) (date ^ (date >>> 32));
-    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/OakInitializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/OakInitializer.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/OakInitializer.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/OakInitializer.java Wed Oct 23 19:51:00 2013
@@ -24,7 +24,6 @@ import org.apache.jackrabbit.oak.api.Com
 import org.apache.jackrabbit.oak.plugins.index.IndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.IndexUpdateProvider;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
 import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -41,9 +40,8 @@ public final class OakInitializer {
         try {
             NodeBuilder builder = store.getRoot().builder();
             initializer.initialize(builder);
-            store.merge(
-                    builder,
-                    new EditorHook(new IndexUpdateProvider(indexEditor)), CommitInfo.EMPTY);
+            CommitHook hook = new EditorHook(new IndexUpdateProvider(indexEditor));
+            store.merge(builder, hook, null);
         } catch (CommitFailedException e) {
             throw new RuntimeException(e);
         }
@@ -60,9 +58,8 @@ public final class OakInitializer {
             wspInit.initialize(builder, workspaceName, indexProvider, commitHook);
         }
         try {
-            store.merge(
-                    builder,
-                    new EditorHook(new IndexUpdateProvider(indexEditor)), CommitInfo.EMPTY);
+            CommitHook hook = new EditorHook(new IndexUpdateProvider(indexEditor));
+            store.merge(builder, hook, null);
         } catch (CommitFailedException e) {
             throw new RuntimeException(e);
         }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStore.java Wed Oct 23 19:51:00 2013
@@ -21,6 +21,7 @@ import java.io.InputStream;
 
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -51,15 +52,17 @@ public interface NodeStore {
      *
      * @param builder  the builder whose changes to apply
      * @param commitHook the commit hook to apply while merging changes
-     * @param info commit info associated with this merge operation
+     * @param info commit info associated with this merge operation,
+     *             or {@code null} if no local commit information is available
      * @return the node state resulting from the merge.
      * @throws CommitFailedException if the merge failed
      * @throws IllegalArgumentException if the builder is not acquired
      *                                  from a root state of this store
      */
     @Nonnull
-    NodeState merge(@Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
-            @Nonnull CommitInfo info) throws CommitFailedException;
+    NodeState merge(
+            @Nonnull NodeBuilder builder, @Nonnull CommitHook commitHook,
+            @Nullable CommitInfo info) throws CommitFailedException;
 
     /**
      * Rebase the changes in the passed {@code builder} on top of the current root state.

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStoreBranch.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStoreBranch.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStoreBranch.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/state/NodeStoreBranch.java Wed Oct 23 19:51:00 2013
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.oak.spi.state;
 
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
 
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
@@ -86,13 +87,15 @@ public interface NodeStoreBranch {
      * the current head revision followed by a fast forward merge.
      *
      * @param hook the commit hook to apply while merging changes
-     * @param info commit info associated with this merge operation
+     * @param info commit info associated with this merge operation,
+     *             or {@code null} if no local commit information is available
      * @return the node state resulting from the merge.
      * @throws CommitFailedException if the merge failed
      * @throws IllegalStateException if the branch is already merged
      */
     @Nonnull
-    NodeState merge(@Nonnull CommitHook hook, @Nonnull CommitInfo info) throws CommitFailedException;
+    NodeState merge(@Nonnull CommitHook hook, @Nullable CommitInfo info)
+            throws CommitFailedException;
 
     /**
      * Rebase the changes from this branch on top of the current

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeBuilderTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeBuilderTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeBuilderTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeBuilderTest.java Wed Oct 23 19:51:00 2013
@@ -50,7 +50,7 @@ public class KernelNodeBuilderTest {
     private static void init(NodeStore store) throws CommitFailedException {
         NodeBuilder builder = store.getRoot().builder();
         builder.child("x").child("y").child("z");
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
     private static void run(NodeStore store) throws CommitFailedException {
@@ -72,7 +72,7 @@ public class KernelNodeBuilderTest {
         assertFalse("child node x/y/z not should not be present", builder
                 .child("x").child("y").hasChildNode("z"));
 
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStateTest.java Wed Oct 23 19:51:00 2013
@@ -32,7 +32,6 @@ import java.util.List;
 import org.apache.jackrabbit.mk.core.MicroKernelImpl;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -58,8 +57,8 @@ public class KernelNodeStateTest {
         builder.child("y");
         builder.child("z");
 
-        state = store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
-        state = store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        state = store.merge(builder, EmptyHook.INSTANCE, null);
+        state = store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
     @After

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreCacheTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreCacheTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreCacheTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/KernelNodeStoreCacheTest.java Wed Oct 23 19:51:00 2013
@@ -28,7 +28,6 @@ import javax.annotation.Nonnull;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
 import org.apache.jackrabbit.mk.core.MicroKernelImpl;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -61,7 +60,7 @@ public class KernelNodeStoreCacheTest {
         b.child("c");
         b.child("d");
         b.child("e");
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
     /**
@@ -138,7 +137,7 @@ public class KernelNodeStoreCacheTest {
     private void modifyContent() throws Exception {
         NodeBuilder builder = store.getRoot().builder();
         builder.child("a").setProperty("foo", "bar");
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
     private void readTree(NodeState root) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/LargeKernelNodeStateTest.java Wed Oct 23 19:51:00 2013
@@ -24,7 +24,6 @@ import static junit.framework.Assert.ass
 
 import org.apache.jackrabbit.mk.core.MicroKernelImpl;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -50,7 +49,7 @@ public class LargeKernelNodeStateTest {
             builder.child("x" + i);
         }
 
-        state = store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        state = store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
     @After

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/NodeStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/NodeStoreTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/NodeStoreTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/NodeStoreTest.java Wed Oct 23 19:51:00 2013
@@ -36,7 +36,6 @@ import org.apache.jackrabbit.oak.api.Com
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.plugins.memory.MultiStringPropertyState;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.commit.Observer;
 import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
@@ -83,8 +82,8 @@ public class NodeStoreTest {
         test.child("x");
         test.child("y");
         test.child("z");
-        root = store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
-        root = store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        root = store.merge(builder, EmptyHook.INSTANCE, null);
+        root = store.merge(builder, EmptyHook.INSTANCE, null);
     }
 
     @After
@@ -127,7 +126,7 @@ public class NodeStoreTest {
         assertFalse(testState.getChildNode("newNode").exists());
         assertTrue(testState.getChildNode("x").exists());
 
-        store.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(rootBuilder, EmptyHook.INSTANCE, null);
 
         // Assert changes are present in the trunk
         testState = store.getRoot().getChildNode("test");
@@ -158,7 +157,7 @@ public class NodeStoreTest {
 
         testBuilder.getChildNode("a").remove();
 
-        store.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(rootBuilder, EmptyHook.INSTANCE, null);
         NodeState newRoot = store.getRoot(); // triggers the observer
 
         NodeState before = states[0];
@@ -192,7 +191,7 @@ public class NodeStoreTest {
                 testBuilder.child("fromHook");
                 return rootBuilder.getNodeState();
             }
-        }, CommitInfo.EMPTY);
+        }, null);
 
         NodeState test = store.getRoot().getChildNode("test");
         assertTrue(test.getChildNode("newNode").exists());
@@ -209,13 +208,13 @@ public class NodeStoreTest {
         for (int i = 0; i <= KernelNodeState.MAX_CHILD_NODE_NAMES; i++) {
             parent.child("child-" + i);
         }
-        store.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(root, EmptyHook.INSTANCE, null);
 
         NodeState base = store.getRoot();
         root = base.builder();
         parent = root.child("parent");
         parent.child("child-new");
-        store.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(root, EmptyHook.INSTANCE, null);
 
         Diff diff = new Diff();
         store.getRoot().compareAgainstBaseState(base, diff);
@@ -228,7 +227,7 @@ public class NodeStoreTest {
         root = base.builder();
         parent = root.getChildNode("parent");
         parent.getChildNode("child-new").moveTo(parent, "child-moved");
-        store.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(root, EmptyHook.INSTANCE, null);
 
         diff = new Diff();
         store.getRoot().compareAgainstBaseState(base, diff);
@@ -244,7 +243,7 @@ public class NodeStoreTest {
         parent.child("child-moved").setProperty("foo", "value");
         parent.child("child-moved").setProperty(
                 new MultiStringPropertyState("bar", Arrays.asList("value")));
-        store.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(root, EmptyHook.INSTANCE, null);
 
         diff = new Diff();
         store.getRoot().compareAgainstBaseState(base, diff);
@@ -261,7 +260,7 @@ public class NodeStoreTest {
         parent.setProperty("foo", "value");
         parent.setProperty(new MultiStringPropertyState(
                 "bar", Arrays.asList("value")));
-        store.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(root, EmptyHook.INSTANCE, null);
 
         diff = new Diff();
         store.getRoot().compareAgainstBaseState(base, diff);
@@ -276,7 +275,7 @@ public class NodeStoreTest {
         root = base.builder();
         parent = root.child("parent");
         parent.getChildNode("child-moved").remove();
-        store.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(root, EmptyHook.INSTANCE, null);
 
         diff = new Diff();
         store.getRoot().compareAgainstBaseState(base, diff);
@@ -309,7 +308,7 @@ public class NodeStoreTest {
     private static NodeStore init(NodeStore store) throws CommitFailedException {
         NodeBuilder builder = store.getRoot().builder();
         builder.setChildNode("root");
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
         return store;
     }
 
@@ -323,11 +322,11 @@ public class NodeStoreTest {
         builder1.setChildNode("node1");
         builder2.setChildNode("node2");
 
-        store.merge(builder1, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder1, EmptyHook.INSTANCE, null);
         assertTrue(store.getRoot().hasChildNode("node1"));
         assertFalse(store.getRoot().hasChildNode("node2"));
 
-        store.merge(builder2, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder2, EmptyHook.INSTANCE, null);
         assertTrue(store.getRoot().hasChildNode("node1"));
         assertTrue(store.getRoot().hasChildNode("node2"));
     }
@@ -355,7 +354,7 @@ public class NodeStoreTest {
         }
 
         builder.child("foo").child(":bar").child("quz").setProperty("p", "v");
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
 
         NodeState after = store.getRoot();
         Diff diff = new Diff();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java Wed Oct 23 19:51:00 2013
@@ -30,7 +30,6 @@ import com.google.common.collect.Sets;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexLookup;
 import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.query.PropertyValues;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -78,7 +77,7 @@ public class AsyncIndexUpdateTest {
         builder.child("testRoot").setProperty("foo", "abc");
 
         // merge it back in
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
 
         AsyncIndexUpdate async = new AsyncIndexUpdate("async", store, provider);
         async.run();
@@ -119,7 +118,7 @@ public class AsyncIndexUpdateTest {
         builder.child("testSecond").setProperty("bar", "ghi");
 
         // merge it back in
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
 
         AsyncIndexUpdate async = new AsyncIndexUpdate("async", store, provider);
         async.run();
@@ -171,7 +170,7 @@ public class AsyncIndexUpdateTest {
                 .setProperty("foo", "xyz");
 
         // merge it back in
-        store.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(builder, EmptyHook.INSTANCE, null);
 
         AsyncIndexUpdate async = new AsyncIndexUpdate("async", store, provider);
         async.run();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/nodetype/NodeTypeIndexTest.java Wed Oct 23 19:51:00 2013
@@ -40,7 +40,6 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
 import org.apache.jackrabbit.oak.query.ast.SelectorImpl;
 import org.apache.jackrabbit.oak.query.index.FilterImpl;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
 import org.apache.jackrabbit.oak.spi.lifecycle.OakInitializer;
 import org.apache.jackrabbit.oak.spi.query.Cursor;
@@ -79,7 +78,7 @@ public class NodeTypeIndexTest {
         addFile(root, "file-1");
 
         store.merge(root, new EditorHook(new IndexUpdateProvider(
-                new PropertyIndexEditorProvider())), CommitInfo.EMPTY);
+                new PropertyIndexEditorProvider())), null);
 
         NodeState rootState = store.getRoot();
         NodeTypeIndex index = new NodeTypeIndex();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueueTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueueTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueueTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/mongomk/CommitQueueTest.java Wed Oct 23 19:51:00 2013
@@ -23,7 +23,6 @@ import java.util.Random;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.jackrabbit.oak.plugins.observation.ChangeDispatcher;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.junit.Test;
 
 /**
@@ -99,8 +98,7 @@ public class CommitQueueTest {
                                 queue.canceled(c);
                             } else {
                                 boolean isBranch = random.nextInt(5) == 0;
-                                queue.done(c, isBranch, CommitInfo.create(
-                                        null, null, System.currentTimeMillis()));
+                                queue.done(c, isBranch, null);
                             }
                         }
                     } catch (Exception e) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/JournalTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/JournalTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/JournalTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/JournalTest.java Wed Oct 23 19:51:00 2013
@@ -21,7 +21,6 @@ import static org.junit.Assert.assertEqu
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryStore;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -47,7 +46,7 @@ public class JournalTest {
         builder.setProperty("foo", "bar");
         NodeState newState = builder.getNodeState();
 
-        root.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        root.merge(builder, EmptyHook.INSTANCE, null);
 
         assertEquals(newState, root.getRoot());
         assertEquals(oldState, left.getRoot());
@@ -74,7 +73,7 @@ public class JournalTest {
         builder.setProperty("foo", "bar");
         NodeState newState = builder.getNodeState();
 
-        left.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        left.merge(builder, EmptyHook.INSTANCE, null);
 
         assertEquals(oldState, root.getRoot());
         assertEquals(newState, left.getRoot());
@@ -101,7 +100,7 @@ public class JournalTest {
         leftBuilder.setProperty("foo", "bar");
         NodeState leftState = leftBuilder.getNodeState();
 
-        left.merge(leftBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        left.merge(leftBuilder, EmptyHook.INSTANCE, null);
 
         assertEquals(oldState, root.getRoot());
         assertEquals(leftState, left.getRoot());
@@ -115,7 +114,7 @@ public class JournalTest {
         NodeBuilder rightBuilder = oldState.builder();
         rightBuilder.setProperty("bar", "foo");
 
-        right.merge(rightBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        right.merge(rightBuilder, EmptyHook.INSTANCE, null);
 
         store.getJournal("right").merge();
         NodeState newState = root.getRoot();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/MergeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/MergeTest.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/MergeTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/MergeTest.java Wed Oct 23 19:51:00 2013
@@ -28,7 +28,6 @@ import javax.annotation.Nonnull;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryStore;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.commit.EmptyHook;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -46,14 +45,14 @@ public class MergeTest {
 
         NodeBuilder a = store.getRoot().builder();
         a.setProperty("foo", "abc");
-        store.merge(a, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(a, EmptyHook.INSTANCE, null);
 
         assertTrue(store.getRoot().hasProperty("foo"));
         assertFalse(store.getRoot().hasProperty("bar"));
 
         NodeBuilder b = store.getRoot().builder();
         b.setProperty("bar", "xyz");
-        store.merge(b, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(b, EmptyHook.INSTANCE, null);
 
         assertTrue(store.getRoot().hasProperty("foo"));
         assertTrue(store.getRoot().hasProperty("bar"));
@@ -72,12 +71,12 @@ public class MergeTest {
         assertFalse(store.getRoot().hasProperty("foo"));
         assertFalse(store.getRoot().hasProperty("bar"));
 
-        store.merge(a, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(a, EmptyHook.INSTANCE, null);
 
         assertTrue(store.getRoot().hasProperty("foo"));
         assertFalse(store.getRoot().hasProperty("bar"));
 
-        store.merge(b, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+        store.merge(b, EmptyHook.INSTANCE, null);
 
         assertTrue(store.getRoot().hasProperty("foo"));
         assertTrue(store.getRoot().hasProperty("bar"));
@@ -96,7 +95,7 @@ public class MergeTest {
                     try {
                         NodeBuilder a = store.getRoot().builder();
                         a.setProperty("foo", "abc" + i);
-                        store.merge(a, EmptyHook.INSTANCE, CommitInfo.EMPTY);
+                        store.merge(a, EmptyHook.INSTANCE, null);
                         semaphore.release();
                     } catch (CommitFailedException e) {
                         fail();
@@ -125,7 +124,7 @@ public class MergeTest {
                 }
                 return after;
             }
-        }, CommitInfo.EMPTY);
+        }, null);
 
         assertTrue(store.getRoot().hasProperty("foo"));
         assertTrue(store.getRoot().hasProperty("bar"));

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java Wed Oct 23 19:51:00 2013
@@ -781,7 +781,7 @@ public class NodeDelegate extends ItemDe
             }
             tree.setProperty(JCR_LOCKISDEEP, isDeep);
             tree.setProperty(JCR_LOCKOWNER, owner);
-            root.commit();
+            sessionDelegate.commit(root);
         } catch (CommitFailedException e) {
             if (e.isAccessViolation()) {
                 throw new AccessControlException(
@@ -809,7 +809,7 @@ public class NodeDelegate extends ItemDe
         try {
             tree.removeProperty(JCR_LOCKISDEEP);
             tree.removeProperty(JCR_LOCKOWNER);
-            root.commit();
+            sessionDelegate.commit(root);
         } catch (CommitFailedException e) {
             if (e.isAccessViolation()) {
                 throw new AccessControlException(

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/SessionDelegate.java Wed Oct 23 19:51:00 2013
@@ -43,6 +43,7 @@ import org.apache.jackrabbit.oak.jcr.sec
 import org.apache.jackrabbit.oak.jcr.session.RefreshStrategy;
 import org.apache.jackrabbit.oak.jcr.session.operation.SessionOperation;
 import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
+import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.Editor;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
 import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
@@ -74,6 +75,8 @@ public class SessionDelegate {
     private int sessionOpCount;
     private long updateCount = 0;
 
+    private String userData = null;
+
     /**
      * Create a new session delegate for a {@code ContentSession}. The refresh behaviour of the
      * session is governed by the value of the {@code refreshInterval} argument: if the session
@@ -190,6 +193,37 @@ public class SessionDelegate {
         return updateCount;
     }
 
+    public void setUserData(String userData) {
+        this.userData = userData;
+    }
+
+    /**
+     * Commits the changes currently in the transient space.
+     * TODO: Consolidate with save().
+     *
+     * @throws CommitFailedException if the commit failed
+     */
+    public void commit() throws CommitFailedException {
+        commit(root);
+    }
+
+    /**
+     * Commits the changes applied to the given root. The user data (if any)
+     * currently attached to this session is passed as the commit message.
+     * Used both for normal save() calls and for the various
+     * direct-to-workspace operations.
+     *
+     * @throws CommitFailedException if the commit failed
+     */
+    public void commit(Root root) throws CommitFailedException {
+        commit(root, null);
+    }
+
+    private void commit(Root root, CommitHook hook)
+            throws CommitFailedException {
+        root.commit(userData, hook);
+    }
+
     public void checkProtectedNode(String path) throws RepositoryException {
         NodeDelegate node = getNode(path);
         if (node == null) {
@@ -295,7 +329,7 @@ public class SessionDelegate {
 
     public void save() throws RepositoryException {
         try {
-            root.commit();
+            commit();
         } catch (CommitFailedException e) {
             throw newRepositoryException(e);
         }
@@ -316,7 +350,7 @@ public class SessionDelegate {
             save();
         } else {
             try {
-                root.commit(new EditorHook(new EditorProvider() {
+                root.commit(null, new EditorHook(new EditorProvider() {
                     @Override
                     public Editor getRootEditor(NodeState before, NodeState after, NodeBuilder builder) {
                         return new ItemSaveValidator(path);
@@ -381,7 +415,7 @@ public class SessionDelegate {
                 throw new RepositoryException("Cannot move node at " + srcPath + " to " + destPath);
             }
             if (!transientOp) {
-                moveRoot.commit();
+                commit(moveRoot);
                 refresh(true);
             }
         } catch (CommitFailedException e) {
@@ -482,4 +516,5 @@ public class SessionDelegate {
             return new ItemSaveValidator(validator, path);
         }
     }
+
 }

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/VersionManagerDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/VersionManagerDelegate.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/VersionManagerDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/VersionManagerDelegate.java Wed Oct 23 19:51:00 2013
@@ -57,14 +57,7 @@ public class VersionManagerDelegate {
 
     private VersionManagerDelegate(SessionDelegate sessionDelegate) {
         this.sessionDelegate = sessionDelegate;
-        this.versionManager = new ReadWriteVersionManager(
-                new VersionStorage(sessionDelegate.getRoot()),
-                sessionDelegate.getRoot()) {
-            @Override
-            protected void refresh() {
-                VersionManagerDelegate.this.sessionDelegate.refresh(true);
-            }
-        };
+        this.versionManager = new ReadWriteVersionManager(sessionDelegate);
     }
 
     @Nonnull

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/WorkspaceDelegate.java Wed Oct 23 19:51:00 2013
@@ -85,7 +85,7 @@ public class WorkspaceDelegate {
 
         try {
             new WorkspaceCopy(root, srcPath, destPath).perform();
-            root.commit();
+            context.getSessionDelegate().commit(root);
             sessionDelegate.refresh(true);
         } catch (CommitFailedException e) {
             throw e.asRepositoryException();

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java Wed Oct 23 19:51:00 2013
@@ -147,10 +147,8 @@ public class ObservationManagerImpl impl
     }
 
     @Override
-    public void setUserData(String userData) throws RepositoryException {
-        for (ChangeProcessor processor : processors.values()) {
-            processor.setUserData(userData);
-        }
+    public void setUserData(@Nullable String userData) {
+        sessionDelegate.setUserData(userData);
     }
 
     @Override

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/ReadWriteVersionManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/ReadWriteVersionManager.java?rev=1535136&r1=1535135&r2=1535136&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/ReadWriteVersionManager.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/ReadWriteVersionManager.java Wed Oct 23 19:51:00 2013
@@ -30,12 +30,11 @@ import org.apache.jackrabbit.oak.api.Roo
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
 import org.apache.jackrabbit.oak.plugins.version.ReadOnlyVersionManager;
 import org.apache.jackrabbit.oak.util.TreeUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
@@ -50,14 +49,13 @@ import static org.apache.jackrabbit.oak.
  */
 public class ReadWriteVersionManager extends ReadOnlyVersionManager {
 
-    private static final Logger log = LoggerFactory.getLogger(ReadWriteVersionManager.class);
+    private final SessionDelegate sessionDelegate;
+
     private final VersionStorage versionStorage;
-    private final Root workspaceRoot;
 
-    public ReadWriteVersionManager(@Nonnull VersionStorage versionStorage,
-                                   @Nonnull Root workspaceRoot) {
-        this.versionStorage = checkNotNull(versionStorage);
-        this.workspaceRoot = checkNotNull(workspaceRoot);
+    public ReadWriteVersionManager(@Nonnull SessionDelegate sessionDelegate) {
+        this.sessionDelegate = sessionDelegate;
+        this.versionStorage = new VersionStorage(sessionDelegate.getRoot());
     }
 
     /**
@@ -69,7 +67,7 @@ public class ReadWriteVersionManager ext
      * @throws RepositoryException if the session could not be refreshed
      */
     protected void refresh() throws RepositoryException {
-        // do nothing
+        sessionDelegate.refresh(true);
     }
 
     @Override
@@ -81,14 +79,14 @@ public class ReadWriteVersionManager ext
     @Override
     @Nonnull
     protected Root getWorkspaceRoot() {
-        return workspaceRoot;
+        return sessionDelegate.getRoot();
     }
 
     @Override
     @Nonnull
     protected ReadOnlyNodeTypeManager getNodeTypeManager() {
         return ReadOnlyNodeTypeManager.getInstance(
-                workspaceRoot, NamePathMapper.DEFAULT);
+                sessionDelegate.getRoot(), NamePathMapper.DEFAULT);
     }
 
     /**
@@ -109,7 +107,7 @@ public class ReadWriteVersionManager ext
     public Tree checkin(@Nonnull Tree versionable)
             throws RepositoryException, InvalidItemStateException,
             UnsupportedRepositoryOperationException {
-        if (workspaceRoot.hasPendingChanges()) {
+        if (sessionDelegate.hasPendingChanges()) {
             throw new InvalidItemStateException("Unable to perform checkin. " +
                     "Session has pending changes.");
         }
@@ -121,10 +119,10 @@ public class ReadWriteVersionManager ext
             versionable.setProperty(JCR_ISCHECKEDOUT,
                     Boolean.FALSE, Type.BOOLEAN);
             try {
-                getWorkspaceRoot().commit();
+                sessionDelegate.commit();
                 refresh();
             } catch (CommitFailedException e) {
-                getWorkspaceRoot().refresh();
+                sessionDelegate.refresh(true);
                 throw e.asRepositoryException();
             }
         }
@@ -193,7 +191,7 @@ public class ReadWriteVersionManager ext
         versionStorage.getTree().setProperty(REP_ADD_VERSION_LABELS,
                 Collections.singleton(labelPath), Type.PATHS);
         try {
-            checkNotNull(versionStorage).commit();
+            sessionDelegate.commit(versionStorage.getRoot());
             refresh();
         } catch (CommitFailedException e) {
             versionStorage.refresh();
@@ -217,7 +215,7 @@ public class ReadWriteVersionManager ext
         versionStorage.getTree().setProperty(REP_REMOVE_VERSION_LABELS,
                 Collections.singleton(labelPath), Type.PATHS);
         try {
-            checkNotNull(versionStorage).commit();
+            sessionDelegate.commit(versionStorage.getRoot());
             refresh();
         } catch (CommitFailedException e) {
             versionStorage.refresh();