Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 207505

Summary: [registry] order in which registry events are sent vs. bundle dependencies
Product: [Eclipse Project] Equinox Reporter: Oleg Besedin <ob1.eclipse>
Component: CompendiumAssignee: Thomas Watson <tjwatson>
Status: RESOLVED FIXED QA Contact:
Severity: enhancement    
Priority: P3 CC: emoffatt, jeffmcaffer, matt_lavin, ob1.eclipse, pascal, sja.eclipse, tjwatson
Version: 3.4   
Target Milestone: 3.4 M4   
Hardware: PC   
OS: Windows XP   
Whiteboard:
Attachments:
Description Flags
patch
none
patch none

Description Oleg Besedin CLA 2007-10-25 15:56:50 EDT
The registry events are sent in the order bundle resolved events are coming from OSGi. 

However, consider this scenario:
Bundle A; extension point PointA
  Bundle B; extension ext1; bundle depends on Bundle A
    Bundle C; extension ext2; bundle depends on Bundle B

In this case the logical expectation would be to receive registry events in the order: PointA; ext1; ext2. However, the order in which they come seems to be undefined.

(The scenario supplied by Matt Lavin in the bug 206936, comment 14.)

There seem to be two possible solutions to this:

(A) modify OSGi to send events in the bundle dependency order
(B) modify registry processing to batch events so that the single event actually sent to listeners include PointA; ext1; ext2 regardless of the order of OSGi events.
(C) provide registry events with "start" and "end" bracketing notifications corresponding to BatchBundleListener (but note that this concept would make sense only to OSGi registry, not to generic registry)

To me, (A) seems to be least intrusive solution that would solve the actual problem. (C) might be an interesting "generic" solution but, ironically, it seems that in the scenario above quite a bit of extra code would have to be written. The (B), in my opinion, would be a rather risky thing to do considering how significantly it will change behavior for existing listeners.
Comment 1 Oleg Besedin CLA 2007-10-25 16:09:25 EDT
Some days I seriously wish were was an edit function in Bugzilla :-). 

For my comment on (C), I was trying to say that, ironically, quite a bit of extra code would have to be written by the user to properly handle the sample scenario even if (C) is implemented.

And, of course "two possible solutions" should read "three possible solutions". Things my spell checker misses... :-)

Comment 2 Thomas Watson CLA 2007-10-29 09:55:32 EDT
I discussed this with Oleg a bit last week and asked him to open this bug for discussion.

Ordering RESOLVED events by dependency order is not a big deal at the Framework level, but is not spec'ed by OSGi. Oleg is worried about batching the RESOLVED events and sending out all the registry changes in a single event all at the same time.  He thinks it will break compatibility of listeners.  Personally I think this is the best solution from both a performance and logical behavior point of view.  The registry events definitely allow for multiple sources to be delivered in the same event so I'm not convinced it will break listeners.  We should at least explore this option.  We always wanted to batch these events from way back in 3.0 but never made the effort.

This would allow the listeners to get the complete picture of the registry in one event after the complete resolution operation occurred (PackageAdmin refreshPackages/resolveBundles).  Currently the listeners are getting pieces of the complete picture as each UNRESOLVED/RESOLVED event is being fired by the Framework.  Here is what happens at the Framework level when refreshPackages is called.

1) The Framework sends out a batchBegin event to indicate a resolution operation is going to occur.
2) The Framework transitions all bundles in the set of bundles being "refreshed" to the INSTALLED state.
2) The Framework sends out UNRESOLVED events for the set of bundles being "refreshed".  The order of UNRESOLVED events is unspecified.
3) The resolver resolves all the bundles which are resolvable.
4) The Framework transitions all the newly resolved bundles into the RESOLVED state.
5) The Framework sends out RESOLVED events for the set of newly resolved bundles.  The order of RESOLVED events is unspecified.
6) The Framework sends out a batchEnd event to indicate the resolution operation has ended.

As you can see the Framework has already transitioned all the bundle states before it fires any events for the set of bundles which transitioned states.  So the extension registry is only getting part of the picture with each UNRESOLVED/RESOLVED event.  Not until the batchEnd event does the extension registry have the complete picture of the contribution state.  If we ordered the events by dependency order it would solve some of the problems but I still feel batching the bundle events until the complete picture is realized is the best approach for the extension registry to give an accurate picture to its listeners.
Comment 3 Thomas Watson CLA 2007-10-31 17:21:50 EDT
Created attachment 81786 [details]
patch

Looks like we already sort the bundles by dependency order during the refreshPackages/resolveBundles operations.  This is done so that we stop/resume the bundles in the correct order.  But we do not use this sorted list to send out the UNRESOLVED/RESOLVED events by dependency order.  This patch fixes this so that UNRESOLVED events are sent out in reverse dependency order and RESOLVED events are sent in dependency order.  It makes sense to me to make these event orders consistent with the stopping and resuming events that occur during resolution.
Comment 4 Jeff McAffer CLA 2007-11-01 16:20:11 EDT
quesiton would be do we want to spec this as API behaviour?  that is, would consumers be able to depend on the order being sorted?  Does that present an inhibitor to future optimizations etc?
Comment 5 Simon Archer CLA 2007-11-01 17:00:58 EDT
My 2 cents: I would vote for documenting the order in which events are dispatched, making the behavior API.  In my experience a framework that fires events in an undefined order results in overly complex event handling code.  In this particular case, the order of event dispatch clearly matters, so let's document it an make it something people can rely upon.
Comment 6 Thomas Watson CLA 2007-11-01 17:42:25 EDT
Jeff's question is, should this be make clear in the OSGi specification? I think.

