Hi Érico,
I don’t know the compress record internals terribly well, but it sounds like the reset behavior you’re seeing isn’t ideal. Changing record functionality to make it more sensible is something that we can do, although we try to be careful
to not break IOCs that might rely on the existing behavior so any changes must be documented.
The compressRecord.c file only ever posts monitors on NUSE and VAL. In older versions of the IOC, CA didn’t handle zero-length arrays very well and that might have been why the RES field didn’t trigger a monitor event on VAL, although I
don’t see why it couldn’t have posted them on the NUSE field.
If you want to try fixing this, you could add a call to
monitor(prec) to the special() routine immediately after the call to
reset(prec) — the
reset() routine has other callers so it can’t call
db_post_events() itself, but calling
monitor(prec) after that looks like it might do the right thing. I don’t know if that’s the best fix, others here may know better and disagree — please take a look and speak up if you’ve worked on the compress record recently!
If that change does what you need and there are no dissenters here, we would consider merging a pull request with that change, but please run the unit tests to see if they might need changes to match — this record type has unit tests!
HTH,
- Andrew
Complexity comes for free, Simplicity you have to work for.
On 12/10/24, 9:35 AM, "Tech-talk" <tech-talk-bounces at aps.anl.gov> wrote:
Hi folks!
We are using compress records as circular buffers, and would like to be
able to empty them between events. However, our current implementation
feels hackish, so I'd like to see if we are missing something.
The circular buffer is implemented similarly to below:
record(calc, "scalar"){
field(CALC, "VAL+1")
}
record(compress, "array"){
field(ALG, "Circular Buffer")
field(NSAM, "100")
field(INP, "scalar PP")
}
Emptying them is done manually, with someone writing to a PV which
writes into the records' RES fields. There are two naive ways of
implementing the reset PV:
record(longout, "reset-array"){
field(OUT, "array.RES")
}
record(longout, "reset-array-pp"){
field(OUT, "array.RES PP")
}
"reset-array" doesn't process the record, so monitor clients don't
received its changed value; only new clients (or explicit Get
operations) see the empty vector. It does leave "array" empty, though,
so subsequent processing of the record will leave it with the correct
amount of elements.
"reset-array-pp" processes the record 'too much'. It will be emptied,
then processed once, so "scalar" is processed as well and "array"
fetches that value, ending up with one element, not empty.
The only way we have managed to make it work, so that monitor clients
(GUI and CLI) observe an empty vector, feels somewhat hackish. It's done
with seq:
record(seq, "reset-array-full"){
field(DOL1, 1)
field(DOL2, 1)
field(LNK1, "array.RES PP") # empty record, process it, ends up
with one element
field(LNK2, "array.RES") # somehow empties record before monitor is
actually posted
}
Is there some better way of implementing this?
If not, is the behavior of "reset-array-full" something we can rely on?
I'd be okay with relying on it, especially if I understood it better.
And could something be done to fix it in epics-base, perhaps always
posting monitors on writes to "special(SPC_RESET)" fields? Would that
make sense?
Cheers,
Érico
Aviso Legal: Esta mensagem e seus anexos podem conter informações confidenciais e/ou de uso restrito. Observe atentamente seu conteúdo e considere eventual consulta ao remetente antes de copiá-la, divulgá-la ou distribuí-la. Se você recebeu esta mensagem por
engano, por favor avise o remetente e apague-a imediatamente.
Disclaimer: This email and its attachments may contain confidential and/or privileged information. Observe its content carefully and consider possible querying to the sender before copying, disclosing or distributing it. If you have received this email by mistake,
please notify the sender and delete it immediately.
|