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/29 01:10:06 UTC

svn commit: r1562321 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation: EventContext.java EventImpl.java EventQueue.java QueueingHandler.java

Author: jukka
Date: Wed Jan 29 00:10:06 2014
New Revision: 1562321

URL: http://svn.apache.org/r1562321
Log:
OAK-1332: Large number of changes to the same node can fill observation queue

Merge EventContext and EventImpl into QueueingHandler to reduce the number
of and size of objects kept around for event generation.

Removed:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventContext.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventImpl.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java?rev=1562321&r1=1562320&r2=1562321&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/EventQueue.java Wed Jan 29 00:10:06 2014
@@ -28,7 +28,6 @@ import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 
 import org.apache.jackrabbit.oak.commons.PathUtils;
-import org.apache.jackrabbit.oak.core.ImmutableTree;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.observation.filter.EventFilter;
 import org.apache.jackrabbit.oak.plugins.observation.filter.Filters;
@@ -50,12 +49,11 @@ class EventQueue implements EventIterato
     private long position = 0;
 
     public EventQueue(
-            @Nonnull NamePathMapper namePathMapper, CommitInfo info,
+            @Nonnull NamePathMapper mapper, CommitInfo info,
             @Nonnull NodeState before, @Nonnull NodeState after,
             @Nonnull String basePath, @Nonnull EventFilter filter) {
         ChangeHandler handler = new QueueingHandler(
-                queue, new EventContext(namePathMapper, info),
-                new ImmutableTree(before), new ImmutableTree(after));
+                queue, mapper, info, before, after);
         for (String name : PathUtils.elements(basePath)) {
             before = before.getChildNode(name);
             after = after.getChildNode(name);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java?rev=1562321&r1=1562320&r2=1562321&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/observation/QueueingHandler.java Wed Jan 29 00:10:06 2014
@@ -18,23 +18,24 @@
  */
 package org.apache.jackrabbit.oak.plugins.observation;
 
-import static javax.jcr.observation.Event.NODE_ADDED;
-import static javax.jcr.observation.Event.NODE_MOVED;
-import static javax.jcr.observation.Event.NODE_REMOVED;
-import static javax.jcr.observation.Event.PROPERTY_ADDED;
-import static javax.jcr.observation.Event.PROPERTY_CHANGED;
-import static javax.jcr.observation.Event.PROPERTY_REMOVED;
+import static java.util.Collections.emptyMap;
 
 import java.util.LinkedList;
 import java.util.Map;
 
 import javax.jcr.observation.Event;
 
+import org.apache.jackrabbit.api.observation.JackrabbitEvent;
 import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.core.ImmutableTree;
+import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
 import org.apache.jackrabbit.oak.plugins.observation.handler.ChangeHandler;
+import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
+import com.google.common.base.Objects;
 import com.google.common.collect.ImmutableMap;
 
 /**
@@ -43,79 +44,235 @@ import com.google.common.collect.Immutab
  */
 class QueueingHandler implements ChangeHandler {
 
+    /**
+     * Dummy session identifier used to identify external commits.
+     */
+    private static final String OAK_EXTERNAL = "oak:external";
+
     private final LinkedList<Event> queue;
 
-    private final EventContext context;
+    private final NamePathMapper mapper;
+
+    private final CommitInfo info;
 
     private final ImmutableTree before;
 
     private final ImmutableTree after;
 
     QueueingHandler(
-            LinkedList<Event> queue, EventContext context,
-            ImmutableTree before, ImmutableTree after) {
+            LinkedList<Event> queue, NamePathMapper mapper, CommitInfo info,
+            NodeState before, NodeState after) {
         this.queue = queue;
-        this.context = context;
-        this.before = before;
-        this.after = after;
+        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);
+        }
+
+        this.before = new ImmutableTree(before);
+        this.after = new ImmutableTree(after);
+    }
+
+    private QueueingHandler(
+            QueueingHandler parent,
+            String name, NodeState before, NodeState after) {
+        this.queue = parent.queue;
+        this.mapper = parent.mapper;
+        this.info = parent.info;
+        this.before = new ImmutableTree(parent.before, name, before);
+        this.after = new ImmutableTree(parent.after, name, after);
     }
 
     @Override
     public ChangeHandler getChildHandler(
             String name, NodeState before, NodeState after) {
-        return new QueueingHandler(
-                queue, context,
-                new ImmutableTree(this.before, name, before),
-                new ImmutableTree(this.after, name, after));
+        return new QueueingHandler(this, name, before, after);
     }
 
     @Override
     public void propertyAdded(PropertyState after) {
-        queue.add(new EventImpl(
-                context, PROPERTY_ADDED, this.after, after.getName()));
+        queue.add(new OakEvent(this.after, after.getName()) {
+            @Override
+            public int getType() {
+                return PROPERTY_ADDED;
+            }
+        });
     }
 
     @Override
     public void propertyChanged(PropertyState before, PropertyState after) {
-        queue.add(new EventImpl(
-                context, PROPERTY_CHANGED, this.after, after.getName()));
+        queue.add(new OakEvent(this.after, after.getName()) {
+            @Override
+            public int getType() {
+                return PROPERTY_CHANGED;
+            }
+        });
     }
 
     @Override
     public void propertyDeleted(PropertyState before) {
-        queue.add(new EventImpl(
-                context, PROPERTY_REMOVED, this.before, before.getName()));
+        queue.add(new OakEvent(this.before, before.getName()) {
+            @Override
+            public int getType() {
+                return PROPERTY_REMOVED;
+            }
+        });
     }
 
     @Override
     public void nodeAdded(String name, NodeState after) {
         ImmutableTree tree = new ImmutableTree(this.after, name, after);
-        queue.add(new EventImpl(context, NODE_ADDED, tree));
+        queue.add(new OakEvent(tree, null) {
+            @Override
+            public int getType() {
+                return NODE_ADDED;
+            }
+        });
     }
 
     @Override
     public void nodeDeleted(String name, NodeState before) {
         ImmutableTree tree = new ImmutableTree(this.before, name, before);
-        queue.add(new EventImpl(context, NODE_REMOVED, tree));
+        queue.add(new OakEvent(tree, null) {
+            @Override
+            public int getType() {
+                return NODE_REMOVED;
+            }
+        });
     }
 
     @Override
