Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 135885 - Standardize and enhance lazy-start
Summary: Standardize and enhance lazy-start
Status: RESOLVED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: Framework (show other bugs)
Version: 3.2   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: 3.3 M4   Edit
Assignee: equinox.framework-inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 161329
  Show dependency tree
 
Reported: 2006-04-10 10:16 EDT by Thomas Watson CLA
Modified: 2007-01-02 17:29 EST (History)
9 users (show)

See Also:


Attachments
patch (15.69 KB, patch)
2006-06-07 17:12 EDT, Thomas Watson CLA
no flags Details | Diff
patch (16.07 KB, patch)
2006-06-14 15:58 EDT, Thomas Watson CLA
no flags Details | Diff
patch (54.86 KB, patch)
2006-09-05 17:32 EDT, Thomas Watson CLA
no flags Details | Diff
patch (56.35 KB, patch)
2006-09-12 12:08 EDT, Thomas Watson CLA
no flags Details | Diff
patch (62.91 KB, patch)
2006-10-18 16:40 EDT, Thomas Watson CLA
no flags Details | Diff
patch (63.61 KB, patch)
2006-10-19 13:31 EDT, Thomas Watson CLA
no flags Details | Diff
patch (52.68 KB, patch)
2006-10-19 21:34 EDT, Thomas Watson CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Watson CLA 2006-04-10 10:16:12 EDT
Comments from BJ Hargrave on the equinox-dev mailing list

At EclipseCon we were brainstorming ways to get Declarative Services registered for bundles which were not started. While there are many details to work out, the basic idea was for the framework to mark lazy start bundles in 
the STARTING state rather than just the RESOLVED state. This would 

(a) allow them to still avoid having a class loader and 
(b) allow SCR to register their declarative services since they are technically started. 

More thinking is needed here though. These bundles would stay in the 
STARTING state until a class was loaded from them. This could occur for 
any reason including SCR trying to load the implementation class for a 
declarative service once it was used by some other bundle. This would 
allow bundles to be installed and provide service without having to be 
explicitly started. I think this is something interesting to pursue for 
3.3.
Comment 1 Thomas Watson CLA 2006-04-10 10:16:36 EDT
This should be investigated for 3.3.
Comment 2 Pascal Rapicault CLA 2006-04-10 11:55:13 EDT
Why can't a registry like a model be used?
Comment 3 BJ Hargrave CLA 2006-04-10 13:35:49 EDT
(In reply to comment #2)
> Why can't a registry like a model be used?
> 

I think you need to say more here, as I don't get what you are asking. :-)
Comment 4 Jeff McAffer CLA 2006-04-10 15:39:45 EDT
I think it is becuaes the bundles need to actually be progressing from RESOLVED to STARTING to have a bundle context and the bundle context is needed to register the services and keep the OSGi service model happy.
Comment 5 Neil Bartlett CLA 2006-04-11 04:48:45 EDT
As far as I can tell, the SCR only needs the BundleContext for an unstarted service so that it can register a ServiceFactory for the services declared in the component descriptor.

Is it not possible to construct some kind of delegating or proxy BundleContext that would allow this usage only? When the bundle actually starts, the proxy could be replaced with a "real" BundleContext.

I'm not saying that there's anything wrong with this proposal, but it would be confusing. You can imagine the support calls... "my bundles are hanging in STARTING state!" etc.
Comment 6 BJ Hargrave CLA 2006-04-11 09:07:06 EDT
(In reply to comment #5)
It is important however to maintain "apperances". That is, only started bundles can register services and services appear to come from the bundle which register them.

SCR could use its own BundleContext to register the service factory surrogates, but then when the system was introspected, all services would come from SCR :-(.

This issue is really about how to make lazy start and SCR work well together while maintaining apperances.
Comment 7 BJ Hargrave CLA 2006-05-02 16:25:17 EDT
For SCR, the proposed change is only necessary if the bundle has both Eclipse-LazyStart: true and a Service-Component header. (Although this is somewhat special casing things).

However, if OSGi adds some means to externally obtain a bundle's BundleContext (see bug 108214), then the proposed change could be more generally useful (even if there is no Service-Component header).
Comment 8 Thomas Watson CLA 2006-06-07 17:12:24 EDT
Created attachment 43799 [details]
patch

This patch is a first attempt at changing lazy-start bundles such that they enter the STARTING state as soon as their start level has been reached and they are resolved.  

Note that a bundle does not automatically attempt to enter the STARTING state unless it is already RESOLVED.  This gives agents some control in preventing a bundle from entering the STARTING state until they cause the bundle to be resolved.  It also prevents the resolver from being run each startup when unresolvable bundles are installed.

This patch includes two new methods on AbstractBundle to start and stop a bundle without persistently marking the start state of the bundle.  This allowed for the implementation of lazy start to be simplified a bit.  These two methods may be interesting to propose back to OSGi:

Bundle#start(boolean persistent)
Bundle#stop(boolean persistent)

The two methods are identical to the no argument Bundle#start and Bundle#stop methods except the bundle is not marked for persistent start or stop if persistent==false.  This would be a useful method for normal bundles that would like to start another bundle but would like for it to only be started for the running session of the framework (regardless if the bundle is lazy-start or not).  Similarly, another bundle may want to stop a bundle only for the running session of the framework but would like it to be restarted on next startup.

Here is an outline of the proposed new behavior of lazy-start bundles
1)  When the start-level of a lazy-start bundle is reached then we attempt to enter the STARTING state.
2)  If the bundle is UNINSTALLED do nothing; otherwise continue to next step
3)  If the bundle is INSTALLED (not resolved) do nothing; otherwise continue to the next step.  We do not want to automatically force a resolution here
4)  Set the bundle state to STARTING and publish a STARTING BundleEvent
5)  return now; do not create BundleContext or attempt to load and start the activator.  This will leave the bundle in the STARTING state.

