Question about DeviceProxy initialization: is there a way to ignore ConnectionFailed?

Hi!

I have a question about DeviceProxy initial behaviour.

If DeviceProxy initial sequence fails for whatever reason, an exception is raised and the DeviceProxy object is NOT created.

However, this is unwanted behaviour for us, because the target server can be just temporarily unavailable (e.g., the client node had booted earlier than the server node).

Is it possible to tell DeviceProxy to treat ConnectionFailed as a temporary error and take care of it behind the scenes?
P.S. Tango is version 9.2.5a, Linux.

P.P.S. I have little experience with TANGO, but some experience with EPICS. And this problem simply don't exist there. Since TANGO is as mature as EPICS, I expected there is some solution, but neither googling nor reading the docs, tutorials and even .h files helped to find any. Now I just hope the problem is in my unfamiliarity with TANGO smile
Hi Bolkhov,

the DeviceProxy connection to the device server is implemented to be stateless. This means that even if there is a problem the connection will be maintained and as soon as the device is available it will be built automatically for the client i.e. behind the scenes. Of course as long as the device is not available any attempts to access it via the DeviceProxy will give an exception. The exception is to inform the client that there was an issue but the DeviceProxy should still be usable. Have you tried to catch the exception and continue using the DeviceProxy? Only in exceptional cases e.g. device has never been defined, database does not exist, will the DeviceProxy be unusable.

If you need to have the exception suppressed i.e you prefer not to catch it, can you please make a feature request so we include this in the list of things to do. Adding information about your use case and the urgency of your need will help us prioritise the implementing of it.

Cheers

Andy

p.s. you are right this not clearly explained in the documentation …
I did some more testing and in fact you should not get the ConnectionFailed when creating the DeviceProxy even if the device server is not running. Maybe you are trying to do some request to the device which is giving this error. In which case you need to know this and catch the exception.

Another possibility is you are trying to subscribe to events via the DeviceProxy before the device is available. In C++ and Python there is a "stateless" flag. Have you tried setting this to true?
Hi,

Just to confirm what Andy said, there are only few cases where the creation of a DeviceProxy class instance throw exception. Those that I remember are:
1 - The device name syntax is incorrect
2 - The device name is not defined in database

My two cents

Regards
Hi, Andy and Manu!

Thanks for your replies!

Here is a small test case:

——————————————
#include <stdio.h>
#include <tango.h>

static void report_exception(const char *caller, CORBA::Exception &e)
{
fprintf(stderr, "%s: exception, details follow:\n", caller);
fprintf(stderr, "——————–\n");
Tango::Except::print_exception(e);
fprintf(stderr, "——————–\n");
}

int main(int argc, char *argv[])
{
Tango::DeviceProxy *dev = NULL;

try
{
dev = new Tango::DeviceProxy("localhost:999/a/b/c");
}
catch (CORBA::Exception &e)
{
report_exception("new Tango::DeviceProxy", e);
fprintf(stderr, "dev=%p\n", dev);
exit(2);
}

printf("Success, dev=%p\n", dev);

return 0;
}
——————————————

The call to "new Tango::DeviceProxy()" immediately raises an exception:

——————————————
~% ./test_tango
new Tango::DeviceProxy: exception, details follow:
——————–
Tango exception
Severity = ERROR
Error reason = API_CorbaException
Desc : TRANSIENT CORBA system exception: TRANSIENT_ConnectFailed
Origin : Connection::connect

Tango exception
Severity = ERROR
Error reason = API_CantConnectToDatabase
Desc : Failed to connect to database on host localhost with port 999
Origin : Connection::connect

——————–
dev=(nil)
——————————————

Two things to note:

1. "localhost:999" port isn't listened (as if the server hadn't started yet). Replacing "localhost:999" with anything else changes little. If the address specified is on some switched-off host, then error is delayed for 6 seconds (and the error is "timeout").

2.
Andy
Have you tried to catch the exception and continue using the DeviceProxy?
Yes, I tried. But even if I catch the exception, I *can't* use the DeviceProxy, because it isn't created: since exception interrupts "operator new", no value is returned.
Edited 4 weeks ago
This is normal behaviour IF (1) there is no Tango database server listening at localhost:999, AND/OR (2) "a/b/c" is not the name of a device defined in the database.

I wonder if you have not confused the Tango database server address, specified by the environment variable TANGO_HOST or in /etc/tangorc or as you did i.e. as part of the name, with the device server network address? The device server network address is handled automatically by Tango. You only need the Database device server running. Common practice is to use ports 10000 or 20000 for the database server. But you are free to use 999 if it is free.

Have you tried the same code with the database server running at localhost:999 and a/b/c the name of a device defined in the database but not running in a device server.

Here is an example in python creating a DeviceProxy to a device ('sys/tg_test/1') which is defined but not running:

In [6]: dev = tango.DeviceProxy('sys/tg_test/1')

When I then try to ping() it I get ConnectionFailed - which is normal because ping() should report an error if it fails:

In [7]: dev.ping()
—————————————————————————
ConnectionFailed Traceback (most recent call last)
<ipython-input-7-b99eba764e11> in <module>
—-> 1 dev.ping()

C:\ProgramData\Anaconda3\lib\site-packages\tango\green.py in greener(obj, *args, **kwargs)
193 green_mode = access('green_mode', None)
194 executor = get_object_executor(obj, green_mode)
–> 195 return executor.run(fn, args, kwargs, wait=wait, timeout=timeout)
196
197 return greener

C:\ProgramData\Anaconda3\lib\site-packages\tango\green.py in run(self, fn, args, kwargs, wait, timeout)
107 # Sychronous (no delegation)
108 if not self.asynchronous or not self.in_executor_context():
–> 109 return fn(*args, **kwargs)
110 # Asynchronous delegation
111 accessor = self.delegate(fn, *args, **kwargs)

C:\ProgramData\Anaconda3\lib\site-packages\tango\device_proxy.py in __DeviceProxy__ping(self, *args, **kwargs)
1499
1500 def __DeviceProxy__ping(self, *args, **kwargs):
-> 1501 return self._ping(*args, **kwargs)
1502
1503

ConnectionFailed: DevFailed[
DevError[
desc = Device sys/tg_test/1 is not exported (hint: try starting the device server)
origin = DeviceProxy::get_corba_name()
reason = API_DeviceNotExported
severity = ERR]
Hi Andy,

What I'm coding is not a Tango application, but a plugin for another control system (for it to be able to access Tango directly).

So,

1. At this point it is irrelevant whether the unreachable address is of a DeviceServer or a DB server: what we need is to be unaffected by temporary network problems (the whole network with TANGO can be inaccessible at the time when our program starts).

2. If I try to connect to a DeviceServer directly, without a DB (by adding "#dbase=no" suffix), then libtango behaves as expected: the DeviceProxy object is successfully created and connection attempts are performed in background until DeviceServer starts and becomes accessible.

It looks like an error when connecting to a DB server is a fatal error, while an error connecting to a DeviceServer is treated as temporary. Is it right?

3.
Andy
Another possibility is you are trying to subscribe to events via the DeviceProxy before the device is available. In C++ and Python there is a "stateless" flag. Have you tried setting this to true?
Yes, that's the next step after DeviceProxy creation.
And "stateless=true" works as expected.

What I need is a similar flag for the whole DeviceProxy object.
 
Register or login to create to post a reply.