-    public void nodeMoved(String sourcePath, String name, NodeState moved) {
-        ImmutableTree tree = new ImmutableTree(this.after, name, moved);
-        Map<String, String> info = ImmutableMap.of(
-                "srcAbsPath", context.getJcrPath(sourcePath),
-                "destAbsPath", context.getJcrPath(tree.getPath()));
-        queue.add(new EventImpl(context, NODE_MOVED, tree, info));
+    public void nodeMoved(
+            final String sourcePath, String name, NodeState moved) {
+        final ImmutableTree tree = new ImmutableTree(this.after, name, moved);
+        queue.add(new OakEvent(tree, null) {
+            @Override
+            public int getType() {
+                return NODE_MOVED;
+            }
+            @Override
+            public Map<?, ?> getInfo() {
+                return ImmutableMap.of(
+                        "srcAbsPath", mapper.getJcrPath(sourcePath),
+                        "destAbsPath", mapper.getJcrPath(tree.getPath()));
+            }
+        });
     }
 
     @Override
     public void nodeReordered(
-            String destName, String name, NodeState reordered) {
-        Map<String, String> info = ImmutableMap.of(
-                "srcChildRelPath", context.getJcrName(name),
-                "destChildRelPath", context.getJcrName(destName));
+            final String destName, final String name, NodeState reordered) {
         ImmutableTree tree = new ImmutableTree(after, name, reordered);
-        queue.add(new EventImpl(context, NODE_MOVED, tree, info));
+        queue.add(new OakEvent(tree, null) {
+            @Override
+            public int getType() {
+                return NODE_MOVED;
+            }
+            @Override
+            public Map<?, ?> getInfo() {
+                return ImmutableMap.of(
+                        "srcChildRelPath", mapper.getJcrName(name),
+                        "destChildRelPath", mapper.getJcrName(destName));
+            }
+        });
+    }
+
+    //-----------------------------------------------------------< private >--
+
+    private abstract class OakEvent implements JackrabbitEvent {
+
+        private final ImmutableTree tree;
+        private final String name;
+
+        OakEvent(ImmutableTree tree, String name) {
+            this.tree = tree;
+            this.name = name;
+        }
+
+        @Override
+        public String getPath() {
+            String path = tree.getPath();
+            if (name != null) {
+                path = PathUtils.concat(path, name);
+            }
+            return mapper.getJcrPath(path);
+        }
+
+        @Override
+        public String getIdentifier() {
+            return IdentifierManager.getIdentifier(tree);
+        }
+
+        @Override
+        public Map<?, ?> getInfo() {
+            return emptyMap();
+        }
+
+        @Override
+        public String getUserID() {
+            return info.getUserId();
+        }
+
+        @Override
+        public String getUserData() {
+            return info.getMessage();
+        }
+
+        @Override
+        public long getDate() {
+            return info.getDate();
+        }
+
+        @Override
+        public boolean isExternal() {
+            return info.getSessionId() == OAK_EXTERNAL;
+        }
+
+        //--------------------------------------------------------< Object >--
+
+        @Override
+        public boolean equals(Object object) {
+            if (this == object) {
+                return true;
+            } else if (object instanceof OakEvent) {
+                OakEvent that = (OakEvent) object;
+                return getType() == that.getType()
+                        && getPath().equals(that.getPath())
+                        && getIdentifier().equals(that.getIdentifier())
+                        && getInfo().equals(that.getInfo())
+                        && Objects.equal(getUserID(), that.getUserID())
+                        && Objects.equal(getUserData(), that.getUserData())
+                        && getDate() == that.getDate()
+                        && isExternal() == that.isExternal();
+            } else {
+                return false;
+            }
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hashCode(
+                    getType(), getPath(), getIdentifier(), getInfo(),
+                    getUserID(), getUserData(), getDate(), isExternal());
+        }
+
+        @Override
+        public String toString() {
+            return Objects.toStringHelper("Event")
+                    .add("type", getType())
+                    .add("path", getPath())
+                    .add("identifier", getIdentifier())
+                    .add("info", getInfo())
+                    .add("userID", getUserID())
+                    .add("userData", getUserData())
+                    .add("date", getDate())
+                    .add("external", isExternal())
+                    .toString();
+        }
+
     }
 
 }