Author: jukka
Date: Sat Jan 25 02:29:12 2014
New Revision: 1561246
URL: http://svn.apache.org/r1561246
Log:
OAK-1332: Large number of changes to the same node can fill observation queue
Extract the shared state of all observation events originating from the
same commit to a separate EventContext object. This helps reduce the
memory overhead of a large queue of events.
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventContext.java
(with props)
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/EventImpl.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/JcrListener.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CommitInfo.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=1561246&r1=1561245&r2=1561246&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
Sat Jan 25 02:29:12 2014
@@ -163,10 +163,11 @@ public class ChangeProcessor implements
EventFilter acFilter = new ACFilter(previousRoot, root,
permissionProvider, basePath);
ImmutableTree beforeTree = getTree(previousRoot, basePath);
ImmutableTree afterTree = getTree(root, basePath);
+ EventContext context = new EventContext(namePathMapper,
info);
EventIterable<Event> events = new EventIterable<Event>(
beforeTree.getNodeState(),
afterTree.getNodeState(),
Filters.all(userFilter, acFilter),
- new JcrListener(beforeTree, afterTree,
namePathMapper, info));
+ new JcrListener(context, beforeTree, afterTree));
Iterator<Event> iterator = events.iterator();
if (iterator.hasNext() && runningMonitor.enterIf(running))
{
try {
Added:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventContext.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventContext.java?rev=1561246&view=auto
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventContext.java
(added)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventContext.java
Sat Jan 25 02:29:12 2014
@@ -0,0 +1,95 @@
+/*
+ * 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.observation;
+
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
+
+/**
+ * Information shared by all events coming from a single commit.
+ */
+final class EventContext {
+
+ /**
+ * Dummy session identifier used to identify external commits.
+ */
+ private static final String OAK_EXTERNAL = "oak:external";
+
+ private final NamePathMapper mapper;
+
+ private final CommitInfo info;
+
+ EventContext(NamePathMapper mapper, CommitInfo info) {
+ this.mapper = mapper;
+ if (info != null) {
+ this.info = info;
+ } else {
+ // Generate a dummy CommitInfo object to avoid extra null checks.
+ // The current time is used as a rough estimate of the commit time.
+ this.info = new CommitInfo(OAK_EXTERNAL, null, null);
+ }
+ }
+
+ String getJcrName(String name) {
+ return mapper.getJcrName(name);
+ }
+
+ String getJcrPath(String path) {
+ return mapper.getJcrPath(path);
+ }
+
+ String getUserID() {
+ return info.getUserId();
+ }
+
+ String getUserData() {
+ return info.getMessage();
+ }
+
+ long getDate() {
+ return info.getDate();
+ }
+
+ boolean isExternal() {
+ return info.getSessionId() == OAK_EXTERNAL;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ } else if (object instanceof EventContext) {
+ EventContext that = (EventContext) object;
+ return info.equals(that.info);
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return info.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return info.toString();
+ }
+
+}
\ No newline at end of file
Propchange:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventContext.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventImpl.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventImpl.java?rev=1561246&r1=1561245&r2=1561246&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventImpl.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventImpl.java
Sat Jan 25 02:29:12 2014
@@ -16,41 +16,32 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.jackrabbit.oak.plugins.observation;
-import java.util.Collections;
import java.util.Map;
-import javax.jcr.RepositoryException;
-
import org.apache.jackrabbit.api.observation.JackrabbitEvent;
+import com.google.common.base.Objects;
+
/**
* TODO document
*/
-class EventImpl implements JackrabbitEvent {
+final class EventImpl implements JackrabbitEvent {
+ private final EventContext context;
private final int type;
- private final String jcrPath;
- private final String userID;
+ private final String path;
private final String identifier;
private final Map<?, ?> info;
- private final long date;
- private final String userData;
- private final boolean external;
-
- EventImpl(
- int type, String jcrPath, String userID, String identifier,
- Map<?, ?> info, long date, String userData, boolean external) {
+
+ EventImpl(EventContext context,
+ int type, String path, String identifier, Map<?, ?> info) {
+ this.context = context;
this.type = type;
- this.jcrPath = jcrPath;
- this.userID = userID;
+ this.path = path;
this.identifier = identifier;
- this.info = info == null ? Collections.emptyMap() : info;
- this.date = date;
- this.userData = userData;
- this.external = external;
+ this.info = info;
}
@Override
@@ -59,13 +50,13 @@ class EventImpl implements JackrabbitEve
}
@Override
- public String getPath() throws RepositoryException {
- return jcrPath;
+ public String getPath() {
+ return context.getJcrPath(path);
}
@Override
public String getUserID() {
- return userID;
+ return context.getUserID();
}
@Override
@@ -80,63 +71,51 @@ class EventImpl implements JackrabbitEve
@Override
public String getUserData() {
- return userData;
+ return context.getUserData();
}
@Override
public long getDate() {
- return date;
+ return context.getDate();
}
@Override
- public synchronized boolean isExternal() {
- return external;
+ public boolean isExternal() {
+ return context.isExternal();
}
+ //------------------------------------------------------------< Object >--
+
@Override
- public final boolean equals(Object other) {
- if (this == other) {
+ public boolean equals(Object object) {
+ if (this == object) {
return true;
- }
- if (other == null || getClass() != other.getClass()) {
+ } else if (object instanceof EventImpl) {
+ EventImpl that = (EventImpl) object;
+ return Objects.equal(this.context, that.context)
+ && this.type == that.type
+ && Objects.equal(this.path, that.path)
+ && Objects.equal(this.identifier, that.identifier)
+ && Objects.equal(this.info, that.info);
+ } else {
return false;
}
-
- EventImpl that = (EventImpl) other;
- return date == that.date && type == that.type &&
- (identifier == null ? that.identifier == null :
identifier.equals(that.identifier)) &&
- (info == null ? that.info == null : info.equals(that.info)) &&
- (jcrPath == null ? that.jcrPath == null :
jcrPath.equals(that.jcrPath)) &&
- (userID == null ? that.userID == null :
userID.equals(that.userID)) &&
- (userData == null ? that.userData == null :
userData.equals(that.userData)) &&
- external == that.external;
-
}
@Override
- public final int hashCode() {
- int result = type;
- result = 31 * result + (jcrPath == null ? 0 : jcrPath.hashCode());
- result = 31 * result + (userID == null ? 0 : userID.hashCode());
- result = 31 * result + (identifier == null ? 0 :
identifier.hashCode());
- result = 31 * result + (info == null ? 0 : info.hashCode());
- result = 31 * result + (int) (date ^ (date >>> 32));
- result = 31 * result + (userData == null ? 0 : userData.hashCode());
- return result;
+ public int hashCode() {
+ return Objects.hashCode(context, type, path, identifier, info);
}
@Override
public String toString() {
- return "EventImpl{" +
- "type=" + type +
- ", jcrPath='" + jcrPath + '\'' +
- ", userID='" + userID + '\'' +
- ", identifier='" + identifier + '\'' +
- ", info=" + info +
- ", date=" + date +
- ", userData=" + userData +
- ", external=" + external +
- '}';
+ return Objects.toStringHelper(this)
+ .add("type", type)
+ .add("path", path)
+ .add("identifier", identifier)
+ .add("info", info)
+ .add("context", context)
+ .toString();
}
}
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/JcrListener.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/JcrListener.java?rev=1561246&r1=1561245&r2=1561246&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/JcrListener.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/JcrListener.java
Sat Jan 25 02:29:12 2014
@@ -39,52 +39,28 @@ import com.google.common.collect.Immutab
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.namepath.PathMapper;
+import org.apache.jackrabbit.oak.core.ImmutableTree;
import
org.apache.jackrabbit.oak.plugins.observation.EventIterable.IterableListener;
-import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.state.NodeState;
/**
* TODO JcrListener...
*/
class JcrListener implements IterableListener<Event> {
- private final Tree beforeTree;
- private final Tree afterTree;
- private final List<Event> events = newArrayList();
- private final PathMapper namePathMapper;
- private final String userId;
- private final long timestamp;
- private final String message;
- private final boolean external;
- JcrListener(Tree beforeTree, Tree afterTree, PathMapper namePathMapper,
CommitInfo info) {
- this.beforeTree = beforeTree;
- this.afterTree = afterTree;
- this.namePathMapper = namePathMapper;
- 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;
- }
- }
+ private final EventContext context;
- private JcrListener(Tree beforeTree, Tree afterTree, PathMapper
namePathMapper, String userId,
- long timestamp, String message, boolean external) {
+ private final ImmutableTree beforeTree;
+ private final ImmutableTree afterTree;
+
+ private final List<Event> events = newArrayList();
+
+ JcrListener(
+ EventContext context,
+ ImmutableTree beforeTree, ImmutableTree afterTree) {
+ this.context = context;
this.beforeTree = beforeTree;
this.afterTree = afterTree;
- this.namePathMapper = namePathMapper;
- this.userId = userId;
- this.timestamp = timestamp;
- this.message = message;
- this.external = external;
}
@Override
@@ -122,14 +98,15 @@ class JcrListener implements IterableLis
String destPath = PathUtils.concat(afterTree.getPath(), name);
events.add(createEvent(NODE_MOVED, afterTree.getChild(name),
ImmutableMap.of(
- "srcAbsPath", namePathMapper.getJcrPath(sourcePath),
- "destAbsPath", namePathMapper.getJcrPath(destPath))));
+ "srcAbsPath", context.getJcrPath(sourcePath),
+ "destAbsPath", context.getJcrPath(destPath))));
}
@Override
public JcrListener create(String name, NodeState before, NodeState after) {
- return new JcrListener(beforeTree.getChild(name),
afterTree.getChild(name), namePathMapper,
- userId, timestamp, message, external);
+ return new JcrListener(
+ context,
+ new ImmutableTree(beforeTree, name, before),
afterTree.getChild(name));
}
@Override
@@ -156,30 +133,24 @@ class JcrListener implements IterableLis
beforeNames.set(a, beforeName);
events.add(createEvent(NODE_MOVED,
afterTree.getChild(name).getChild(afterName),
ImmutableMap.of(
- "srcChildRelPath", beforeNames.get(a),
- "destChildRelPath", beforeNames.get(a +
1))));
+ "srcChildRelPath",
context.getJcrName(beforeNames.get(a)),
+ "destChildRelPath",
context.getJcrName(beforeNames.get(a + 1)))));
}
}
}
}
private Event createEvent(int eventType, Tree tree) {
- return createEvent(eventType, tree.getPath(), getIdentifier(tree),
emptyMap());
+ return new EventImpl(context, eventType, tree.getPath(),
getIdentifier(tree), emptyMap());
}
private Event createEvent(int eventType, Tree tree, Map<?, ?> info) {
- return createEvent(eventType, tree.getPath(), getIdentifier(tree),
info);
+ return new EventImpl(context, eventType, tree.getPath(),
getIdentifier(tree), info);
}
private Event createEvent(int eventType, Tree parent, PropertyState
property) {
String path = PathUtils.concat(parent.getPath(), property.getName());
- return createEvent(eventType, path, getIdentifier(parent), emptyMap());
- }
-
- private Event createEvent(int eventType, String path, String id, Map<?, ?>
info) {
- return new EventImpl(
- eventType, namePathMapper.getJcrPath(path), userId, id,
- info, timestamp, message, external);
+ return new EventImpl(context, eventType, path, getIdentifier(parent),
emptyMap());
}
}
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=1561246&r1=1561245&r2=1561246&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
Sat Jan 25 02:29:12 2014
@@ -25,10 +25,12 @@ import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import com.google.common.base.Objects;
+
/**
* Commit info instances associate some meta data with a commit.
*/
-public class CommitInfo {
+public final class CommitInfo {
public static final String OAK_UNKNOWN = "oak:unknown";
@@ -84,6 +86,28 @@ public class CommitInfo {
return date;
}
+ //------------------------------------------------------------< Object >--
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ } else if (object instanceof CommitInfo) {
+ CommitInfo that = (CommitInfo) object;
+ return sessionId.equals(that.sessionId)
+ && userId.equals(that.userId)
+ && Objects.equal(this.message, that.message)
+ && this.date == that.date;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(sessionId, userId, message, date);
+ }
+
@Override
public String toString() {
return toStringHelper(this)
@@ -93,4 +117,5 @@ public class CommitInfo {
.add("date", date)
.toString();
}
+
}