Hi Scott,
I'll try to explain what I'm seeing from start to fail.
I have a server that advertises two remote services. I have a client that discovers both of those services inside my discovery locator. When the two services are discovered, I see DiscoveredServiceTrackerImpl register just the first service because findProxyServiceRegistration() returns true for the second service. It's returning true because the two service endpoint descriptors are returning equals. RemoteServiceEndpoingDescriptionImpl.equals() returns true because serviceId.equals(other.serviceId) is returning true. The service id compare returns true because ServiceID.equals() compares the location and type which are both the same. Location is osgiservices://server_ip:9278 and type is ServiceTypeID[typeName=_osgiservices._tcp.default._iana]. I extended ServiceID in the same way as the JSLP provider:
package com.ibm.hdwb.util.common.service.discovery;
import java.net.URI;
import org.eclipse.ecf.core.identity.Namespace; import org.eclipse.ecf.discovery.identity.IServiceTypeID; import org.eclipse.ecf.discovery.identity.ServiceID;
public class HdwbDiscoveryServiceID extends ServiceID {
private static final long serialVersionUID = -5265675009221335638L;
protected HdwbDiscoveryServiceID(Namespace namespace, IServiceTypeID type, URI anUri) { super(namespace, type, anUri); } }
It seems to me that there are three possibilities:
1. location should be unique and it's not 2. type should be unique and it's not 3. I must override ServiceID.equals() and compare the values of the ecf.rsvc.id which I read from your last email as the way service id's are unique.
As an experiment, I changed my extension of ServiceID to overload equals() (see below) to compare the property values of ecf.rsvc.id and in doing so, the service ids are no longer equal which ripples up the chain causing findProxyServiceRegistration() to return false and the second service is now registered.
package com.ibm.hdwb.util.common.service.discovery;
import java.net.URI;
import org.eclipse.ecf.core.identity.Namespace; import org.eclipse.ecf.discovery.identity.IServiceTypeID; import org.eclipse.ecf.discovery.identity.ServiceID;
public class HdwbDiscoveryServiceID extends ServiceID {
private static final long serialVersionUID = -5265675009221335638L;
protected HdwbDiscoveryServiceID(Namespace namespace, IServiceTypeID type, URI anUri) { super(namespace, type, anUri); }
@Override public boolean equals(Object obj) { if(!super.equals(obj)) return false; else { ServiceID other = (ServiceID) obj; return other.getServiceInfo().getServiceProperties().getProperty("ecf.rsvc.id").equals(getServiceInfo().getServiceProperties().getProperty("ecf.rsvc.id")); } }
@Override public int hashCode() { return super.hashCode() + getServiceInfo().getServiceProperties().getProperty("ecf.rsvc.id").hashCode(); } }
Does this explination make sense? I think I understand the basics of discovery, but I do not have a good grasp of the whole service id / type / namespace classes.
Bryan
On Sep 14, 2009, at 4:24 PM, Scott Lewis wrote: Hi Bryan, Bryan Hunt wrote: Hi Scott,
As an experiment, I changed my service id class to overload equals to compare the value of the ecf.rsvc.id property, and now both services are being registered.
Open a bug?
Sure. I'm still not completely clear on where/what is exactly wrong with what's there...e.g. which service id class are you referring to being overridden...but yes a bug would be great/fine to track. Thanks, Scott
Bryan
On Sep 14, 2009, at 2:42 PM, Scott Lewis wrote:
Hi Bryan,
Bryan Hunt wrote:
Hi Scott,
What part of the service id should be unique? the URI? The URI is always osgiservices://ip_address
There should be a service property in the discovered serviceInfo with name org.eclipse.ecf.remoteservice.Constants.SERVICE_ID and value byte[] (which is the byte [] created via Long.toString().getBytes().
The value of this property should be set automatically in the method org.eclipse.ecf.internal.osgi.services.distribution.EventHookImpl.getServicePublicationProperties(IRemoteServiceContainer, ServiceReference, String[], IRemoteServiceRegistration) on line 182, the Long value is first looked up on the remoteServiceRegistration (the remote service id value should/is set when the container.registerRemoteService is called...i.e. internal to the container implementation.
Note that as specified by RFC119, when the distribution provider registers a ServicePublication service (to trigger the OSGi discovery), the RFC119 discovery impl handles the ServicePublication (starting on line 251 of org.eclipse.ecf.internal.osgi.services.discovery.ServicePublicationHandler.handleServicePublication(ServiceReference)) by putting the remote service id (as a byte[]) into the discoveryServiceProperties via a call to
discoveryServiceProperties.setPropertyBytes(Constants.SERVICE_ID,
remoteServiceIDAsBytes);
Perhaps it's possible that your discovery impl doesn't yet support setPropertyBytes (I'm just guessing here) and so the value is getting lost somehow?
Scott
Bryan
On Sep 14, 2009, at 1:42 PM, Scott Lewis wrote:
Hi Bryan,
Thanks, first of all, for the testing/debugging help.
Bryan Hunt wrote:
Thanks Scott!
I think I've tracked down the problem with services not getting registered. When the second service gets registered The DiscoveredServiceTrackerImpl calls findProxyServiceRegistration() with a SerivceEndpointDescriptor for the service to be registered. Inside the for loop, it gets the RemoteServiceregistration reg = to the registration from the first registered service, and when it calls if(sed.equals(reg.getServiceEndpointDescription()) that evaluates to true which causes the function to return true and the service is not registered. It loggs the error "... previously registered locally...ignoring" Look like a bug?
I'm not yet sure. Obviously the sed.equals(reg.getServiceEndpointDescription()) should return false...and I believe this equals test is actually implemented via this method:
org.eclipse.ecf.internal.osgi.services.discovery.RemoteServiceEndpointDescriptionImpl.equals
which should check for equality of *both* the remote services location (i.e. the endpoint URI) *and* the remote service id. For your use case, the locations of the two registered services should be the same (i.e. they are from the same endpoint I assume), but the remote service ids *should be* different.
If you can debug into this code with your use case I would like to understand why this equals is returning true.
If you agree this is a bug, any chance of getting it fixed for 3.0.1? I think I can live with the duplicate service registrations, but this one is a blocker.
We only have a day or two more where we can make updates for 3.0.1, so I'm not sure whether we'll be able to identify the issue and fix quickly enough. I certainly want to, but we have to follow the build/deployment schedule described on http://wiki.eclipse.org/Galileo
Thanks...please let me know and I'll do all I can.
Thanks,
Scott
Bryan
On Sep 14, 2009, at 9:40 AM, Scott Lewis wrote:
Hi Bryan,
I've opened this bug for r-OSGi on this issue https://bugs.eclipse.org/bugs/show_bug.cgi?id=289356
If Jan or Markus can't get to it right away, I will deal with it (i.e. before ECF 3.1).
Scott
--Boundary_(ID_kYW4jSWp30xfDCs4f0EKkw)
Content-type: text/plain; charset=us-ascii; format=flowed; delsp=yes
Content-transfer-encoding: 7BIT
I'm having some problems with RFC119. I'm using R-OSGi as the remote service provider, and my own discovery provider. My server is registering two remote services with the discovery provider. I see the client locator find both of the services. One of the services is being registered twice, and the other not at all. I've debugged the duplicate registration a bit and see that the service gets registered when the DiscoveredServiceTrackerImpl gets the IRemoteService, and again when it actually registers the service. I'm thinking this is a bug. Screenshots of the stack traces are below. I'll try to work on why the second service is not being registered at all tomorrow.
Bryan
|