Hi Gerrit,
On 12/5/23, 1:20 AM, you wrote:
I have a device continuously sending data that I parse via StreamDevice
into the following records:
record (ai, "$(CHAN)_CT_03") {
field (DESC, "PM count greater 0.3µm")
field (INP, "@particulatematter.proto getCount($(U),$(CHAN)) $(CBPCT)")
record (ai, "$(CHAN)_CT_05") {
field (DESC, "PM count greater 0.5µm")
In the protocol, the first record is parsed directly, the others are
populated using record redirection
…
This all works fine except for one thing:
Sometimes I need to reset these channels, e.g., using caput on the
commandline. This works as expected for all channels except for the first
one that is using I/O Intr scanning. For this, caput is able to change the
value, a following caget reports the new value. However, camonitor does
not recognise the change. I do get the new value when restarting
camonitor, though. This also leads to the new value not being recognised by
As this works fine with all other records, it looks to me like the
scanning field (I/O Intr), maybe in combination with StreamDevice, is
causing my trouble here. Is this expected behaviour?
Yes, although it may not be well explained in the documentation, and some aspects might not be covered at all. I'm going to discuss the internals of the implementation here, feel free to ignore the code that I link to, but this behaviour
was intentional as I hope you'll see. It also various depending on the record type, not all VAL fields have the same attribute settings, for reasons that are usually specific to that record type.
Puts to the VAL field of a record get special handling by the code that actually modifies the field value, and that's almost always the dbPut() routine in module/database/src/ioc/db/dbAccess.c.
This part is particularly relevant to the behaviour you're asking about above. Puts to fields other than VAL will publish a CA monitor event (line 1390) so clients will be notified of the change at that point.
However, for a VAL field that has the PP attribute set that means the put operation should cause the record to be processed. That part happens in the routines which call dbPut() so it isn't done here, usually that would be on line 1273
in dbPutField(). When the record gets processed after dbPut() has written to the VAL field, the process() routine may modify the field again and then trigger its own CA monitor event if the value change merits it (related to MDEL/ADEL and some other mechanisms
which might squelch that). Thus in those cases we don’t want the dbPut() to send out a monitor since there may be another one along very soon if appropriate, and if it's not appropriate we'd want the monitor to be skipped anyway.
Now there's one more twist in your case: The record's SCAN field is set to "I/O Intr", and in that case the dbProcess() call on line 1273 will not be made because the PP attribute on the VAL field only makes the record process when it has
SCAN=Passive. All your other ai records fall into this case which is why you can reset those channels using a caput, but the I/O Intr record won't work like that. You already found the workaround for that in your next email, and this is the answer to your
later question about the documentation, when it talks about Passive records it does mean that the processing
only happens when SCAN=Passive. It doesn't mention other SCAN types and they don't get processed by the PP mechanisms.
Rolf Keitel's description thus applies to your later ai records, but not to the I/O Intr record itself. I believe there are only two ways that an I/O Intr record can get processed; by an interrupt from device support, or when something
puts a value to its PROC field. The latter can happen by many mechanisms though, e.g. DB link, CA link, CA client, PVA client, dbpf etc.
HTH,
- Andrew
Complexity comes for free, Simplicity you have to work for.