After a lazy-start bundle has entered the STARTING state then there are two ways the bundle could be started 1) a class is loaded from it, this is the typical lazy-start scenario 2) The bundle is explicitly started.

In both cases the BundleEvent.STARTING event is NOT published again and the BundleContext is created and the activator is started.  The only difference between the two is if the bundle is explicitly started then it will be marked for start on the next session of the framework.

There are some details that need to be considered when a bundle is updated/refreshed.

When updating a bundle the bundle enters the INSTALLED state.  For lazy-start bundles which were in the STARTING state should we force a resolution to the bundle so that it may enter the STARTING state again?  The current patch will keep the bundle in the INSTALLED state, you must force a resolve yourself to get it back to the STARTING state.  This seems to be consistent with the install case where we force the agent to resolve the bundle before it can enter the STARTING state.

When refreshing a bundle (using PackageAdmin) the resolver currently agressively resolves the bundles.  When refreshing a lazy-start bundle in the STARTING state this will allow it to enter the STARTING state immediately.  Is this desired?  I'm not sure how to prevent this behavior without changing the resolver to not be agressive.

The method AbstractBundle.getContext (used by SCR) has been changed to create the context if it is not already created and the bundle is either STARTING or ACTIVE.  This should allow the SCR implementation to create BundleContext objects for lazy-start bundle on demand.
Comment 9 Thomas Watson CLA 2006-06-14 15:58:26 EDT
Created attachment 44445 [details]
patch

Updated patch to fix small bug when uninstalling a bundle.  This uninstalling was not properly transitioning the bundle state from STARTING -> UNINSTALLED.
Comment 10 Thomas Watson CLA 2006-09-05 17:32:59 EDT
Created attachment 49441 [details]
patch

Lots of rework.  This patch incorporates many changes which are being considered in an RFC that specs the lazy-start behavior.

Most of the changes are around the following:
- what happens when a lazy-start bundle fails to start
- what happens when a lazy-start bundle is explicitly stopped
- what happens when the start-level is changed.
- what BundleEvents are published for lazy-start bundles
Comment 11 Simon Archer CLA 2006-09-06 07:45:06 EDT
The OSGi R4 spec states in section 4.3.2:

  "STARTING - The bundle is being started, the BundleActivator.start method
  has been called, and the start method has not yet returned."

I'm sure your intentions are good, but I worry that leaving a bundle in the STARTING state will both confuse developers (because they'll believe that their bundle's "start method has not yet returned"), and will disagree with the spec.

