pvalink: input proc if changed
This commit is contained in:
@ -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.
|
||||
|
@ -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().
|
||||
|
@ -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()) {
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user