Experimental Physics and Industrial Control System
Hi Giacomo,
On 09/05/2017 10:01 AM, Giacomo S. wrote:
> So, summing up, suppose to recreate this scenario:
>
> - application starts
> --> client requests monitoring of pv1 = foo:ai1
>
> - (first request, so) ca_context_create(ca_enable_preemptive_callback)
>
> - ca_create_channel (...)
>
> - (in connection_handler invoked from EPICS foo thread: )
> ca_create_subscription(...)
A note: You are allowed to subscribe to channels using a different
request data type than their native type, and the IOC will do its best
to convert the data for you. I don't completely understand how your
connection_handler() method transforms the native type, but I just
wanted to make that point for later on...
> [ monitors for a while, receive event callbacks from EPICS foo thread]
>
> --> client requests pv2 = foo:ai2
>
> - ca_create_channel (...)
>
> - (in connection_handler invoked from EPICS foo thread: )
> ca_create_subscription(...)
>
>
> ---> network goes down
>
> - (in pv1 connection callback invoked from EPICS foo thread:) 1.
> ca_clear_subscription() BUT NOT ca_clear_channel()
Here's where Michael and I have slightly differing opinions: I wouldn't
necessarily clear the subscription when the connection goes down,
especially if I'm not relying on the native data type of the channel to
select what type I subscribe with. CA will remember the original
subscription and will reconnect it to the IOC when it comes back. In
connection_handler() you were already storing the fact that you have
already subscribed, so that code wouldn't create multiple subscriptions.
One issue that you do have to be careful of though is if an IOC gets
rebooted with a modified database so the data type of a channel you were
subscribed to changes between the connection going down and coming back
up. In this case CA subscriptions will reconnect using the type in their
original subscription request, which might now be different to the
native type of the channel. The client code has to be aware of that and
use the type information from the data update callback.
Michael's approach of clearing subscriptions at disconnect is probably
safer, but requires the application code to do a bit more work, as
evidenced by the additional calls to ca_create_subscription() below. The
difference is really a matter of opinion.
> - (in pv2 connection callback invoked from EPICS foo thread:) 1.
> ca_clear_subscription() BUT NOT ca_clear_channel()
>
> ---> network UP again
>
>
> - (in pv1 connection callback invoked from EPICS foo thread:) 1.
> ca_create_subscription()
>
> - (in pv2 connection callback invoked from EPICS foo thread:) 1.
> ca_create_subscription()
>
> ---> client requests pv3 = bar:ai3
>
> - ca_create_channel (...)
>
> - (in connection_handler invoked from EPICS >>> bar <<< thread: )
> ca_create_subscription(...) <--- bar THREAD <----
>
> [ receive event callbacks from 2 threads: foo for pv1 and pv2, bar for
> pv3 ]
>
> ---> client wants to disconnect everything (or application shutdown)
>
> - foreach pv: // is this
> safe to be called from the thread that initially called the ca_create*
> counterparts???
You can call any ca routine from any thread that has been attached to
the context, so yes.
> * ca_clear_subscription();
> * ca_clear_channel();
>
> - ca_context_destroy(); // from same
> thread where ca_context_create() was called
>
>
> Is the above correct? Am I somewhere wrong?
It looks like you understand it pretty well.
> Some more simpler questions:
>
> 1. every time I receive an event, evargs contain not only the value /
> timestamp but also configuration parameters, right (HI, LO thresholds
> and so on...)
Not sure what the question is there. Your event_handler_cb() routine is
given a struct event_handler_args whose void *dbr pointer points to the
dbr_* type that you subscribed to. There are many different dbr_* data
types defined in db_access.h containing different subsets of the
available data, but none of them provides everything, so you may need to
subscribe to the same channel multiple times with different types and
different event masks. Channel metadata (enum strings, alarm levels etc)
usually change much less frequently than the data itself, and the event
mask DBE_PROPERTY is designed to tell you when metadata has changed.
> 2. are there utility functions to extract the value and timestamp from
> the evargs and easily convert them into the correct type (short,
> double, int...)
There are some macros in db_access.h that can help, e.g. dbr_value_ptr
if you limit the number of types you subscribe to you can avoid having
to write code that understands all the dbr_* types.
> 3. If I monitor a PV, is it possible to know from the args if it's a
> vector (and its dimension) or a scalar?
Yes, the struct event_handler_args contains the data type, chid and
element count for the data contained in this update (look in cadef.h for
its definition). count==1 means it's a scalar.
> 4. where can I find the explanation of this: Lo disp limit, hi disp
> limit, Lo alarm limit.... ?
Those metadata fields are supplied from fields of the record, disp =
display, so a graph of the channel data over time should expect to use
the low display limit for the bottom of the y axis and the high display
limit for the top. Alarm limits tell you if the PV generates alarms what
data values would trigger those alarms, so you could put a marker on the
axis if you chose to do so.
> 5. How to extract the timestamp of the event (as far as I've seen from
> the code, there must be a timestamp from the server and one from the
> client. In this case, what does the client side timestamp mean. Is it
> the timestamp when the event is received on the client itself?)
You appear to be looking at code from catools, which added the idea of
providing a client-side timestamp as well as or instead of the timestamp
from the IOC itself. I think it just provides the client's idea of the
time when the CA library called its callback; this isn't part of the CA
client library itself.
> Is there a good tutorial for a quick start and the answers to my
> questions 1 to 5?
> I mean a quick start to understand how to program a client in C (C++).
Maybe not at the level of detail you're asking, I think you've probably
gone beyond what most CA client tutorials covered, but you could browse
the EPICS Training links to see if there are any that help:
http://www.aps.anl.gov/epics/docs/training.php
> One final thing: I've seen a set of C++ libraries (pvaClientCPP,
> pvCommonCPP) and in general the
>
> "EPICS V4 C++ module"
>
> but it looks like it's not up to date with the latest EPICS release.
>
> Is this the "official" C++ Epics module?
>
> Is it normal that it trails the last EPICS version?
Those modules are part of the newer EPICS V4 network protocol
implementation, which are designed to supplement and eventually replace
the CA protocol. That's a completely different topic and the APIs are
completely different, I suggest you ignore them for now.
HTH,
- Andrew
--
Arguing for surveillance because you have nothing to hide is no
different than making the claim, "I don't care about freedom of
speech because I have nothing to say." -- Edward Snowdon
- Replies:
- Re: C++ multi threaded application. Giacomo S.
- Re: C++ multi threaded application. Giacomo S.
- References:
- C++ multi threaded application. Giacomo S.
- Re: C++ multi threaded application. Andrew Johnson
- Re: C++ multi threaded application. Giacomo S.
- Re: C++ multi threaded application. Giacomo S.
- Navigate by Date:
- Prev:
Re: C++ multi threaded application. Giacomo S.
- Next:
Re: Archiver: Problems with disconnected PVs Shankar, Murali
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
<2017>
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: C++ multi threaded application. Giacomo S.
- Next:
Re: C++ multi threaded application. Giacomo S.
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
<2017>
2018
2019
2020
2021
2022
2023
2024