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 md...@apache.org on 2013/06/05 14:06:58 UTC

svn commit: r1489829 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: core/ContentSessionImpl.java plugins/observation/ChangeDispatcher.java

Author: mduerig
Date: Wed Jun  5 12:06:58 2013
New Revision: 1489829

URL: http://svn.apache.org/r1489829
Log:
OAK-775 Implement backward compatible observation
javadoc

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/ChangeDispatcher.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java?rev=1489829&r1=1489828&r2=1489829&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java Wed Jun  5 12:06:58 2013
@@ -97,7 +97,7 @@ class ContentSessionImpl implements Cont
     @Override
     public Root getLatestRoot() {
         checkLive();
-        RootImpl root = new RootImpl(store, hook, changeDispatcher.createHook(this), workspaceName,
+        RootImpl root = new RootImpl(store, hook, changeDispatcher.newHook(this), workspaceName,
                 loginContext.getSubject(), securityProvider, indexProvider) {
             @Override
             protected void checkLive() {

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=1489829&r1=1489828&r2=1489829&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 Jun  5 12:06:58 2013
@@ -37,22 +37,55 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.NodeStore;
 import org.apache.jackrabbit.oak.util.TODO;
 
+/**
+ * A {@code ChangeDispatcher} instance records changes to a {@link NodeStore}
+ * and dispatches them to interested parties.
+ * <p>
+ * The {@link #newHook(ContentSession)} method registers a hook for
+ * reporting changes. Actual changes are reported by calling
+ * {@link Hook#contentChanged(NodeState, NodeState)}. Such changes are considered
+ * to have occurred on the local cluster node and are recorded as such. Changes
+ * that occurred in-between calls to any hook registered with a change processor
+ * are considered to have occurred on a different cluster node and are recorded as such.
+ * <p>
+ * The {@link #newListener()} registers a listener for receiving changes reported
+ * into a change dispatcher by any of its hooks.
+ */
 public class ChangeDispatcher {
     private final NodeStore store;
     private final Set<Listener> listeners = Sets.newHashSet();
 
-    private NodeState previous;
+    private NodeState previousRoot;
 
-    public ChangeDispatcher(NodeStore store) {
+    /**
+     * Create a new instance for recording changes to {@code store}.
+     * @param store  the node store to record changes for
+     */
+    public ChangeDispatcher(@Nonnull NodeStore store) {
         this.store = store;
-        previous = checkNotNull(store.getRoot());
+        previousRoot = checkNotNull(store.getRoot());
     }
 
+    /**
+     * Create a new {@link Hook} for reporting changes occurring in the
+     * passed {@code contentSession}. The content session is used to
+     * determine the user associated with the changes recorded through this
+     * hook and to determine the originating session of changes.
+     * @param contentSession  session which will be associated with any changes reported
+     *                        through this hook.
+     * @return a new {@code Hook} instance
+     */
     @Nonnull
-    public Hook createHook(ContentSession contentSession) {
+    public Hook newHook(ContentSession contentSession) {
         return new Hook(contentSession);
     }
 
+    /**
+     * Create a new {@link Listener} for receiving changes reported into
+     * this change dispatcher. Listeners need to be {@link Listener#dispose() disposed}
+     * when no longer needed.
+     * @return  a new {@code Listener} instance.
+     */
     @Nonnull
     public Listener newListener() {
         Listener listener = new Listener();
@@ -75,9 +108,9 @@ public class ChangeDispatcher {
 
     @CheckForNull
     private synchronized ChangeSet externalChange(NodeState root) {
-        if (root != previous) {
-            ChangeSet changeSet = ChangeSet.external(previous, root);
-            previous = root;
+        if (root != previousRoot) {
+            ChangeSet changeSet = ChangeSet.external(previousRoot, root);
+            previousRoot = root;
             return changeSet;
         }
         return null;
@@ -85,8 +118,8 @@ public class ChangeDispatcher {
 
     @Nonnull
     private synchronized ChangeSet internalChange(NodeState root, ContentSession contentSession) {
-        ChangeSet changeSet = ChangeSet.local(previous, root, contentSession);
-        previous = root;
+        ChangeSet changeSet = ChangeSet.local(previousRoot, root, contentSession);
+        previousRoot = root;
         return changeSet;
     }
 
@@ -116,6 +149,13 @@ public class ChangeDispatcher {
 
     //------------------------------------------------------------< Sink >---
 
+    /**
+     * Hook for reporting changes. Actual changes are reported by calling
+     * {@link Hook#contentChanged(NodeState, NodeState)}. Such changes are considered
+     * to have occurred on the local cluster node and are recorded as such. Changes
+     * that occurred in-between calls to any hook registered with a change processor
+     * are considered to have occurred on a different cluster node and are recorded as such.
+     */
     public class Hook implements PostCommitHook {
         private final ContentSession contentSession;
 
@@ -131,13 +171,24 @@ public class ChangeDispatcher {
 
     //------------------------------------------------------------< Listener >---
 
+    /**
+     * Listener for receiving changes reported into a change dispatcher by any of its hooks.
+     */
     public class Listener {
         private final Queue<ChangeSet> changeSets = Queues.newLinkedBlockingQueue();
 
+        /**
+         * Free up any resources associated by this hook.
+         */
         public void dispose() {
             unregister(this);
         }
 
+        /**
+         * Poll for changes reported to this listener.
+         * @return  {@code ChangeSet} of the changes or {@code null} if no changes occurred since
+         *          the last call to this method.
+         */
         @CheckForNull
         public ChangeSet getChanges() {
             if (changeSets.isEmpty()) {
@@ -153,15 +204,21 @@ public class ChangeDispatcher {
 
     //------------------------------------------------------------< ChangeSet >---
 
+    /**
+     * Instances of this class represent changes to a node store. In addition they
+     * record meta data associated with such changes like whether a change occurred
+     * on the local cluster node, the user causing the changes and the date the changes
+     * where persisted.
+     */
     public abstract static class ChangeSet {
         private final NodeState before;
         private final NodeState after;
 
-        public static ChangeSet local(NodeState base, NodeState head, ContentSession contentSession) {
+        static ChangeSet local(NodeState base, NodeState head, ContentSession contentSession) {
             return new InternalChangeSet(base, head, contentSession, System.currentTimeMillis());
         }
 
-        public static ChangeSet external(NodeState base, NodeState head) {
+        static ChangeSet external(NodeState base, NodeState head) {
             return new ExternalChangeSet(base, head);
         }
 
@@ -170,11 +227,38 @@ public class ChangeDispatcher {
             this.after = after;
         }
 
+        /**
+         * Determine whether these changes originate from the local cluster node
+         * or an external cluster node.
+         * @return  {@code true} iff the changes originate from a remote cluster node.
+         */
         public abstract boolean isExternal();
+
+        /**
+         * Determine whether these changes where caused by the passed content
+         * session.
+         * @param contentSession  content session to test for
+         * @return  {@code true} iff these changes where cause by the passed content session.
+         *          Always {@code false} if {@link #isExternal()} is {@code true}.
+         */
         public abstract boolean isLocal(ContentSession contentSession);
+
+        /**
+         * Determine the user associated with these changes.
+         * @return  user id or {@link ObservationConstants#OAK_UNKNOWN} if {@link #isExternal()} is {@code true}.
+         */
         public abstract String getUserId();
+
+        /**
+         * Determine the date when these changes where persisted.
+         * @return  date or {@code 0} if {@link #isExternal()} is {@code true}.
+         */
         public abstract long getDate();
 
+        /**
+         * {@link NodeStateDiff} of the changes
+         * @param diff  node state diff instance for traversing the changes.
+         */
         public void diff(NodeStateDiff diff) {
             // TODO wrap diff into access check wrapper
             after.compareAgainstBaseState(before, diff);