[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [ecf-dev] connections/threads are not cleaned up after failing importService call

Hi again,

the workaround described below does not work in all circumstances.

The problem still seems to be that remote services can only be successfully registered if the client uses the exact same hostname for the endpoint ID as used by the server itself. Otherwise the containerID's in org.eclipse.ecf.remoteservice.RemoteServiceID.namespaceEquals(BaseID) does not match and the service registration fails (I'm not sure if there are additional other places where the hostname matters while service import/export).

The problem for me is, that the "local" hostname where the service is provided is not always the network visibly name the clients need to use to connect to the server.

Is there a way to make the remote services work then the client (service consumer) and the server (service provider) use different hostnames for the server?

I'm using ecf generic server.

Thanks for any hints!

Bye Peter

Am 18.09.2017 um 16:22 schrieb Peter Hermsdorf:

After some further debugging I was able to workaround the described problem by making the connection to the virtual machine work regardless of the used hostname in the endpoint description.

I used some constant value for ENDPOINT_ID and used RemoteConstants.ENDPOINT_CONNECTTARGET_ID to define the "real network" target/host to connect to:

props.put(RemoteConstants.ENDPOINT_CONNECTTARGET_ID, "ecftcp://" + host + ":8889/server");
props.put(ENDPOINT_ID, "p4://server");

So no more hostname matching to identify the correct service on the target machine.

But the original problem still remains unresolved ...

Bye, Peter

Am 18.09.2017 um 14:24 schrieb Peter Hermsdorf:

Hi Scott,

thanks for your suggestion, but the described fix does not seem to work. The returned container is always null and so cannot be disconnected. This is caused by the importEndpoint of the importReference being null.

This is what I'm doing:

1) register my remote service and a reconnect listener for that service:

ÂÂÂ ÂÂÂ final ImportRegistration registration = remoteServiceAdmin.importService(endpointDescription);

ÂÂÂ ÂÂÂ final ReconnectServiceAdminListener reconnectListener = new ReconnectServiceAdminListener(remoteServiceAdmin,
ÂÂÂ ÂÂÂ ÂÂÂ ÂÂÂ containerManager,
ÂÂÂ ÂÂÂ ÂÂÂ ÂÂÂ registration, endpointDescription);
ÂÂÂ ÂÂÂ context.registerService(RemoteServiceAdminListener.class.getName(), reconnectListener, null);

2) inside the ReconnectListener I basically try to re-import the service when the registration/connection fails:

