- 1 What is p2?
- 2 Accessing Repositories
- 3 Integration
- 3.1 How do I incorporate p2 into my RCP app?
- 3.2 Why aren't my dropins being picked up?
- 3.3 Why am I getting errors trying when access p2 services?
- 3.4 Why are my uninstalled bundles being reloaded!?
- 3.5 But why aren't uninstalled bundles/features immediately removed?
- 3.6 Why aren't bundles being removed when their associated feature has been removed?
- 4 Using p2 for Updating
- 5 Where can I learn more?
- 6 References
What is p2?
p2 is a provisioning platform for Eclipse-based applications. It replaces the older Update Manager as the mechanism for managing an Eclipse installation. Provisioning is the act of finding and installing new functionality, and updating or removing existing functionality; it is distinct from building.
p2 manages artifacts, such as bundles, features, and products; you can think of these as bags of bytes. p2 not only stores these artifacts, it also stores metadata about these artifacts, such as version information, cryptographic signatures, dependencies between artifacts, platform specifics, and special installation requirements.
Every p2 artifact is uniquely identified by an identifier and version number. For example, the Equinox OSGi container from the Indigo release is a bundle whose identifier is org.eclipse.osgi and version 3.7.0.v20110110. p2 assumes that two artifacts with the same identifier and same version number are the same artifact.
An artifact is made available to p2 by publishing the artifact to a repository, a process that also adds any metadata about the artifact. p2 comes with several publishers that know how to extract metadata for bundles, features, and products. Most Eclipse build systems (e.g., Tycho, Buckminister, PDE/Build) can automatically publish the artifacts during a build. Other publishers could be created using p2's APIs to handle other types of artifacts (e.g., Windows DLLs).
The p2 Director is responsible for installing a set of artifacts. The Director uses the metadata about an artifact, called an installable unit or IU, to determine how the artifact should be installed and to include any dependencies of those artifacts. Thus installing a product requires installing its associated features, which requires installing the specified bundles; installing the product also requires installing the platform-specific executable.
The Director is a wrapper around several lower-level p2 components. A Profile records the IUs installed. An Agent uses the Planner to determine the IUs to be managed, and uses the Engine to actually perform the sequence of installation steps. These installation steps are handled by touchpoints specific to each type of artifact.
See the p2 concepts guide for more details about these different terms.
Why won't p2 replace an updated bundle in a repository?
p2 assumes that two artifacts with the exact same identifier and version are the same artifact. Once an artifact has been published to a repository, it cannot be replaced. This restriction acts both as a performance optimization, to avoid unnecessary downloads, as well as a consistency check. For example, the Equinox OSGi container from the Indigo release is a bundle whose identifier is org.eclipse.osgi and version 3.7.0.v20110110. Any update to an artifact must be published with a new version number.
How can I find the features that include a particular bundle?
$ eclipse -console -noSplash -noExit -vmargs -Declipse.application.launchDefault=false osgi> provaddrepo http://download.eclipse.org/eclipse/updates/3.7-I-builds osgi> provlpquery * "select(parent | parent.properties['org.eclipse.equinox.p2.type.group'] == true && parent.requirements.exists(rc | everything.exists(iu | iu ~= rc && iu.id == 'BUNDLEID')))" true
For wildcards one may use:
osgi> provlpquery * "select(parent | parent.properties['org.eclipse.equinox.p2.type.group'] == true && parent.requirements.exists(rc | everything.exists(iu | iu ~= rc && iu.id ~= /*BUNDLEID*/)))" true
Credit to Paul Webster.
How do I incorporate p2 into my RCP app?
There are three approaches for integrating p2 into your app.
- The first approach, called the "User Interface API", is actually a framework for managing updates, complete with wizards and configurable scheduling. It is the same framework used by Eclipse's update management. Your application provides policies and other configuration values to guide this framework. Note that this API has a dependency on the Eclipse 3.x Platform UI (org.eclipse.ui), and requires the Platform UI compatibility layer for applications using the Eclipse 4 Application Platform.
- The second approach is to use p2's higher-level Operation APIs to drive updates. These APIs provide a thin layer over the Core APIs (described next) to describe updates as an atomic install, uninstall, or update of an artifact. are more intended for headless applications.
- The third and final approach, is to use p2's Core APIs, where you interact with the p2 agent directly. This is the most powerful, but also most complex, of the possible approaches. See the worked examples for all approaches in the article on "Equinox/p2/Adding Self-Update to an RCP Application", and the example applications.
Please note that we do not recommend that you invoke the p2 director from your application with a shell call (e.g., "app.exe -application org.eclipse.equinox.p2.director …")!
There is a fourth approach for integrating p2 into your app: using dropins. DBut dropins are not recommended, and has been officially deprecated by the p2 team.
Why aren't my dropins being picked up?
See the dropins debugging section for details on debugging dropins-related issues.
Why am I getting errors trying when access p2 services?
p2 relies on the OSGi Declarative Services feature. You must include and start the org.eclipse.equinox.ds bundle. Be sure to read the p2 Core API overview on how to access p2 services.
Why are my uninstalled bundles being reloaded!?
!ENTRY org.eclipse.update.configurator 4 0 2008-07-16 17:20:33.320 !MESSAGE Could not install bundle plugins/org.eclipse.compare_3.4.0.I20080604.jar Bundle "org.eclipse.compare" version "3.4.0.I20080604" has already been installed from: reference:file:plugins\org.eclipse.compare_3.4.0.I20080604.jar
Such messages are a symptom of the org.eclipse.update.configurator being installed. The org.eclipse.update.configurator causes all bundles in plugins to be installed into the runtime. To prevent this behaviour, set the org.eclipse.update.reconcile property to false for your product.
org.eclipse.update.configurator is included as part of the org.eclipse.rcp feature and cannot be removed for historical reasons.
But why aren't uninstalled bundles/features immediately removed?
p2 does not immediately remove bundles on uninstall for several reasons:
- Minimizing waste: By retaining the bundles, p2 can save time and bandwidth to should these bundles be re-installed.
- For safety: Many bundles do not properly support hot-swapping and removal. Writing bundles that can be uninstalled completely is surprisingly difficult, and even harder to test.
In practice the timing of deletion should not matter as p2 ensures that the bundles will not be re-installed (modulo the org.eclipse.update.configurator issue described elsewhere in this FAQ).
p2 does periodically perform a garbage collection of uninstalled features and bundles, typically after having performed another uninstall. See elsewhere in this FAQ for details on how to explicitly request a garbage collect.
Why aren't bundles being removed when their associated feature has been removed?
There are two aspects to this problem.
First, you should ensure that features are recorded when installing a feature by specifying the "org.eclipse.update.install.features=true" property, such that the bundles have a recorded dependency against the feature. This property is not the default, so if you are using the p2 director manually it is worth verifying.
Second, you must invoke the p2 garbage collector. By default, p2 only performs a garbage collect at its discretion. Normally this is fine since the actual bundles to be loaded are still known and managed (either in the config.ini file or by the simpleconfigurator).
You can cause a garbage collect in one of 3 ways:
- Configure your product to invoke a GC on startup by adding the following line to your product's plugin_customization.ini (requires the org.eclipse.equinox.p2.ui.sdk.scheduler bundle):
- Run the garbage collector application:
eclipse -application org.eclipse.equinox.p2.garbagecollector.application -profile SDKProfile
- Explicitly invoke the p2 garbage collection from code:
IProvisioningAgentProvider provider = // obtain the IProvisioningAgentProvider using OSGi services IProvisioningAgent agent = provider.createAgent(null); // null = location for running system if(agent == null) throw new RuntimeException("Location was not provisioned by p2"); IProfileRegistry profileRegistry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME); if (profileRegistry == null) throw new RuntimeException("Unable to acquire the profile registry service."); // can also use IProfileRegistry.SELF for the current profile IProfile profile = profileRegistry.getProfile("SDKProfile"); GarbageCollector gc = (GarbageCollector) agent.getService(GarbageCollector.SERVICE_NAME); gc.runGC(profile);
Using p2 for Updating
Why am I getting dependency satisfaction errors when I update my feature?
Deciphering a cryptic failure message like the following is a rite of passage on becoming a p2 expert:
Cannot complete the install because of a conflicting dependency. Software being installed: MyTool Feature 2.0.2 (com.mytool.feature 2.0.2) Software currently installed: MyTool Feature 2.0.3 (com.mytool.feature 2.0.3) Only one of the following can be installed at once: com.mytool.feature 2.0.3 com.mytool.feature 2.0.2 Cannot satisfy dependency: From: MyTool 2.0.2 (com.mytool.product 2.0.2) To: MyTool Feature (com.mytool.feature 2.0.2)
To understand and solve this message requires understanding several key concepts about p2.
When an IU (e.g., a product, feature, or bundle) is explicitly provisioned, the IU is recorded in the p2 profile as a root IU. A root IU will never be changed unless explicitly removed. When other IUs are installed or removed, p2's planner will attempt to find a configuration that will satisfy the other root IUs given their dependencies; if no configuration can be found, then the installation fails. The planner can generate an explanation, like the text above, to explain the constraints that failed.
Installations fail for two reasons.
The first reason is that many IUs are marked as singletons. Features, for example, are normally singletons, and thus two versions of the same feature cannot be installed at the same time. Although OSGi allows running multiple versions of a bundle, certain types of bundles, like an Eclipse plugin that contributes extensions to the extension registry, are marked as singleton: the extension registry does not support differentiating between multiple versions of a plugin and extension. Other IUs, like the Equinox platform launchers (org.eclipse.equinox.executables) are singletons as they actually correspond to files on disk (e.g., "eclipse.exe"). For example, if product two different IUs depend on two different versions of a single IU, the installation will fail.
The second reason is due to conflicting version requirements. p2 expresses dependencies between IUs using version ranges. But several of PDE's standard artifacts, such as products and features, historically specified their requirements using exact version numbers.
In the example above, product com.mytool.product 2.0.2, a singleton, requires exactly version 2.0.2 of com.mytool.feature. Because features are singletons, only one of com.mytool.feature 2.0.3 and 2.0.3 can be installed at once. And so the installation fails. The solution is to relax the com.mytool.product definition to allow a version range on the com.mytool.feature rather than an exact version using a p2.inf file.
To avoid installation failures:
- Specify the minimum set of IUs actually required. Let p2 satisfy the remaining dependencies.
- Decouple features based on API vs implementation dependencies. If your feature does not actually depend on the implementation of a particular version of a feature, then don't specify that requrement: instead ensure the features are required in a higher-level mechanism, like a product. Or specify such feature dependencies using the "Dependency" tab of the feature editor (akak imports). For example, in Eclipse Platform 4.2, the org.eclipse.rcp feature has an exact requirement on the org.eclipse.e4.rcp feature as there is an implementation dependency (i.e., org.eclipse.rcp 4.2 may not work with org.eclipse.e4.rcp 4.3), but org.eclipse.e4.rcp has an import dependency using a version range on two EMF features as it is an API dependency.
- Use p2.inf files where necessary to work around PDE artifacts that historically specify exact versions.
How can I determine what is a root IU?
You can see the items marked as a root by looking at the latest profile file in .../p2/org.eclipse.p2.engine/profileRegistry/<profileName>/ and looking for the string 'org.eclipse.equinox.p2.type.root'.
How can I tell if an IU is a singleton?
One way is to examine the content.xml for the containing repository, and find the IU's <unit>.
<unit id='org.junit.source' version='4.8.2.v4_8_2_v20110321-1705' singleton='false'> ... </unit>
IUs are considered singletons by default.
An excercise for a future reader: construct a p2 query to check the status of an IU in a repository.
Where can I learn more?
- The p2 wiki
- Pascal Rapicault has a number of presentations on various aspects of p2.
- Eclipse articles and tutorials tagged with p2
- Webinars tagged with p2