pvalink: input proc if changed

This commit is contained in:
Michael Davidsaver
2018-04-21 13:31:03 -07:00
parent 75efc13244
commit e3c0703df1
5 changed files with 42 additions and 3 deletions

View File

@ -184,6 +184,7 @@ record(longin, "src") {
time:false, # set record time during getValue
monorder:0, # Order of record processing as a result of CP and CPP
retry:false,# allow Put while disconnected.
always:false,# CP/CPP input link process even when .value field hasn't changed
defer:false # Defer put
}})
}
@ -283,6 +284,12 @@ Put to contain updates to multiple sub-fields.
Allow a Put operation to be queued while the link is disconnected.
The Put will be executed when the link becomes connected.
@subsubsection qsrv_link_always always: CP/CPP always process
By default (always:false) a subscription update will only cause a CP input link
to scan if the structure field (cf. field: option) is marked as changed.
Set to true to override this, and always process the link.
@subsubsection qsrv_link_sem Link semantics/behavior
This section attempts to answer some questions about how links behave in certain situations.

View File

@ -78,7 +78,7 @@ struct pvaLinkConfig : public jlink
MSI,
} ms;
bool defer, pipeline, time, retry, local;
bool defer, pipeline, time, retry, local, always;
int monorder;
// internals used by jlif parsing
@ -168,6 +168,7 @@ private:
std::vector<dbCommon*> scan_records;
std::vector<bool> scan_check_passive;
std::vector<epics::pvData::BitSet> scan_changed;
DBManyLock atomic_lock;
};
@ -194,6 +195,7 @@ struct pvaLink : public pvaLinkConfig
epics::pvData::PVStructure::const_shared_pointer fld_display,
fld_control,
fld_valueAlarm;
epics::pvData::BitSet proc_changed;
// cached snapshot of alarm and timestamp
// captured in pvaGetValue().

View File

@ -256,6 +256,9 @@ void pvaLinkChannel::run_dbProcess(size_t idx)
if(scan_check_passive[idx] && precord->scan!=0) {
return;
} else if(connected_latched && !op_mon.changed.logical_and(scan_changed[idx])) {
return;
} else if (precord->pact) {
if (precord->tpro)
printf("%s: Active %s\n",
@ -327,6 +330,7 @@ void pvaLinkChannel::run()
scan_records.clear();
scan_check_passive.clear();
scan_changed.clear();
for(links_t::iterator it(links.begin()), end(links.end()); it!=end; ++it)
{
@ -343,6 +347,7 @@ void pvaLinkChannel::run()
scan_records.push_back(link->plink->precord);
scan_check_passive.push_back(link->pp != pvaLink::CP);
scan_changed.push_back(link->proc_changed);
}
DBManyLock ML(scan_records);
@ -351,8 +356,6 @@ void pvaLinkChannel::run()
links_changed = false;
}
// TODO: if connected_latched. Option to test op_mon.changed with link::fld_value to only process on value change
}
if(scan_records.empty()) {

View File

@ -17,6 +17,7 @@ pvaLinkConfig::pvaLinkConfig()
,time(false)
,retry(false)
,local(false)
,always(false)
,monorder(0)
{}
pvaLinkConfig::~pvaLinkConfig() {}
@ -41,6 +42,7 @@ using namespace pvalink;
* "monorder":#,// order of processing during CP scan
* "defer":true,// whether to immediately start Put, or only queue value to be sent
* "retry":true,// queue Put while disconnected, and retry on connect
* "always":true,// CP/CPP updates always process a like, even if its input field hasn't changed
* "local":false,// Require local channel
* }
*/
@ -114,6 +116,8 @@ jlif_result pva_parse_bool(jlink *pjlink, int val)
pvt->retry = !!val;
} else if(pvt->jkey == "local") {
pvt->local = !!val;
} else if(pvt->jkey == "always") {
pvt->always = !!val;
} else if(pvt->debug) {
printf("pva link parsing unknown integer depth=%u key=\"%s\" value=%s\n",
pvt->parseDepth, pvt->jkey.c_str(), val ? "true" : "false");

View File

@ -114,6 +114,29 @@ void pvaLink::onTypeChange()
fld_display = std::tr1::dynamic_pointer_cast<const pvd::PVStructure>(getSubField("display"));
fld_control = std::tr1::dynamic_pointer_cast<const pvd::PVStructure>(getSubField("control"));
fld_valueAlarm = std::tr1::dynamic_pointer_cast<const pvd::PVStructure>(getSubField("valueAlarm"));
proc_changed.clear();
// build mask of all "changed" bits associated with our .value
// CP/CPP input links will process this link only for updates where
// the changed mask and proc_changed share at least one set bit.
if(fld_value) {
// bit for this field
proc_changed.set(fld_value->getFieldOffset());
// bits of all parent fields
for(const pvd::PVStructure* parent = fld_value->getParent(); parent; parent = parent->getParent()) {
proc_changed.set(parent->getFieldOffset());
}
if(fld_value->getField()->getType()==pvd::structure)
{
// bits of all child fields
const pvd::PVStructure *val = static_cast<const pvd::PVStructure*>(fld_value.get());
for(size_t i=val->getFieldOffset(), N=val->getNextFieldOffset(); i<N; i++)
proc_changed.set(i);
}
}
}
} // namespace pvalink