Author: mreutegg
Date: Wed Aug 24 04:36:26 2005
New Revision: 239609
URL: http://svn.apache.org/viewcvs?rev=239609&view=rev
Log:
Move preparation of events out of write lock to prevent possible deadlock situations.
Modified:
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventConsumer.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventState.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventConsumer.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventConsumer.java?rev=239609&r1=239608&r2=239609&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventConsumer.java
(original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventConsumer.java
Wed Aug 24 04:36:26 2005
@@ -20,6 +20,7 @@
import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.core.PropertyId;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.state.ItemState;
import org.apache.jackrabbit.core.security.AccessManager;
import org.apache.log4j.Logger;
@@ -29,11 +30,11 @@
import javax.jcr.observation.EventIterator;
import javax.jcr.observation.EventListener;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.WeakHashMap;
/**
* The <code>EventConsumer</code> class combines the {@link
@@ -66,11 +67,11 @@
private final EventFilter filter;
/**
- * A map of <code>Set</code> objects that hold references to denied
- * <code>EventState</code>s. The map uses the <code>EventStateCollection</code>
- * as the key to reference a deny Set.
+ * A map of <code>Set</code> objects that hold references to
+ * <code>ItemId</code>s of denied <code>ItemState</code>s. The
map uses the
+ * <code>EventStateCollection</code> as the key to reference a deny Set.
*/
- private final Map accessDenied = Collections.synchronizedMap(new HashMap());
+ private final Map accessDenied = Collections.synchronizedMap(new WeakHashMap());
/**
* cached hash code value
@@ -165,7 +166,7 @@
if (denied == null) {
denied = new HashSet();
}
- denied.add(state);
+ denied.add(state.getId());
}
}
}
@@ -175,12 +176,43 @@
}
/**
+ * Checks for which deleted <code>ItemStates</code> this
+ * <code>EventConsumer</code> has enough access rights to see the event.
+ *
+ * @param events the collection of {@link EventState}s.
+ * @param deletedItems Iterator of deleted <code>ItemState</code>s.
+ */
+ void prepareDeleted(EventStateCollection events, Iterator deletedItems) {
+ Set denied = null;
+ while (deletedItems.hasNext()) {
+ ItemState item = (ItemState) deletedItems.next();
+ // check read permission
+ boolean granted = false;
+ try {
+ granted = session.getAccessManager().isGranted(item.getId(), AccessManager.READ);
+ } catch (RepositoryException e) {
+ log.warn("Unable to check access rights for item: " + item.getId());
+ }
+ if (!granted) {
+ if (denied == null) {
+ denied = new HashSet();
+ }
+ denied.add(item.getId());
+ }
+ }
+ if (denied != null) {
+ accessDenied.put(events, denied);
+ }
+ }
+
+ /**
* Dispatches the events to the <code>EventListener</code>.
*
* @param events a collection of {@link EventState}s
* to dispatch.
*/
void consumeEvents(EventStateCollection events) throws RepositoryException {
+ // Set of ItemIds of denied ItemStates
Set denied = (Set) accessDenied.remove(events);
// check permissions
for (Iterator it = events.iterator(); it.hasNext();) {
@@ -200,7 +232,7 @@
if (denied == null) {
denied = new HashSet();
}
- denied.add(state);
+ denied.add(state.getId());
}
}
}
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventState.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventState.java?rev=239609&r1=239608&r2=239609&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventState.java
(original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventState.java
Wed Aug 24 04:36:26 2005
@@ -17,6 +17,9 @@
package org.apache.jackrabbit.core.observation;
import org.apache.jackrabbit.core.nodetype.NodeTypeImpl;
+import org.apache.jackrabbit.core.ItemId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.core.NodeId;
import org.apache.jackrabbit.name.Path;
import javax.jcr.Session;
@@ -331,6 +334,21 @@
*/
Session getSession() {
return session;
+ }
+
+ /**
+ * Returns the id of the associated item of this <code>EventState</code>.
+ *
+ * @return the <code>ItemId</code>.
+ */
+ ItemId getId() {
+ if (childUUID == null) {
+ // property event
+ return new PropertyId(parentUUID, childRelPath.getName());
+ } else {
+ // node event
+ return new NodeId(childUUID);
+ }
}
/**
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java?rev=239609&r1=239608&r2=239609&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
(original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/EventStateCollection.java
Wed Aug 24 04:36:26 2005
@@ -45,6 +45,16 @@
* The <code>EventStateCollection</code> class implements how {@link EventState}
* objects are created based on the {@link org.apache.jackrabbit.core.state.ItemState}s
* passed to the {@link #createEventStates} method.
+ * <p/>
+ * The basic sequence of method calls is:
+ * <ul>
+ * <li>{@link #createEventStates} or {@link #addAll} to create or add event
+ * states to the collection</li>
+ * <li>{@link #prepare} or {@link #prepareDeleted} to prepare the events. If
+ * this step is omitted, EventListeners might see events of deleted item
+ * they are not allowed to see.</li>
+ * <li>{@link #dispatch()} to dispatch the events to the EventListeners.</li>
+ * </ul>
*/
public final class EventStateCollection {
@@ -343,10 +353,19 @@
}
/**
- * Prepares the events for dispatching.
+ * Prepares already added events for dispatching.
*/
public void prepare() {
dispatcher.prepareEvents(this);
+ }
+
+ /**
+ * Prepares deleted items from <code>changes</code>.
+ *
+ * @param changes the changes to prepare.
+ */
+ public void prepareDeleted(ChangeLog changes) {
+ dispatcher.prepareDeleted(this, changes);
}
/**
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java?rev=239609&r1=239608&r2=239609&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java
(original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/FilteredEventIterator.java
Wed Aug 24 04:36:26 2005
@@ -45,6 +45,9 @@
*/
private final EventFilter filter;
+ /**
+ * Set of <code>ItemId</code>s of denied <code>ItemState</code>s.
+ */
private final Set denied;
/**
@@ -63,9 +66,9 @@
* @param c an unmodifiable Collection of {@link javax.jcr.observation.Event}s.
* @param filter only event that pass the filter will be dispatched to the
* event listener.
- * @param denied <code>Set</code> of denied <code>EventState</code>s
+ * @param denied <code>Set</code> of <code>ItemId</code>s of
denied <code>ItemState</code>s
* rejected by the <code>AccessManager</code>. If
- * <code>null</code> no <code>EventState</code>
is denied.
+ * <code>null</code> no <code>ItemState</code>
is denied.
*/
public FilteredEventIterator(EventStateCollection c,
EventFilter filter,
@@ -151,11 +154,9 @@
while (next == null && actualEvents.hasNext()) {
state = (EventState) actualEvents.next();
// check denied set
- if (denied == null || !denied.contains(state)) {
+ if (denied == null || !denied.contains(state.getId())) {
try {
- next = filter.blocks(state) ? null : new EventImpl(filter.getSession(),
- /* filter.getItemManager(), */
- state);
+ next = filter.blocks(state) ? null : new EventImpl(filter.getSession(),
state);
} catch (RepositoryException e) {
log.error("Exception while applying filter.", e);
}
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java?rev=239609&r1=239608&r2=239609&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
(original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/observation/ObservationManagerFactory.java
Wed Aug 24 04:36:26 2005
@@ -21,6 +21,7 @@
import org.apache.commons.collections.buffer.UnboundedFifoBuffer;
import org.apache.jackrabbit.core.ItemManager;
import org.apache.jackrabbit.core.SessionImpl;
+import org.apache.jackrabbit.core.state.ChangeLog;
import org.apache.log4j.Logger;
import java.util.Collections;
@@ -182,6 +183,22 @@
for (Iterator it = consumers.iterator(); it.hasNext();) {
EventConsumer c = (EventConsumer) it.next();
c.prepareEvents(events);
+ }
+ }
+
+ /**
+ * Prepares changes that involve deleted item states.
+ *
+ * @param events the event state collection.
+ * @param changes the changes.
+ */
+ void prepareDeleted(EventStateCollection events, ChangeLog changes) {
+ Set consumers = new HashSet();
+ consumers.addAll(getSynchronousConsumers());
+ consumers.addAll(getAsynchronousConsumers());
+ for (Iterator it = consumers.iterator(); it.hasNext();) {
+ EventConsumer c = (EventConsumer) it.next();
+ c.prepareDeleted(events, changes.deletedStates());
}
}
Modified: incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java?rev=239609&r1=239608&r2=239609&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
(original)
+++ incubator/jackrabbit/trunk/core/src/java/org/apache/jackrabbit/core/state/SharedItemStateManager.java
Wed Aug 24 04:36:26 2005
@@ -333,6 +333,12 @@
// todo: remember by provider
ArrayList virtualRefs = new ArrayList();
+ EventStateCollection events = null;
+ if (obsMgr != null) {
+ events = obsMgr.createEventStateCollection();
+ events.prepareDeleted(local);
+ }
+
acquireWriteLock();
boolean holdingWriteLock = true;
@@ -366,7 +372,6 @@
}
}
- EventStateCollection events = null;
boolean succeeded = false;
try {
@@ -404,11 +409,9 @@
shared.added(state.getOverlayedState());
}
- /* prepare the events */
- if (obsMgr != null) {
- events = obsMgr.createEventStateCollection();
+ /* create event states */
+ if (events != null) {
events.createEventStates(root.getUUID(), local, this);
- events.prepare();
}
/* Push all changes from the local items to the shared items */
|