Author: jukka
Date: Wed Jan 29 19:07:15 2014
New Revision: 1562552
URL: http://svn.apache.org/r1562552
Log:
OAK-1332: Large number of changes to the same node can fill observation queue
Extract the path and identifier tracking code to separate utility classes.
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/PathTracker.java
(with props)
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierTracker.java
(with props)
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/PathTracker.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/PathTracker.java?rev=1562552&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/PathTracker.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/PathTracker.java
Wed Jan 29 19:07:15 2014
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.namepath;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+/**
+ * Simple utility class for lazily tracking the current path during
+ * a tree traversal that recurses down a subtree.
+ */
+public class PathTracker {
+
+ private final PathTracker parent;
+
+ private final String name;
+
+ private String path;
+
+ public PathTracker() {
+ this.parent = null;
+ this.name = null;
+ this.path = "/";
+ }
+
+ private PathTracker(PathTracker parent, String name) {
+ this.parent = parent;
+ this.name = name;
+ this.path = null; // initialize lazily
+ }
+
+ public PathTracker getChildTracker(String name) {
+ return new PathTracker(this, name);
+ }
+
+ public String getPath() {
+ if (path == null) { // implies parent != null
+ path = PathUtils.concat(parent.getPath(), name);
+ }
+ return path;
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/namepath/PathTracker.java
------------------------------------------------------------------------------
svn:eol-style = native
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierTracker.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierTracker.java?rev=1562552&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierTracker.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierTracker.java
Wed Jan 29 19:07:15 2014
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.oak.plugins.identifier;
+
+import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
+import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
+
+import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+/**
+ * Simple utility class for lazily tracking the current identifier during
+ * a tree traversal that recurses down a subtree.
+ */
+public class IdentifierTracker {
+
+ private final TypePredicate referenceable;
+
+ private final IdentifierTracker parent;
+
+ private final String name;
+
+ private String identifier;
+
+ public IdentifierTracker(NodeState root) {
+ this.referenceable = new TypePredicate(root, MIX_REFERENCEABLE);
+ this.parent = null;
+ this.name = null;
+
+ String uuid = root.getString(JCR_UUID);
+ if (uuid != null && referenceable.apply(root)) {
+ this.identifier = uuid;
+ } else {
+ this.identifier = "/";
+ }
+ }
+
+ private IdentifierTracker(
+ IdentifierTracker parent, String name, String uuid) {
+ this.referenceable = parent.referenceable;
+ this.parent = parent;
+ this.name = name;
+ this.identifier = uuid; // possibly null
+ }
+
+ public IdentifierTracker getChildTracker(String name, NodeState state) {
+ String uuid = state.getString(JCR_UUID);
+ if (uuid != null && !referenceable.apply(state)) {
+ uuid = null; // discard jcr:uuid value of a non-referenceable node
+ }
+ return new IdentifierTracker(this, name, uuid);
+ }
+
+ public String getIdentifier() {
+ if (identifier == null) { // implies parent != null
+ identifier = PathUtils.concat(parent.getIdentifier(), name);
+ }
+ return identifier;
+ }
+
+}
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierTracker.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java?rev=1562552&r1=1562551&r2=1562552&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java
(original)
+++
jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/QueueingHandler.java
Wed Jan 29 19:07:15 2014
@@ -19,8 +19,6 @@
package org.apache.jackrabbit.oak.jcr.observation;
import static java.util.Collections.emptyMap;
-import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
-import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
import java.util.Map;
@@ -28,7 +26,8 @@ import org.apache.jackrabbit.api.observa
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.commons.PathUtils;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
-import org.apache.jackrabbit.oak.plugins.nodetype.TypePredicate;
+import org.apache.jackrabbit.oak.namepath.PathTracker;
+import org.apache.jackrabbit.oak.plugins.identifier.IdentifierTracker;
import org.apache.jackrabbit.oak.plugins.observation.EventHandler;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.state.NodeState;
@@ -51,13 +50,9 @@ class QueueingHandler implements EventHa
private final String name;
- private String path = null; // initialized lazily
+ private final PathTracker pathTracker;
- private String identifier = null; // initialized lazily
-
- private final TypePredicate beforeReferenceable;
-
- private final TypePredicate afterReferenceable;
+ private final IdentifierTracker identifierTracker;
private final EventQueue queue;
@@ -74,10 +69,13 @@ class QueueingHandler implements EventHa
NodeState before, NodeState after) {
this.parent = null;
this.name = null;
- this.path = "/";
- this.beforeReferenceable = new TypePredicate(before,
MIX_REFERENCEABLE);
- this.afterReferenceable = new TypePredicate(after, MIX_REFERENCEABLE);
+ this.pathTracker = new PathTracker();
+ if (after.exists()) {
+ this.identifierTracker = new IdentifierTracker(after);
+ } else {
+ this.identifierTracker = new IdentifierTracker(before);
+ }
this.queue = queue;
this.mapper = mapper;
@@ -99,8 +97,14 @@ class QueueingHandler implements EventHa
this.parent = parent;
this.name = name;
- this.beforeReferenceable = parent.beforeReferenceable;
- this.afterReferenceable = parent.afterReferenceable;
+ this.pathTracker = parent.pathTracker.getChildTracker(name);
+ if (after.exists()) {
+ this.identifierTracker =
+ parent.identifierTracker.getChildTracker(name, after);
+ } else {
+ this.identifierTracker =
+ parent.getBeforeIdentifierTracker().getChildTracker(name,
before);
+ }
this.queue = parent.queue;
this.mapper = parent.mapper;
@@ -110,39 +114,13 @@ class QueueingHandler implements EventHa
this.after = after;
}
- private String getPath() {
- if (path == null) { // implies parent != null
- path = PathUtils.concat(parent.getPath(), name);
- }
- return path;
- }
-
- private String getIdentifier() {
- if (identifier == null) { // implies after.exists()
- String uuid = after.getString(JCR_UUID);
- if (uuid != null && afterReferenceable.apply(after)) {
- this.identifier = uuid;
- } else if (!after.exists()) {
- this.identifier = getBeforeIdentifier();
- } else if (parent == null) {
- this.identifier = "/";
- } else {
- return PathUtils.concat(parent.getIdentifier(), name);
- }
- }
- return identifier;
- }
-
- private String getBeforeIdentifier() {
- String uuid = before.getString(JCR_UUID);
- if (uuid != null && beforeReferenceable.apply(before)) {
- return uuid;
- } else if (parent == null) {
- return "/";
- } else if (parent.identifier != null && !parent.after.exists()) {
- return PathUtils.concat(parent.identifier, name);
+ private IdentifierTracker getBeforeIdentifierTracker() {
+ if (!after.exists()) {
+ return identifierTracker;
+ } else if (parent != null) {
+ return parent.getBeforeIdentifierTracker().getChildTracker(name,
before);
} else {
- return PathUtils.concat(parent.getBeforeIdentifier(), name);
+ return new IdentifierTracker(before);
}
}
@@ -186,7 +164,7 @@ class QueueingHandler implements EventHa
@Override
public void nodeAdded(String name, NodeState after) {
- queue.addEvent(new NodeEvent(name, after, afterReferenceable) {
+ queue.addEvent(new NodeEvent(name, after, identifierTracker) {
@Override
public int getType() {
return NODE_ADDED;
@@ -196,7 +174,7 @@ class QueueingHandler implements EventHa
@Override
public void nodeDeleted(String name, NodeState before) {
- queue.addEvent(new NodeEvent(name, before, beforeReferenceable) {
+ queue.addEvent(new NodeEvent(name, before,
getBeforeIdentifierTracker()) {
@Override
public int getType() {
return NODE_REMOVED;
@@ -207,7 +185,7 @@ class QueueingHandler implements EventHa
@Override
public void nodeMoved(
final String sourcePath, String name, NodeState moved) {
- queue.addEvent(new NodeEvent(name, moved, afterReferenceable) {
+ queue.addEvent(new NodeEvent(name, moved, identifierTracker) {
@Override
public int getType() {
return NODE_MOVED;
@@ -224,7 +202,7 @@ class QueueingHandler implements EventHa
@Override
public void nodeReordered(
final String destName, final String name, NodeState reordered) {
- queue.addEvent(new NodeEvent(name, reordered, afterReferenceable) {
+ queue.addEvent(new NodeEvent(name, reordered, identifierTracker) {
@Override
public int getType() {
return NODE_MOVED;
@@ -242,29 +220,17 @@ class QueueingHandler implements EventHa
private abstract class NodeEvent extends ItemEvent {
- private final String uuid;
+ private final String identifier;
- NodeEvent(String name, NodeState node, TypePredicate isReferenceable) {
+ NodeEvent(String name, NodeState node, IdentifierTracker tracker) {
super(name);
- String uuid = node.getString(JCR_UUID);
- if (uuid != null && isReferenceable.apply(node)) {
- this.uuid = uuid;
- } else {
- this.uuid = null;
- }
+ this.identifier =
+ tracker.getChildTracker(name, node).getIdentifier();
}
@Override
public String getIdentifier() {
- if (uuid != null) {
- return uuid;
- } else if (getType() == NODE_REMOVED) {
- return PathUtils.concat(
- QueueingHandler.this.getBeforeIdentifier(), name);
- } else {
- return PathUtils.concat(
- QueueingHandler.this.getIdentifier(), name);
- }
+ return identifier;
}
}
@@ -280,13 +246,13 @@ class QueueingHandler implements EventHa
@Override
public String getPath() {
return PathUtils.concat(
- mapper.getJcrPath(QueueingHandler.this.getPath()),
+ mapper.getJcrPath(pathTracker.getPath()),
mapper.getJcrName(name));
}
@Override
public String getIdentifier() {
- return QueueingHandler.this.getIdentifier();
+ return identifierTracker.getIdentifier();
}
@Override