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 2014/01/27 20:15:10 UTC
svn commit: r1561798 - in
/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation:
ChangeProcessor.java EventGenerator.java
Author: jukka
Date: Mon Jan 27 19:15:10 2014
New Revision: 1561798
URL: http://svn.apache.org/r1561798
Log:
OAK-1332: Large number of changes to the same node can fill observation queue
Postpone generation of NODE_ADDED and NODE_REMOVED events to when the
added or removed node gets diffed. This way only a single NODE_ADDED or
NODE_REMOVED event instance will be in the in the event queue at any
given time.
Modified:
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/observation/EventGenerator.java
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=1561798&r1=1561797&r2=1561798&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 Mon Jan 27 19:15:10 2014
@@ -34,8 +34,6 @@ import org.apache.jackrabbit.api.jmx.Eve
import org.apache.jackrabbit.commons.iterator.EventIteratorAdapter;
import org.apache.jackrabbit.commons.observation.ListenerTracker;
import org.apache.jackrabbit.oak.api.ContentSession;
-import org.apache.jackrabbit.oak.core.ImmutableRoot;
-import org.apache.jackrabbit.oak.core.ImmutableTree;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
import org.apache.jackrabbit.oak.plugins.observation.filter.ACFilter;
import org.apache.jackrabbit.oak.plugins.observation.filter.EventFilter;
@@ -159,10 +157,8 @@ public class ChangeProcessor implements
String basePath = provider.getPath();
EventFilter userFilter = provider.getFilter(previousRoot, root);
EventFilter acFilter = new ACFilter(previousRoot, root, permissionProvider, basePath);
- ImmutableTree beforeTree = getTree(previousRoot, basePath);
- ImmutableTree afterTree = getTree(root, basePath);
EventGenerator events = new EventGenerator(
- namePathMapper, info, beforeTree, afterTree,
+ namePathMapper, info, previousRoot, root, basePath,
Filters.all(userFilter, acFilter));
if (events.hasNext() && runningMonitor.enterIf(running)) {
try {
@@ -179,10 +175,6 @@ public class ChangeProcessor implements
previousRoot = root;
}
- private static ImmutableTree getTree(NodeState nodeState, String path) {
- return new ImmutableRoot(nodeState).getTree(path);
- }
-
private static class RunningGuard extends Guard {
private boolean stopped;
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java?rev=1561798&r1=1561797&r2=1561798&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventGenerator.java Mon Jan 27 19:15:10 2014
@@ -75,17 +75,21 @@ public class EventGenerator implements E
*/
public EventGenerator(
@Nonnull NamePathMapper namePathMapper, CommitInfo info,
- @Nonnull ImmutableTree before, @Nonnull ImmutableTree after,
- @Nonnull EventFilter filter) {
+ @Nonnull NodeState before, @Nonnull NodeState after,
+ @Nonnull String basePath, @Nonnull EventFilter filter) {
this.context = new EventContext(namePathMapper, info);
filter = Filters.all(new VisibleFilter(), checkNotNull(filter));
- new EventDiff(before, after, filter).run();
+
+ new EventDiff(before, after, basePath, filter).run();
}
private class EventDiff implements NodeStateDiff, Runnable {
- private final EventFilter filter;
+ /**
+ * The diff handler of the parent node, or {@code null} for the root.
+ */
+ private final EventDiff parent;
/**
* The name of this node, or the empty string for the root.
@@ -93,35 +97,58 @@ public class EventGenerator implements E
private final String name;
/**
- * Before state of this node.
+ * Before state, or {@code MISSING_NODE} if this node was added.
*/
private final NodeState before;
/**
- * AFter state of this node.
+ * After state, or {@code MISSING_NODE} if this node was removed.
*/
private final NodeState after;
+ /**
+ * Filter for selecting which events to produce, or {@code null} if
+ * no events should be produced below this node.
+ */
+ private final EventFilter filter;
+
private final ImmutableTree beforeTree;
private final ImmutableTree afterTree;
- EventDiff(ImmutableTree before, ImmutableTree after,
+ EventDiff(NodeState before, NodeState after, String path,
EventFilter filter) {
- this.name = before.getName();
- this.before = before.getNodeState();
- this.after = after.getNodeState();
+ String name = null;
+ ImmutableTree btree = new ImmutableTree(before);
+ ImmutableTree atree = new ImmutableTree(after);
+ for (String element : PathUtils.elements(path)) {
+ name = element;
+ before = before.getChildNode(name);
+ after = after.getChildNode(name);
+ btree = new ImmutableTree(btree, name, before);
+ atree = new ImmutableTree(atree, name, after);
+ }
+
+ this.parent = null;
+ this.name = name;
+ this.before = before;
+ this.after = after;
this.filter = filter;
- this.beforeTree = before;
- this.afterTree = after;
+ this.beforeTree = btree;
+ this.afterTree = atree;
}
- public EventDiff(
+ private EventDiff(
EventDiff parent, String name,
- NodeState before, NodeState after, EventFilter filter) {
+ NodeState before, NodeState after) {
+ this.parent = parent;
this.name = name;
this.before = before;
this.after = after;
- this.filter = filter;
+ if (parent.filter != null) {
+ this.filter = parent.filter.create(name, before, after);
+ } else {
+ this.filter = null;
+ }
this.beforeTree = new ImmutableTree(parent.beforeTree, name, before);
this.afterTree = new ImmutableTree(parent.afterTree, name, after);
}
@@ -130,9 +157,39 @@ public class EventGenerator implements E
@Override
public void run() {
- after.compareAgainstBaseState(before, this);
+ // postponed handling of added nodes
+ if (before == MISSING_NODE && parent != null) {
+ PropertyState sourceProperty = after.getProperty(SOURCE_PATH);
+ if (sourceProperty != null) {
+ String sourcePath = sourceProperty.getValue(STRING);
+ if (parent.filter.includeMove(sourcePath, name, after)) {
+ Map<String, String> info = ImmutableMap.of(
+ "srcAbsPath", context.getJcrPath(sourcePath),
+ "destAbsPath", context.getJcrPath(afterTree.getPath()));
+ events.add(new EventImpl(context, NODE_MOVED, afterTree, info));
+ }
+ }
+
+ if (parent.filter.includeAdd(name, after)) {
+ events.add(new EventImpl(context, NODE_ADDED, afterTree));
+ }
+ }
+
+ // postponed handling of removed nodes
+ if (after == MISSING_NODE && parent != null) {
+ if (parent.filter.includeDelete(name, before)) {
+ events.add(new EventImpl(context, NODE_REMOVED, beforeTree));
+ }
+ }
+
+ // process changes below this node
+ if (filter != null) {
+ after.compareAgainstBaseState(before, this);
+ }
}
+ //-------------------------------------------------< NodeStateDiff >--
+
@Override
public boolean propertyAdded(PropertyState after) {
if (filter.includeAdd(after)) {
@@ -168,40 +225,20 @@ public class EventGenerator implements E
@Override
public boolean childNodeAdded(String name, NodeState after) {
- PropertyState sourceProperty = after.getProperty(SOURCE_PATH);
- if (sourceProperty != null) {
- String sourcePath = sourceProperty.getValue(STRING);
- if (filter.includeMove(sourcePath, name, after)) {
- String destPath = PathUtils.concat(afterTree.getPath(), name);
- Map<String, String> info = ImmutableMap.of(
- "srcAbsPath", context.getJcrPath(sourcePath),
- "destAbsPath", context.getJcrPath(destPath));
- ImmutableTree tree = new ImmutableTree(afterTree, name, after);
- events.add(new EventImpl(context, NODE_MOVED, tree, info));
- }
- }
- if (filter.includeAdd(name, after)) {
- ImmutableTree tree = new ImmutableTree(afterTree, name, after);
- events.add(new EventImpl(context, NODE_ADDED, tree));
- }
- addChildGenerator(name, MISSING_NODE, after);
+ generators.add(new EventDiff(this, name, MISSING_NODE, after));
return true;
}
@Override
public boolean childNodeChanged(
String name, NodeState before, NodeState after) {
- addChildGenerator(name, before, after);
+ generators.add(new EventDiff(this, name, before, after));
return true;
}
@Override
public boolean childNodeDeleted(String name, NodeState before) {
- if (filter.includeDelete(name, before)) {
- ImmutableTree tree = new ImmutableTree(beforeTree, name, before);
- events.add(new EventImpl(context, NODE_REMOVED, tree));
- }
- addChildGenerator(name, before, MISSING_NODE);
+ generators.add(new EventDiff(this, name, before, MISSING_NODE));
return true;
}
@@ -232,21 +269,6 @@ public class EventGenerator implements E
}
}
- /**
- * Factory method for creating {@code EventGenerator} instances of child nodes.
- * @param name name of the child node
- * @param before before state of the child node
- * @param after after state of the child node
- */
- private void addChildGenerator(
- String name, NodeState before, NodeState after) {
- EventFilter childFilter = filter.create(name, before, after);
- if (childFilter != null) {
- generators.add(
- new EventDiff(this, name, before, after, childFilter));
- }
- }
-
}
//-----------------------------------------------------< EventIterator >--