If you feel that this is necessary, maybe a change to the OSGi spec needs to be proposed for R5.
Comment 12 Thomas Watson CLA 2006-09-06 09:17:30 EDT
(In reply to comment #11)
> The OSGi R4 spec states in section 4.3.2:
>   "STARTING - The bundle is being started, the BundleActivator.start method
>   has been called, and the start method has not yet returned."
> I'm sure your intentions are good, but I worry that leaving a bundle in the
> STARTING state will both confuse developers (because they'll believe that their
> bundle's "start method has not yet returned"), and will disagree with the spec.
> If you feel that this is necessary, maybe a change to the OSGi spec needs to be
> proposed for R5.

We are working with OSGi to make changes to the future specification of OSGi.  When I get more time (hopefully in the next week or so) I will post a detailed design on the Equinox wiki that we are proposing back to OSGi.
Comment 13 BJ Hargrave CLA 2006-09-06 09:49:12 EDT
(In reply to comment #11)
> The OSGi R4 spec states in section 4.3.2:
> 
>   "STARTING - The bundle is being started, the BundleActivator.start method
>   has been called, and the start method has not yet returned."
> 

I am working with Tom on this idea. I think we just need to modify the wording here to indicate that the start method has not necessarily been called. In fact that wording is somewhat wrong anyway since there is a window between setting the bundle's state to STARTING and actually calling the start method. We are just proposing expanding that window :-)
Comment 14 Thomas Watson CLA 2006-09-06 18:08:57 EDT
See Equinox WIKI http://wiki.eclipse.org/index.php/Lazy_Start_Bundles for a description of the lazy-start design.

This is an early draft that will  change much before the final design is agreed upon.
Comment 15 Thomas Watson CLA 2006-09-12 12:08:30 EDT
Created attachment 49947 [details]
patch

latest patch with a few fixes.  This patch also includes a suggested workaround to recover from ClassCircularityErrors when starting a lazy-bundle.
Comment 16 Thomas Watson CLA 2006-10-18 16:40:31 EDT
Created attachment 52268 [details]
patch

latest patch against head.

Adds better error report handling for CNFE's.
Comment 17 Thomas Watson CLA 2006-10-19 13:31:41 EDT
Created attachment 52330 [details]
patch

- bug fix for classes with a dependency chain.  The previous patch was not activating bundles correctly in this case.

During rather long discussion with others in OSGi we came to the following desicions with respect to lazy-start

1) Resource loads will not cause a bundle to be lazy-started

2) A failed attempt to activate a lazy-start bundle will not result in a ClassNotFoundeException or NoClassDefFoundError.  Instead the class will be allowed to return but an error will be recorded (logged etc.)

This approach may cause us some issues, it basically means code that depends on its own bundle to be activated will fail late instead of failing early at classload time.

3) If a lazy-start bundle fails to start then it will enter the RESOLVED state and no more attempts will be made to start the bundle unless it is refreshed

4) The start-level service will be loosened to allow bundles within the same start-level to be shutdown in an order the framework sees fit.  We could not come to a consensus that this order MUST be by dependency order (like it currently is in Equinox).  For now Equinox will implement it by dependency order.

I will be prototyping these latest decisions and updating the design doc posted at the WIKI soon (at http://bundles.osgi.org/Design/LazyStart).  Look for another patch hopefully in the next few days ...
Comment 18 Thomas Watson CLA 2006-10-19 21:34:47 EDT
Created attachment 52363 [details]
patch

Incorporates latest design changes:
- Do not throw class loading errors when a lazy-start bundle cannot start
- Do not attempt to restart failed lazy-start bundle.
- When a lazy-start bundle has a class loaded from it and its start-level is not met then it must be started when/if its start-level is met later

More fixes for activation order when there are class dependency chains and cycles between bundles.
Comment 19 Thomas Watson CLA 2006-11-07 12:56:29 EST
Changing title to reflect the work being done in this bug.  See an updated wiki at http://bundles.osgi.org/Design/LazyStart for an updated design.

I will release the latest prototype of this design today.  I will also send a note to the dev mailing list explaining the changes to the community.  The new lazy-start design fixes a very old ClassCircularityError bug 5875.  To fix this we introduced a concept of a "trigger class" (read the wiki for more information).

The reason I bring this up here is because this design changes the way bundles are lazy activated in a subtle way.  In Eclipse today bundles are lazy-activated before the first class is even searched for within the bundle.  When a class is loaded with a chain of dependencies then we activate bundles as we walk down the chain of dependencies.  If we have a Class hierarchy X->Y->Z with classes X, Y, and Z coming from different bundles then we end up activating the bundles in the order of X, Y, Z.  This approach leaves us open to the ClassCircularityError in bug 5875 because we may activate a bundle while defining the class (when defining a class all classes in its heirarchy are also loaded, these classes may be in other bundles).

Running activation code while defining a class must be avoided.  To do this the new lazy-start design does not activate any bundles until the "trigger class" is completely defined.  Then we activate bundles from the bottom up.  So in the above case the activation order would be Z, Y, X.
Comment 20 Thomas Watson CLA 2006-11-07 13:43:47 EST
Released latest prototype to HEAD along with new tests to org.eclipse.osgi.tests.  I tagged both projects before I released with "before_bug135885" and after I released I tagged both projects with "after_bug135885".