[ 
https://issues.apache.org/jira/browse/OAK-1368?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14077565#comment-14077565
 ] 

Michael Dürig commented on OAK-1368:
------------------------------------

Implementing this turns out to be more tricky than initially thought:

* To use the current pull based implementation would mean we'd need a way to 
co-iterate over the event iterators from within a single thread. Not something 
we can reasonably do without language support for continuations. 

* An alternative implementation (which I POCed locally) does solve the problem 
of concurrently accessing session related entities. It does not show much of a 
performance gain though. The implementation does a diff per session and uses a 
linked blocking queue per event listener. Once the queue becomes full, the 
diffing would block until the respective listener has caught up. Due to this 
running the producer and the consumer side of the queues on the same thread 
pool is prone to deadlocking. Using different thread pools, there is still a 
big potential of dead lock on consumer threads if they run off a bounded thread 
pool with fewer threads than there are queues unless we implement some form of 
work stealing, which again becomes quite complex given Java's library support. 
Another problem with running multiple listeners off the same diff is avoiding 
to receive events from the past. I.e. once a new listener has been registered 
there might still be earlier diffs pending. Solving this involves hacking the 
{{BackgroundObserver}} to support call back being placed into the queue of 
pending revisions and using those to do the actual registering. 

Given this cannot be fixed by improving the current implementation but rather 
needs a new implementation, which most likely suffers from its own 
idiosyncrasies, I'd rather stick with the current implementation and 
concentrate on improving it where necessary:

* Keep an eye on the possible lock contention on the name path mapper. This 
hasn't come up so far. However should we happen to see this we could implement 
a snapshot mechanism where each listener would have its own snapshot copy of 
the current name path mapper. The snapshot mechanism could take advantage of 
the fact the change in name space mappings are rare. 

* Pass a dedicated and correctly refreshed instance of a permission provider to 
each listener and keep an eye on the performance impact.

* Improve event filter support so consumers can be more specific on what events 
they want to receive (e.g. OAK-1978).

* If doing a separate diff for each listener turns out to be too expensive, we 
could try to keep the results of diffs resulting in only in a few events in 
memory: a first diff would run against a composite handler of all handles 
attached to bounded queues. All queues that didn't overflow during that first 
diff would be sent of to the associated event handlers. For the remaining 
queues an extra diff would be run each. Such an approach would result in just a 
single diff for all listeners if all of them have sufficiently strict filters 
such that the number of events is lower than the size of the queue. 

I'll file separate issues for above bullet points as they come up. 

> Only one Observer per session
> -----------------------------
>
>                 Key: OAK-1368
>                 URL: https://issues.apache.org/jira/browse/OAK-1368
>             Project: Jackrabbit Oak
>          Issue Type: Improvement
>          Components: jcr
>            Reporter: Jukka Zitting
>            Assignee: Michael Dürig
>            Priority: Critical
>              Labels: observation
>             Fix For: 1.1, 1.0.4
>
>
> As mentioned in OAK-1332, a case where a single session registers multiple 
> observation listeners can be troublesome if events are delivered concurrently 
> to all of those listeners, since in such a case the {{NamePathMapper}} and 
> other session internals will likely suffer from lock contention.
> A good way to avoid this would be to have all the listeners registered within 
> a single session be tied to a single {{Observer}} and thus processed 
> sequentially.
> Doing so would also improve performance as the listeners could leverage the 
> same content diff. As the listeners come from a single session and thus 
> presumably from a single client, there's no need to worry about one client 
> blocking the work of another.



--
This message was sent by Atlassian JIRA
(v6.2#6252)

Reply via email to