[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[p2-dev] Service ranking and p2's IAgentServiceFactory.

p2-dev's,

I've been tracking down a problem that has to do with upgrades of our product
and I've been left scratching my head.

My immediate question is:

Does the default IProvisioningAgent honour service.ranking when looking for UIServices?

Problem Background
==================

In our product we have a custom authentication dialog that we 
use for authentication when a customer connects to our private p2 repo.

We use the org.eclipse.equinox.p2.core.UIServices service to register our own
implementation of an org.eclipse.equinox.p2.core.spi.IAgentServiceFactory.
When registering the service we set the service.ranking to 255 to ensure that
our service is selected above the default.

e.g.
~~~
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0"; name="com.codesourcery.portal.ide.PortalServiceUIComponent">
	<property name="service.ranking" type="Integer">255</property>
	<implementation class="com.codesourcery.portal.ide.PortalServiceUIComponent"/>
	<service>
		<provide interface="org.eclipse.equinox.p2.core.spi.IAgentServiceFactory"/>
	</service>
	<property name="p2.agent.servicename" type="String" value="org.eclipse.equinox.p2.core.UIServices"/>
</scr:component>
~~~

In a normal install of our product the service we install works just fine.

However, after an upgrade the default service and default authentication 
dialog start being used.

This is because:

(a) The bundle ID order is different. After the upgrade we are at a lower
    bundle ID e.g.

osgi> ss
...
127     ACTIVE      org.eclipse.equinox.p2.core_2.1.0.v20110502-1955
...
316     <<LAZY>>    com.codesourcery.portal.ide_1.0.0.376509
...

(b) The code in the default ProvisioningAgent uses an OSGi API that doesn't 
    take into account the service.ranking.

org.eclipse.equinox.p2.core/src/org/eclipse/equinox/internal/p2/core/ProvisioningAgent.java
...
			//attempt to get factory service from service registry
			Collection<ServiceReference<IAgentServiceFactory>> refs;
			try {
				refs = context.getServiceReferences(IAgentServiceFactory.class, "(" + IAgentServiceFactory.PROP_CREATED_SERVICE_NAME + '=' + serviceName + ')'); //$NON-NLS-1$
			} catch (InvalidSyntaxException e) {
				e.printStackTrace();
				return null;
			}
			if (refs == null || refs.isEmpty())
				return null;
			ServiceReference<IAgentServiceFactory> firstRef = refs.iterator().next();
...

The call to getServiceReferences returns 2 services, the default and ours.

However refs.iterator().next() returns the first service, ignoring the service.ranking,
and using the default, which is not correct for our situation.

What's the solution to this problem?

Should p2 be using an iterator that takes into account the service.ranking?

Should I have done something to make my bundle start first?
- I'm pretty sure this is a not kosher since bundle start level should not be used
  to control service start order since services might come and go at any point.

Should I implement my own provisioning agent that does the right thing?
- This seems like a lot of work for an OSGi-based services solution which should
  be using service ranking.

Our product is shipping with 3.7.1 but I've looked at the code in git trunk
and it's the same.

Did I miss anything?

Notes:
* Of relevance is this discussion in 2010-02-02:
http://dev.eclipse.org/mhonarc/lists/p2-dev/msg02670.html
Unfortunately John doesn't directly comment on Meng's point about:
"... But the implementation of IProvisioningAgent simply uses the first 
factory instance in its querying result..."

Cheers,
Carlos.
-- 
Carlos O'Donell
Mentor Graphics / CodeSourcery
carlos_odonell@xxxxxxxxxx
carlos@xxxxxxxxxxxxxxxx
+1 (613) 963 1026