Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "Equinox/p2/FAQ"

< Equinox‎ | p2
(On diagnosing and avoiding installation failures)
(Update GC code snippet)
Line 74: Line 74:
 
* Configure your product to invoke a GC on startup by adding the following line to your product's <tt>plugin_customization.ini</tt> (requires the <tt>org.eclipse.equinox.p2.ui.sdk.scheduler</tt> bundle):
 
* Configure your product to invoke a GC on startup by adding the following line to your product's <tt>plugin_customization.ini</tt> (requires the <tt>org.eclipse.equinox.p2.ui.sdk.scheduler</tt> bundle):
 
   <pre>org.eclipse.equinox.p2.ui.sdk.scheduler/gcOnStartup=true</pre>
 
   <pre>org.eclipse.equinox.p2.ui.sdk.scheduler/gcOnStartup=true</pre>
* Run the garbage collector application:<ref>http://www.eclipse.org/forums/index.php?t=msg&amp;amp;amp;amp;goto=543500</ref>  
+
* Run the garbage collector application:<ref>http://www.eclipse.org/forums/index.php?t=msg&amp;goto=543500</ref>  
 
   <pre>eclipse -application org.eclipse.equinox.p2.garbagecollector.application -profile SDKProfile</pre>
 
   <pre>eclipse -application org.eclipse.equinox.p2.garbagecollector.application -profile SDKProfile</pre>
 
* Explicitly invoke the p2 garbage collection from code:
 
* Explicitly invoke the p2 garbage collection from code:
<pre>IProfileRegistry profileRegistry = (IProfileRegistry) ServiceHelper.getService(Activator.getContext(), IProfileRegistry.class.getName());
+
<pre>
if (profileRegistry == null)
+
IProvisioningAgentProvider provider = // obtain the IProvisioningAgentProvider using OSGi services
throw new RuntimeException("Unable to acquire the profile registry service.");
+
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
 
// can also use IProfileRegistry.SELF for the current profile
 
IProfile profile = profileRegistry.getProfile("SDKProfile");
 
IProfile profile = profileRegistry.getProfile("SDKProfile");
new GarbageCollector().runGC(profile);
+
GarbageCollector gc = (GarbageCollector) agent.getService(GarbageCollector.SERVICE_NAME);
 +
gc.runGC(profile);
 
</pre>
 
</pre>
  

Revision as of 11:40, 20 March 2012

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.

Accessing Repositories

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?

Using the p2 Query Language from the OSGi console, substitute the appropriate repository URL and BUNDLEID:

$ 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.

Integration

How do I incorporate p2 into my RCP app?

There are three approaches for integrating p2 into your app.

  1. 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.
  2. 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.
  3. 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.

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.[1] 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):
org.eclipse.equinox.p2.ui.sdk.scheduler/gcOnStartup=true
  • Run the garbage collector application:[2]
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.[3]

To avoid installation failures:

  1. Specify the minimum set of IUs actually required. Let p2 satisfy the remaining dependencies.
  2. 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.
  3. Use p2.inf files where necessary to work around PDE artifacts that historically specify exact versions.[4]


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

References

  1. http://dev.eclipse.org/mhonarc/lists/p2-dev/msg00905.html
  2. http://www.eclipse.org/forums/index.php?t=msg&goto=543500
  3. http://aniefer.blogspot.com/2009/07/composing-and-updating-custom-eclipse.html
  4. http://aniefer.blogspot.com/2009/07/composing-and-updating-custom-eclipse.html

Back to the top