Author: jukka
Date: Tue Nov 5 23:33:03 2013
New Revision: 1539195
URL: http://svn.apache.org/r1539195
Log:
OAK-1143: [scala] Repository init throws "illegal cyclic reference involving
class ChangeDispatcher"
Adjust the Observer interface as suggested in the issue
Modified:
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/plugins/mongomk/MongoNodeStore.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/spi/commit/EmptyObserver.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/Observer.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/kernel/NodeStoreTest.java
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=1539195&r1=1539194&r2=1539195&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
Tue Nov 5 23:33:03 2013
@@ -158,9 +158,8 @@ public class KernelNodeStore implements
public synchronized KernelNodeState getRoot() {
String revision = kernel.getHeadRevision();
if (!revision.equals(root.getRevision())) {
- NodeState before = root;
root = getRootState(revision);
- observer.contentChanged(before, root);
+ observer.contentChanged(root, null);
}
return root;
}
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=1539195&r1=1539194&r2=1539195&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
Tue Nov 5 23:33:03 2013
@@ -329,13 +329,10 @@ public final class MongoNodeStore
Revision setHeadRevision(@Nonnull Revision newHead) {
checkArgument(!newHead.isBranch());
Revision previous = headRevision;
- if (checkNotNull(newHead).equals(previous)) {
- return previous;
- }
- // head changed
- headRevision = newHead;
- if (previous != null) {
- observer.contentChanged(getRoot(previous), getRoot(newHead));
+ if (!checkNotNull(newHead).equals(previous)) {
+ // head changed
+ headRevision = newHead;
+ observer.contentChanged(getRoot(newHead), null);
}
return previous;
}
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=1539195&r1=1539194&r2=1539195&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
Tue Nov 5 23:33:03 2013
@@ -84,11 +84,9 @@ public class SegmentNodeStore implements
}
synchronized SegmentNodeState getHead() {
- NodeState before = head.getChildNode(ROOT);
head = new SegmentNodeState(
store.getWriter().getDummySegment(), journal.getHead());
- NodeState after = head.getChildNode(ROOT);
- observer.contentChanged(before, after);
+ observer.contentChanged(head.getChildNode(ROOT), null);
return head;
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EmptyObserver.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EmptyObserver.java?rev=1539195&r1=1539194&r2=1539195&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EmptyObserver.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EmptyObserver.java
Tue Nov 5 23:33:03 2013
@@ -16,6 +16,9 @@
*/
package org.apache.jackrabbit.oak.spi.commit;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import org.apache.jackrabbit.oak.spi.state.NodeState;
/**
@@ -31,7 +34,8 @@ public class EmptyObserver implements Ob
public static final EmptyObserver INSTANCE = new EmptyObserver();
@Override
- public void contentChanged(NodeState before, NodeState after) {
+ public void contentChanged(
+ @Nonnull NodeState root, @Nullable CommitInfo info) {
// do nothing
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/Observer.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/Observer.java?rev=1539195&r1=1539194&r2=1539195&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/Observer.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/Observer.java
Tue Nov 5 23:33:03 2013
@@ -16,51 +16,55 @@
*/
package org.apache.jackrabbit.oak.spi.commit;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import org.apache.jackrabbit.oak.spi.state.NodeState;
/**
- * Extension point for observing changes in an Oak repository. Content
- * changes are reported by passing the "before" and "after" state of the
- * content tree to the {@link #contentChanged(NodeState, NodeState)}
- * callback method.
+ * Extension point for observing changes in an Oak repository. Observer
+ * implementations might use the observed content changes to update caches,
+ * trigger JCR-level observation events or otherwise process the changes.
+ * <p>
+ * An observer is informed about content changes by calling the
+ * {@link #contentChanged(NodeState, CommitInfo)} method. The frequency and
+ * granularity of these callbacks is not specified. However, each observer is
+ * always guaranteed a linear sequence of changes. In other words the
+ * method will not be called concurrently from multiple threads and successive
+ * calls to represent a logical sequence of repository states, i.e. the root
+ * state passed to one call is guaranteed to be a base state of the root
+ * state passed to the next call. The observer is expected to keep track of
+ * the previously observed state if it wants to use a content diff to
+ * determine what exactly changed between two states.
* <p>
- * Each observer is guaranteed to see a linear sequence of changes, i.e.
- * the "after" state of one method call is guaranteed to be the "before"
- * state of the following call. This sequence of changes only applies while
- * a hook is registered with a specific repository instance, and is thus for
- * example <em>not</me> guaranteed across repository restarts.
+ * A repository may capture the optional {@link CommitInfo} instance passed
+ * to a commit and make it available to observers along with the committed
+ * committed content changes. In such cases, i.e. when the commit info
+ * argument is non-{@code null}, the reported content change is guaranteed
+ * to contain <em>only</em> changes from that specific commit (and the
+ * applied commit hooks). Note that it is possible for a repository to report
+ * commit information for only some commits but not others.
* <p>
- * Note also that two observers may not necessarily see the same sequence of
- * content changes, and each commit does not necessarily trigger a separate
- * observer callback. It is also possible for an observer to be notified
- * when no actual changes have been committed.
+ * It should also be noted that two observers may not necessarily see the
+ * same sequence of content changes. It is also possible for an observer to
+ * be notified when no actual content changes have happened.
* <p>
* A specific implementation or deployment may offer more guarantees about
* when and how observers are notified of content changes. See the relevant
* documentation for more details about such cases.
*
- * @since Oak 0.3
+ * @since Oak 0.11
*/
public interface Observer {
/**
- * Observes a content change. The implementation might for example
- * use this information to update caches, trigger JCR-level observation
- * events or otherwise record the change.
- * <p>
- * Content changes are observed for both commits made locally against
- * the repository instance to which the hook is registered and any
- * other changes committed by other repository instances in the same
- * cluster.
- * <p>
- * After-commit hooks are executed synchronously within the context of
- * a repository instance, so to prevent delaying access to latest changes
- * the after-commit hooks should avoid any potentially blocking
- * operations.
+ * Observes a content change. See the {@link Observer} class javadocs
+ * and relevant repository and observer registration details for more
+ * information on when and how this method gets called.
*
- * @param before content tree before the changes
- * @param after content tree after the changes
+ * @param root root state of the repository
+ * @param info local commit information, or {@code null}
*/
- void contentChanged(NodeState before, NodeState after);
+ void contentChanged(@Nonnull NodeState root, @Nullable CommitInfo info);
}
Modified:
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java?rev=1539195&r1=1539194&r2=1539195&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/NodeStoreFixture.java
Tue Nov 5 23:33:03 2013
@@ -23,12 +23,16 @@ import static org.apache.jackrabbit.oak.
import java.io.Closeable;
import java.io.IOException;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
import org.apache.jackrabbit.mk.core.MicroKernelImpl;
import org.apache.jackrabbit.oak.plugins.mongomk.MongoMK;
import org.apache.jackrabbit.oak.kernel.KernelNodeStore;
import org.apache.jackrabbit.oak.plugins.mongomk.MongoNodeStore;
import org.apache.jackrabbit.oak.plugins.segment.SegmentNodeStore;
import org.apache.jackrabbit.oak.plugins.segment.memory.MemoryStore;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.Observer;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStore;
@@ -163,12 +167,14 @@ public abstract class NodeStoreFixture {
}
private static class ResettableObserver implements Observer {
+
private Observer observer;
@Override
- public void contentChanged(NodeState before, NodeState after) {
+ public void contentChanged(
+ @Nonnull NodeState root, @Nullable CommitInfo info) {
if (observer != null) {
- observer.contentChanged(before, after);
+ observer.contentChanged(root, info);
}
}
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=1539195&r1=1539194&r2=1539195&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
Tue Nov 5 23:33:03 2013
@@ -18,6 +18,7 @@
*/
package org.apache.jackrabbit.oak.kernel;
+import static com.google.common.base.Preconditions.checkNotNull;
import static junit.framework.Assert.assertFalse;
import static org.apache.jackrabbit.oak.api.Type.LONG;
import static org.junit.Assert.assertEquals;
@@ -30,12 +31,17 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.apache.jackrabbit.oak.NodeStoreFixture;
import org.apache.jackrabbit.oak.api.CommitFailedException;
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;
@@ -137,14 +143,13 @@ public class NodeStoreTest {
@Test
public void afterCommitHook() throws CommitFailedException {
- final NodeState[] states = new NodeState[2]; // { before, after }
+ final AtomicReference<NodeState> observedRoot =
+ new AtomicReference<NodeState>(null);
fixture.setObserver(new Observer() {
@Override
- public void contentChanged(NodeState before, NodeState after) {
- if (!before.equals(after)) {
- states[0] = before;
- states[1] = after;
- }
+ public void contentChanged(
+ @Nonnull NodeState root, @Nullable CommitInfo info) {
+ observedRoot.set(checkNotNull(root));
}
});
@@ -160,12 +165,8 @@ public class NodeStoreTest {
store.merge(rootBuilder, EmptyHook.INSTANCE, null);
NodeState newRoot = store.getRoot(); // triggers the observer
- NodeState before = states[0];
- NodeState after = states[1];
- assertNotNull(before);
+ NodeState after = observedRoot.get();
assertNotNull(after);
-
-
assertFalse(before.getChildNode("test").getChildNode("newNode").exists());
assertTrue(after.getChildNode("test").getChildNode("newNode").exists());
assertFalse(after.getChildNode("test").getChildNode("a").exists());
assertEquals(42, (long)
after.getChildNode("test").getChildNode("newNode").getProperty("n").getValue(LONG));