To make it part of the spec we need to have a strong (hopefully general) use case for making the events occur in dependency order.  For simplicity reasons OSGi would likely want to spec the events to occur by bundle ID order, which IMHO is just as good as being random.

We had the same issue in the StartLevel specification.  In OSGi R4 the specification mandated that bundles within the same start-level would be activated by bundle ID order when their start-level was met and would be stopped in reverse bundle ID order when their start-level was not met.  This caused us issues in Eclipse on shutdown when bundles are not stopped by reverse dependency order.  If Bundle X depends on Bundle Y and Bundle Y is stopped before Bundle X then we could have issues when stopping Bundle X if it needs something from Bundle Y when stopping.

We argued to change the spec to mandate that bundles be started/stopped based on dependency order.  In the end, it was difficult to convince the OSGi crowd, which generally thinks start order should never be important, to mandate specific orders within the same start-level.  By OSGi R4.1 the specification was completely relaxed and it became up to the implementation to decide on the order bundles are started/stopped within the same start-level.  Equinox does it by dependency order.

Here I think the issue is a bit different because if you look at this from a resolver point of view then the bundles lower on the stack must be resolved before the bundles which depend on them higher up in the stack, otherwise the higher bundles could not be resolved.  One wrinkle is what to do about cycles, I think it is sufficient to leave bundles involved in cycles to have undetermined UNRESOLVED/RESOLVED event orders.

I opened OSGi bug https://www2.osgi.org/members/bugzilla/show_bug.cgi?id=575 to clarify the spec.  In the mean time I see no reason for us not to make the event order determinate for non-cyclic bundles.
Comment 7 Jeff McAffer CLA 2007-11-03 08:48:16 EDT
the reason to not do this is that people will become dependent on the order and thereby introducing a framework implementation dependency.

While I understand the scenario driving this I don't really see how it is different from say service registration.  If you are registering service A and it depends on service B then it has to be lazy about that dependency and listen for B to show up.  Bundle dependency order should not come into play.
Comment 8 Thomas Watson CLA 2007-11-05 09:24:47 EST
(In reply to comment #7)
I think bundle resolution is a bit different from service registration because a bundle cannot be in the RESOLVED state unless all of its required dependencies are satisfied first.  When X depends on Y it seems untruthful to inform a BundleListener that X got resolved before Bundle Y.  In reality a resolver is going to make sure Bundle Y can and is resolved before allowing Bundle X to resolve.  To me it makes sense to have the events reflect this.

But stepping back I still think batching the events in the service registry is the best solution for the problem at hand.  Not until the registry's BundleListener has received all resolved events does the registry have a complete picture of the resolution state.  Ordering events can help but will still be undefined for dependency cycles.  Also I think there are cases possible in the extension registry where dependency ordered events would be the incorrect order (See bug 206936 comment 11).

What a flip-flop I am :)

Bottom line, I think it makes sense to order UNRESOLVED/RESOLVED events by dependency order (when there are no cycles), but I think that only partially solves the registry events order issues.  If dependency ordered BundleEvents only partially solve the extension registry event order then maybe it is not worth changing at this point.  I'll see what OSGi CPEG thinks and report back.
Comment 9 Thomas Watson CLA 2007-11-15 17:49:49 EST
CPEG was not keen on spec'ing an ordering policy for RESOVLED/UNRESOLVED events, but it is not against the spec to order them by dependency order if we so choose.

The consensus was that for "transactional" type of operations, such as resolveBundles/refreshPackages, where a group of BundleEvents compose the operation a new type of listener could be defined to receive a list of events that occurred during the operation.  The extension registry would then implement this new kind of listener and would receive a single event with all the events that occurred.  At this point, the registry can send out regisrty events to registry listeners in what ever order it see fit.  If dependency order makes sense then the registry could order the events that way.

This obviously will not be spec'ed any time soon.  Next step in CPEG is to produce an RFP with the requirements for such a listener.  But in the mean time we could order our events at the framework level to get by in most cases.
Comment 10 Oleg Besedin CLA 2007-11-30 10:36:32 EST
+1 for the patch.
Comment 11 Thomas Watson CLA 2007-11-30 14:49:57 EST
Created attachment 84225 [details]
patch

Updated patch against HEAD.
Comment 12 Thomas Watson CLA 2007-11-30 14:51:18 EST
Patch released for 3.4 M4.
Comment 13 Eric Moffatt CLA 2007-12-04 14:47:32 EST
I was talking with Oleg this morning about needing -exactly- this type of depenency-based eventing. It's a fairly common scenario for UI Features to define their Commands/Handlers/KeyBindings in one plugin and their Menu contributions in another (which is dependent on the first).

This will save me -a lot- of work...thanks !

BTW, is the ordering only available through the new listener or does it also apply to 'legacy' listeners?
Comment 14 Thomas Watson CLA 2007-12-04 15:06:51 EST
(In reply to comment #13)
> BTW, is the ordering only available through the new listener or does it also
> apply to 'legacy' listeners?
> 

It should apply to both registry listener types.
Comment 15 Oleg Besedin CLA 2007-12-04 15:11:13 EST
The OSGi ordering is propagated to both new and old listeners.