jackrabbit-oak-issues mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Jukka Zitting (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (OAK-1143) [scala] Repository init throws "illegal cyclic reference involving class ChangeDispatcher"
Date Mon, 04 Nov 2013 16:37:18 GMT

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

Jukka Zitting commented on OAK-1143:

So my basic idea was to change the {{Observer.contentChanged()}} method to:

     * Observes a content change. The implementation might for example
     * use this information to update caches, trigger JCR-level observation
     * events or otherwise record the change.
     * <p>
     * Content changes are observed for both commits made locally against
     * the repository instance to which the hook is registered and any
     * other changes committed by other repository instances in the same
     * cluster. Extra commit information in the {@link CommitInfo} argument
     * is available for local commits; for external changes the argument is
     * {@code null}.
     * <p>
     * Each observer instance is guaranteed a linear sequence of observations.
     * In other words this method will not be called concurrently from multiple
     * threads and successive calls to this method represent a logical sequence
     * of repository states, i.e. the root state passed to one call is guaranteed to
     * be a base state of the root state passed to the next call. The observer is
     * expected to keep track of the previously observed state if it wants to use
     * a content diff to determine what exactly changed between two states.
     * @param root root state of the repository
     * @param info local commit information, or {@code null}
    void contentChanged(NodeState root, CommitInfo info);

This should allow us to split the {{ChangeDispatcher}} functionality to a) the {{NodeStore}}-specific
bits that generates these callbacks based on the actual commits and updates from other parts
of the cluster, and b) an {{Observer}} implementation that uses event queues to decouple the
event producer from the registered event consumers. The a) part would essentially consist
of the {{beforeCommit}}, {{localCommit}}, {{afterCommit}} and {{externalCommit}} methods,
and the {{add}} method would be replaced by a call to the {{Observer}} of part b). That observer
would keep track of all registered normal observers, with an event queue and a dedicated listener
thread for each of them. On {{contentChanged()}} it would push a copy the observed change
to each of the event queues, and the listener threads would take care of duplicating that
{{contentChange}} call to each of the registered observers.

That way the NodeStore implementations would only need the part a) functionality (which could
well be inlined) and a single {{Observer}} reference (OAK-1131), thus breaking the dependency
to the more complex functionality now included in {{ChangeDispatcher}}. And since the composite
{{Observer}} from part b) is dependant on neither the {{NodeStore}} nor any higher level code
(it just deals with observers, event queues and background threads), we can inject it both
to the underlying {{NodeStore}} and to the observation managers in {{oak-jcr}}, thus eliminating
the need for {{ContentSessionImpl}} to be {{Observable}}.

With these changes in place, we would also be able to turn the {{ChangeProcessor}} class to
a normal {{Observer}}, attached to one of those event queues. This would make JCR observation
just one observer plugin among others, and would allow us to extend the rate-limiting / background
thread functionality to all observers. That in turn would for example allow us to turn the
asynchronous indexer mechanism to an observer instead of it having to explicitly poll the
repository for changes.

> [scala] Repository init throws "illegal cyclic reference involving class ChangeDispatcher"
> ------------------------------------------------------------------------------------------
>                 Key: OAK-1143
>                 URL: https://issues.apache.org/jira/browse/OAK-1143
>             Project: Jackrabbit Oak
>          Issue Type: Bug
>          Components: core
>            Reporter: Alex Parvulescu
>            Priority: Minor
> I've been playing with Oak on Scala a bit and it looks like the latest changes introduced
a problem that makes Oak unusable.
> Basically trying to setup a repo throws the following error:
> {noformat}
> OakRepository.scala:65: error: illegal cyclic reference involving class ChangeDispatcher
> [ERROR]     new Oak(new SegmentNodeStore(new FileStore(new File(fname), 268435456, true)))
> [ERROR]                 ^
> [ERROR] one error found
> {noformat}
> I've simplified the code down to the most basic barebone repo init to make it easier
to digest [0].
> This is a Scala bug, but my point is that this used to work prior to the changedispacher
changes, so I'm thinking we could move some bits around to get it working from Scala again.
> [0] https://github.com/alexparvulescu/soak/blob/master/src/main/scala/com/pfalabs/soak/OakRepository.scala#L65

This message was sent by Atlassian JIRA

View raw message