public class ReconnectServiceAdminListener implements RemoteServiceAdminListener {

ÂÂÂ private static final Duration RECONNECT_DELAY = Duration.ofSeconds(10);

ÂÂÂ private final ReconnectJob reconnectJob;
ÂÂÂ private final EndpointDescription endpointDescription;
ÂÂÂ private final RemoteServiceAdmin remoteServiceAdmin;
ÂÂÂ private ImportRegistration registration;

ÂÂÂ private final IContainerManager containerManager;

ÂÂÂ public ReconnectServiceAdminListener(final RemoteServiceAdmin remoteServiceAdmin,
ÂÂÂ ÂÂÂ ÂÂÂ final IContainerManager containerManager, final ImportRegistration registration,
ÂÂÂ ÂÂÂ ÂÂÂ final EndpointDescription endpointDescription) {
ÂÂÂ ÂÂÂ this.remoteServiceAdmin = remoteServiceAdmin;
ÂÂÂ ÂÂÂ this.containerManager = containerManager;
ÂÂÂ ÂÂÂ this.registration = registration;
ÂÂÂ ÂÂÂ this.endpointDescription = endpointDescription;
ÂÂÂ ÂÂÂ reconnectJob = new ReconnectJob();
ÂÂÂ ÂÂÂ if (registration.getException() != null) {
ÂÂÂ ÂÂÂ ÂÂÂ reconnectJob.schedule(RECONNECT_DELAY.toMillis());

ÂÂÂ @Override
ÂÂÂ public void remoteAdminEvent(final RemoteServiceAdminEvent e) {
ÂÂÂ ÂÂÂ final org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.RemoteServiceAdminEvent event = (org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.RemoteServiceAdminEvent) e;
ÂÂÂ ÂÂÂ if (event.getEndpointDescription().isSameService(endpointDescription)) {
ÂÂÂ ÂÂÂ ÂÂÂ switch (event.getType()) {
ÂÂÂ ÂÂÂ ÂÂÂ ÂÂÂ case RemoteServiceAdminEvent.IMPORT_ERROR:
ÂÂÂ ÂÂÂ ÂÂÂ ÂÂÂ ÂÂÂ reconnectJob.schedule(RECONNECT_DELAY.toMillis());

ÂÂÂ class ReconnectJob extends Job {

ÂÂÂ ÂÂÂ public ReconnectJob() {
ÂÂÂ ÂÂÂ ÂÂÂ super("ReconnectJob");

ÂÂÂ ÂÂÂ @Override
ÂÂÂ ÂÂÂ protected IStatus run(final IProgressMonitor monitor) {

ÂÂÂ ÂÂÂ ÂÂÂ final org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.ImportRegistration remoteServiceImportRegistration = (org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.ImportRegistration) registration;
ÂÂÂ ÂÂÂ ÂÂÂ final ID containerID = remoteServiceImportRegistration.getContainerID();
ÂÂÂ ÂÂÂ ÂÂÂ final IContainer container = containerManager.getContainer(containerID);
ÂÂÂ ÂÂÂ ÂÂÂ if (container != null) {
ÂÂÂ ÂÂÂ ÂÂÂ ÂÂÂ container.disconnect();

ÂÂÂ ÂÂÂ ÂÂÂ registration.close();
ÂÂÂ ÂÂÂ ÂÂÂ registration = remoteServiceAdmin.importService(endpointDescription);
ÂÂÂ ÂÂÂ ÂÂÂ return Status.OK_STATUS;


The Thread count still increases with every run of the ReconnectJob.

Any suggestions on how to solve this issue?

Bye Peter

Am 16.09.2017 um 05:03 schrieb Scott Lewis:
Hi Peter,

I'm assuming that you are using the generic provider.

I think you can do what you need to do by:

1) You can cast the ImportRegistration to org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.ImportRegistration
2) Call org.eclipse.ecf.osgi.services.remoteserviceadmin.RemoteServiceAdmin.ImportRegistration.getContainerID() to get the container ID
3) Using the IContainerManager service (a singleton ecf service) and the ID from 2 call:ÂÂ IContainer c = containerManager.getContainer(id) to get the associated container instance.
4) Call c.disconnect() to release the connection and associated threads.


On 9/15/2017 7:27 AM, Peter Hermsdorf wrote:

we encountered a problem while trying to import services exported from a process running in a local VM (_not_ JVM). The VM forwards the necessary port to the host machine.

As for the problem: RemoteAdminService#importService causes a RemoteAdminServiceEvent.IMPORT_ERROR to be signalled and the connections/threads opened due to the importService call do not get closed, even though we call ImportRegistration#close() on failed attempts. The latter does not happen, if there is no one listening on the port at all. Since, we have code that regularly calls importService again for services, that should be, but are not currently imported (according to RemoteAdminService#getImportedEndpoints), we slowly accumulate more and more threads.

The tcp connection to the local VM seems to be successful, but due to issues regarding requested hostname and actual hostname ECF (correctly) does not "connect the services" (see https://dev.eclipse.org/mhonarc/lists//ecf-dev/msg07259.html for a discussion of the "hostname problem - localhost != getCanonicalHostname()" in EndPointDescriptions; in this case it is host::getCanonicalHostname() != VM::getCanonicalHostname())

So importService creates threads/connections, fails to import, and even with a call to ImportRegistration#close() does not clean up the threads/connections.

Any suggestions on how to solve this issue or more generally handle this reconnect use-case are more than welcome!

Best regards,

Bye Peter

PS: we use the ecf generic provider on the latest ecf release