Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group Put semantics/options #15

Open
mdavidsaver opened this issue Mar 28, 2018 · 7 comments
Open

Group Put semantics/options #15

mdavidsaver opened this issue Mar 28, 2018 · 7 comments

Comments

@mdavidsaver
Copy link
Member

mdavidsaver commented Mar 28, 2018

@ttkorhonen Brings up a case I hadn't considered wrt. group Put (edited for brevity).

record(ao, "output:step1") {
  field(PINI, "YES")
  field(FLNK, "outputvalue")
  info(Q:group, {
     "output:table":{
     "":{+type:"meta", +channel:"VAL"},
     "value.stepone":{+type:"plain",+channel:"VAL",+putorder:1}
     }
   })
}
record(ao, "output:step2") {
  field(PINI, "YES")
  field(FLNK, "outputvalue")
  info(Q:group, {
     "output:table":{
     "value.steptwo":{+type:"plain",+channel:"VAL",+putorder:1}
     }
   })
}
record(calc, "outputvalue") {
  field(CALC, "A+B")
  field(INPA, "output:step1")
  field(INPB, "output:step2")
}

Unlike the table example (iocBoot/iocimagedemo/table.db) where only one PV causes real action, in Timo's case changing any input may cause the output to change. Timo's expectation is that one group Put should result in "outputvalue" being processed once. However, what he does is equivalent to the pseudo-code:

dbScanLock("output:step1")
dbScanLock("output:step2")
dbPut("output:step1", ...)
if(scanPassive("output:step1") dbProcess("output:step1")
dbPut("output:step2", ...)
if(scanPassive("output:step2") dbProcess("output:step2")
dbScanUnLock("output:step1")
dbScanUnLock("output:step2")

The dbProcess() calls, along with the FLNKs will result in "outputvalue" being processed several times.

So the question is, how to avoid this while still preserving the behavior of single Puts?

@mdavidsaver
Copy link
Member Author

I can see that at minimum, group members need the option for force, or prohibit, processing as is already available for single Puts as a pvRequest option.

@ttkorhonen
Copy link

This is probably an ignorant question but does dbProcess have to follow immediately after each dbPut? In other words, would this be possible in a group put:

dbScanLock("output:step1")
dbScanLock("output:step2")
dbPut("output:step1", ...)
dbPut("output:step2", ...)
if(scanPassive("output:step1") dbProcess("output:step1")
if(scanPassive("output:step2") dbProcess("output:step2")
dbScanUnLock("output:step1")
dbScanUnLock("output:step2")

For the use case that I had in mind this would be OK, as far as I can think now.

@ralphlange
Copy link
Contributor

We have been discussing this at one of our f2f meetings, not sure what we ended with.

My original idea was:
If we consider a group put as an atomic operation, no processing should happen between setting elements. Processing should be explicitly specified as part of the mapping (for each field: process this record or not, process order). Client only specifies if the whole configured thing takes place or not.

I remember arguments:
Could be done by specifying .PROC fields as either visible or hidden fields inside the structure.
What if records in the group process other records in the group?

@ralphlange
Copy link
Contributor

Note that IIRC monitors on PP fields are not sent by dbPut() - the database relies on processing happening as a result of the put. This breaks if group puts suppress processing.

@anjohnson
Copy link
Member

I don’t think it’s any field’s PP status that normally suppresses generating monitors, IIRC that only applies to to VAL fields that are PP. The DBD file has no way to notify the IOC whether a particular field will generate a monitor on processing, and in most cases those might be conditional anyway (the Recore Reference column Rec Proc Monitor can’t be derived from the DBD info). However @ralphlange ‘s point still applies: if a group write modifies a PP VAL field but never processes the record no monitor will be fired, although that’s no different than using a DB link that is marked NPP.

@mdavidsaver
Copy link
Member Author

This is probably an ignorant question but does dbProcess have to follow immediately after each dbPut?

No. Doing this would avoid sending monitor updates with intermediate values, but still sends extra updates.

I opted to start with things this way because "like a sequence of caput" seems easier for experienced users to reason about. I'm open to finding a better way though.

To elaborate on #15 (comment) I'm thinking to add a mapping option like +pp:true with possible values being: true, false, or null (default/passive).

With this code change, and some extra 'PP' in your example, I think I can get the effect you're after.

record(ao, "output:step1") {
  field(PINI, "YES")
  field(FLNK, "outputvalue")
  info(Q:group, {
     "output:table":{
     "":{+type:"meta", +channel:"VAL"},
     "value.stepone":{+type:"plain",+channel:"VAL",+putorder:1,+pp:false}
     }
   })
}
... output:step2 omitted ...
record(calc, "outputvalue") {
  field(CALC, "A+B")
  field(INPA, "output:step1 PP")  # added PP
  field(INPB, "output:step2 PP")
  info(Q:group, {
    "_fake": {+type:"proc", +channel:"VAL", +putorder:2, +trigger:"*"}
  }
}

This would make a group put equivalent to

dbScanLock("output:step1");
dbScanLock("output:step2");
dbScanLock("outputvalue");
dbPut("output:step1", ...);
dbPut("output:step2", ...);
dbProcess("outputvalue"); // PP input links cause step1/2 to process once with new values
dbScanUnLock("output:step1");
dbScanUnLock("output:step2");
dbScanUnLock("outputvalue");

@mdavidsaver
Copy link
Member Author

mdavidsaver commented Mar 31, 2018

My original idea was:

I have to admit I remember only some of this argument, so we'll probably have to rehash it. This change by itself doesn't solve any fundamental problem, though it doesn't seem to introduce any new confusion. So I'm undecided...

What I see as "the fundamental problem" is the dbPutLink()/dbGetLink()/dbScanFwdLink() are recursive. I think I can see a way to avoid this for output/forward links. Where I get stuck is ordered and conditional input links w/ PP.

Still, this would be enough in Timo's case. If dbScanFwdLink() for DB_LINK only flags the target record for later processing, then the processing changes from the step1 and step2 records could be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants