Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 330905 - Problem with persisting bundles state after install when eclipse.stateSaveDelayInterval is set to 0
Summary: Problem with persisting bundles state after install when eclipse.stateSaveDel...
Status: RESOLVED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: Framework (show other bugs)
Version: 3.6   Edit
Hardware: PC Windows Vista
: P3 minor (vote)
Target Milestone: 3.7 M4   Edit
Assignee: Thomas Watson CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2010-11-23 06:40 EST by Lazar Kirchev CLA
Modified: 2010-11-29 14:31 EST (History)
2 users (show)

See Also:


Attachments
Sample test bundle to reproduce the problem. (327 bytes, application/x-java-archive)
2010-11-23 06:40 EST, Lazar Kirchev CLA
no flags Details
patch (6.10 KB, patch)
2010-11-29 14:06 EST, Thomas Watson CLA
no flags Details | Diff
patch (6.12 KB, text/plain)
2010-11-29 14:29 EST, Thomas Watson CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Lazar Kirchev CLA 2010-11-23 06:40:07 EST
Created attachment 183658 [details]
Sample test bundle to reproduce the problem.

Steps to reproduce:

1. start Equinox with the property eclipse.stateSaveDelayInterval set to zero
2. install the attached test bundle 
3. exit with the exit command
4. start again Equinox and check that the ss command does not list the installed bundle

The same happens if, instead of exiting the framework, the JVM process in which runs the framework gets killed.

This problem reproduces in most cases, although sometimes the installed bundle is correctly persisted. I checked the code which installs a bundle and it seems that in this particular case of eclipse.stateSaveDelayInterval set to zero there is a bug. In Framework.installWorkerPrivileged(...) the persisting of data is performed in a call to BundleInstall.commit(...). It delegates to code in BaseStorage and finally the data for all bundles, which are in the list of installed bundles, is persisted. But the newly installed bundle is added to this list after the call to the commit() method, so when the bundles are persisted, it is not among them. This does not happen with the default value of eclipse.stateSaveDelayInterval (which is 30000 ms), because then a separate thread waits for this timeout, and during this time the newly installed bundle is added to the list of installed bundles. The persisting thread is started from BaseStorage's StateSeaver.requestSave(). Is there any reason why the new bundle is added to the list after the call to commit()?

Another strange thing is that in the state persisting logic (in requestSave()) first a check is made if  eclipse.stateSaveDelayInterval is zero. If it is zero, the state is persisted, and then the thread for persisting the state is started. If the property is not zero only the thread is started. Is it necessary to start a thread when the property is 0? In this case the state is persisted anyway.

The reason why the problem is not 100% reproducible is synchronization - when the property is 0 in most cases the code in the run() method of the thread is executed before the bundle is added to the list of bundles (it does not wait at all), but sometimes the adding happens first and then the thread saves it.

The reason for implementing delayed persisting with eclipse.stateSaveDelayInterval is to minimize the disk operations in case of lots of operations e.g. installs. But doesn't this delay violate the OSGi spec? According to the spec the installation of a bundle must be persistent – the bundle must remain installed across Framework and Java VM invocations until it is explicitly uninstalled. In the case of delayed persisting if during the wait interval the process, in which the framework runs gets killed for some reason, the newly installed bundles will not be persisted.
Comment 1 Thomas Watson CLA 2010-11-28 22:22:25 EST
Investigate for M4.
Comment 2 Thomas Watson CLA 2010-11-29 14:06:16 EST
Created attachment 184067 [details]
patch

Here is a patch that fixes the immediate issues.  There are two main issues.

1) StateSaver creates a background thread when eclipse.stateSaveDelayInterval=0.  This is not needed in that case.  I think this background thread may be what actually causes you to succeed in some cases.

2) The other issue is an ordering issue with the data structure not being updated properly before saving the state.  
 - We did not add the bundle to the bundles repo before requesting a save
 - We did not update the resolver state before requesting a save

 - I also noticed that we did not request a save on uninstall either which would cause similar issues with an uninstalled bundle not really being removed when restarting.

There is still an issue with disk usage when using eclipse.stateSaveDelayInterval=0 setting.  We never clean up old versions of the cache until we close the framework.  This leaves you with a very large set of generation files while running an instance that has lots of bundle lifecycle operations.  I opened bug331372 to track that issue.
Comment 3 Thomas Watson CLA 2010-11-29 14:29:58 EST
Created attachment 184069 [details]
patch

Last patch still had a bug in uninstall because the data being uninstalled was not being marked as dirty so the save request did not cause anything to actually be done.
Comment 4 Thomas Watson CLA 2010-11-29 14:31:48 EST
Patch released.