[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] Race conditions with remote provider

Hi Alex,

On 6/6/2011 3:12 PM, Alex Blewitt wrote:
<stuff deleted>
Well, I'm not using r-osgi to write a discovery provider. I'm writing a discovery provider, and I'm then using R-OSGi to talk between two VMs. So I'm pretty much using the r-{osgi,zookeeper} example product, except ^zookeeper^myContainer.


<stuff deleted>
So I had something like (excuse the exact method calls, this is from memory):

class Activator {
   void start() {
     id = IDFactory.getDefault().createId(namespace, new String[] { "a","b","c" });
     myContainer = new MyContainer();
     context.registerService(myContainer, {IDiscoveryListener, IDiscoveryAdvertiser});

The problem was that the ID Factory was using the namespace (either from the plugin.xml where I have some links, or from a service I may have registered prior to that call ... think the plugin.xml is how it's finding it) and using bundle.getClass() to load the namespace's specific class provider.

Since the start() method hasn't completed at that point, an external bundle doing bundle.loadClass(some.class.name) fails with some OSGi 'bundle not started' type exception.
I see. Markus Kuppe is the lead committer on the discovery API, so I'll defer to him...but one approach you might take is to create a ServiceFactory (rather than registering the locator/advertiser service directly in the start method). This will defer the container creation and the call to IDFactory.getDefault() (the IDFactory...and the container factory for that matter...defer the processing of the appropriate extensions until the *first* time that IDFactory.getDefault() is called).
Right, I see. Somewhat like registering a service factory instead of registering a service. I still need to plug in some data at ID creation tme though.

Yeah, I think I understand. You should still be able to pass the ID creation data unique to your discovery into a ServiceFactory...if you wish.

                        jdc = new JMDNSDiscoveryContainer();   //<-- the jmdns id is created in this constructor
                        jdc.connect(null, null);
This creates the JMDNS' ID, true. But I need to pass in an ID in the jdc.connect(id,null) instead of a 'null' - because it can be configured with different properties.

Yeah, I see. I think it would still be possible to explicitly create the ID of appropriate type in the ServiceFactory...and pass in any args...if you wish.

<stuff deleted>

That way, I can delay any time between the discovery provider setup and the (first) listener being registered. Hooray!

Hooray indeed!

On the plus side, I've now got a much better idea of how the discovery stuff hangs together. I think there's also a lot of opportunity to make an abstract container to make it easier to provide discovery containers in the future. Quite a lot of the specific provider calls boil down to 'make this available' and 'tell me when a service arrives'. But there's a lot of glue code (turning ServiceProperties into a Map<String,String>, managing the set of services, standard implementations of notifying when services come and go etc.)

Have you consulted the AbstractDiscoveryContainerAdapter class in org.eclipse.ecf.discovery? i.e:


Several of the existing discovery providers extend this abstract superclass, in order to have a common impl of discovery behavior.

I'll have a go sometime at putting up a proof of concept on GitHub when I get a chance.

That would be terrific, thanks. If you like we can either add it to the ECF github repo at: http://github.com/ECF or we can/could add it as a contribution to the EF git repo. Your choice of course.