General questions regarding TANGO

Hi there,

While exercising with TANGO 8.1.2 (On Windows platform, mainly with PyTango and C++ API), some questions rose up.

Documentation (The TANGO Control System Manual Version 8.1):
  • At page 55 (4.6.5.2.1 Subscribing to events)
    • "The client implements […]. Note that this callback method will be executed by a thread started by the underlying ORB."
  • At page 56, just before (4.6.5.2.3 Unsubscribing from an event)
    • "In push model, there are some cases […] where the callback method could be executed concurrently by different threads started by the ORB".
  • Those 2 sentences seem to contradict with one another.
    • Does it mean that, on client side, there is a "thread pool" mechanism dealing with "push_event" callbacks or just one thread dealing with them?
    • While logging to find out, it seems there is only one thread dealing with "push_event" callbacks (logged thread id is always the same and different from main thread id)
  • At page 309 (9.3.1.1 Serialization model within a device server)
    • "1. Serialization by device. […]"
      • Can someone clarify?
      • POGO generates singleton device class but singleton is not thread safe. The "device_factory" method simply creates new instances of device implementation but there is no lock in POGO generated device implementation
      • Can someone explain how it works (thread wise, how does it work when a client connects to a device)?
Event handling thread(s) when a client subscribes to an event:
  • Is it possible not to execute callback at event subscription time?
  • in push mode, are the received events queued on client side as well?
    • If yes, is there a way to tune the retention mechanism (cf. buffer size in pull mode)?
      • Is it possible to increase queue size in case of long running push_event callbacks?
    • If no, what is the best practice? (cf. General best practices when dealing with events (at reception time) part)
  • The "EventData" structure only contains the device proxy source (the one pushing the event) but not the device proxy target (the one receiving the event).
    • It could be interesting to have such information in next release
    • Then, what is the best practice, inside a push_event, to call a device proxy target method? (cf. General best practices when dealing with events (at reception time) part)
  • Is it possible to push an event [ex. "push_change_event"] from a "push_event" callback?
General best practices when dealing with events (at reception time):
  • As I understand, the processing of a push_event callback should be as fast as possible to prevent dealing thread from timing out, losing connection, then reconnecting and so on.
    • Does that mean, within the push_event method, to delegate processing (ex.: on event reception, need to perform a big computation) to a user worker thread using a queue?
    • Is Yat4TANGO.DeviceTask a good candidate or simple user worker thread is enough?
    • Is there an equivalent of Yat4TANGO.DeviceTask implemented in PyTango?
  • Is it good practice to pass "this" to subscribe_event method as long as "this" implements "push_event" method?
  • Is it better to pass device name to callback class and perform a call to device using device proxy?
  • Some devices of same class, need to connect to a PostgreSQL database
    • Is it better to implement a PostgreSQL device, a bit like the TANGO database device?
      • Devices would connect to it at "init_device" time
    • Is it preferable that each device connects directly to the PostgreSQL database?
      • But then, how to share database connection? Should each device owns its database connection?
      • Connection string would a device class property
Log:
  • Is it possible, using PyTango logger, to change time format (ex.: "%Y-%m-%d %H:%M:%S.%f" with f: microseconds) so as to display milliseconds/microseconds in log?
  • In PyTango, how one can retrieve device impl logger to give it to inner classes?
  • Does LogAdapter exist in PyTango?

Thanks for your time.
Kind regards,
Cyrille.
Hi Cyrille,

I try to answer your pytango related questions below.

cgarino
  • Is there an equivalent of Yat4TANGO.DeviceTask implemented in PyTango?

Yes, we are in luck in python. The threading and multiprocessing modules that come with python provide similar functionality to what you have in yat4tango.
You can find across thread and across process objects like Queue, Event, Pipe, Pool of workers, etc.

cgarino
Log:
  • Is it possible, using PyTango logger, to change time format (ex.: "%Y-%m-%d %H:%M:%S.%f" with f: microseconds) so as to display milliseconds/microseconds in log?
  • In PyTango, how one can retrieve device impl logger to give it to inner classes?
  • Does LogAdapter exist in PyTango?

The PyTango interface to the Tango Logging system is very basic. I am afraid that the answer to all three questions is no. But this is mainly because nobody asked for it yet. There is no technical reason not to do it. I invite you to create a feature request in the tango source forge ticket system.

cgarino
Thanks for your time.
Kind regards,
Cyrille.
You are welcome.

Kind regards
Tiago
Edited 9 years ago
Hi Cyrille,

let me answer your question on "Serialization by device. […]" and client threads in the server:

(o) every client connecting to a device server creates its own thread. This enables multithreading of clients on the server side. It also enable high performance of the server because it can process multiple clients simultaneously on a multi-core system. However when accessing physical hardware e.g. a serial line, it is not always a good idea to allow multiple clients to have simultaneous access. This is why TANGO implements different sereialisation models - BY_DEVICE, BY_CLASS, BY_SERVER and NONE. These models use a mutex to serialise client access to be only ONE client executing per device, per device class and per process. The last serialisation model allows multiple client access without any serialisation at all. This is useful for device server who need very high multi-client performance and who are thread safe e.g. the database device server.

The documentation on threading in device servers is here:

http://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/ds_prog/node10.html#SECTION001030000000000000000

Hope that helps,

Kind regards

Andy
Hi Cyrille,

Is Yat4TANGO.DeviceTask a good candidate or simple user worker thread is enough?
Concerning your question about the yat4tango DeviceTask class, if you plan to handle Tango events in your Task, there’s an even better candidate: the yat4tango::EventsConsumerTask class. It’s just a specialization of DeviceTask with some “events consumer” features. It can optionally “auto setup” the event for the target attribute at registration (see yat4tango::SubscriptionAction::AUTO_CONFIGURE). Some hate that feature, some love it. Have a look to the provided “events_consumer_task” example (see. samples directory of the SVN trunk).

Is there an equivalent of Yat4TANGO.DeviceTask implemented in PyTango?
Both the DeviceTask and EventsConsumerTask are available for Python. It’s a pure Python implementation (i.e. doesn’t require the C++ yat4tango lib).

Does LogAdapter exist in PyTango?
I have a 'personal package' containing python implementation of the LogAdapter class.

I could cleanup my code in order to turn it into public release of what could be called pyYat4Tango.
Any interest?

Nicolas.
Edited 9 years ago
Hi Cyrille

Most of your questions have been answered already but not all of them:

- There is only ONE thread executing event callback on the client side. The sentences you noticed in the documentation were true
for Tango up to release 7 when the event system was the CORBA notification service. Now that we are using ZMQ, they are not
valid any more. We have to update this part of the doc. Good catch!
Note that in the ZMQ layer, thre is a bufferization of the incoming events in case of long running event callback. See doc chapter
A 9.3 and A 12.3.5
- It is not possible to not execute the event callback at subscription time. This is the way Tango manages the late joiner pb.
- In event push mode, the event queues are the ZMQ buffer (see first answer)
- In the EventData instance that you get when you receive one event, it is the DeviceProxy instance of the device on which the subscription has been done which is received (Not the source, the receiver device)
- I think it is possible to push events in one event callback

Hoping this help

Emmanuel
Thanks a lot for all these answers!

Cyrille.
 
Register or login to create to post a reply.