SharedPV monitor discard empty updates
This commit is contained in:
@@ -71,5 +71,25 @@ BitMask request2mask(const FieldDesc* desc, const Value& pvRequest)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool testmask(const Value& update, const BitMask& mask)
|
||||
{
|
||||
auto desc = Value::Helper::desc(update);
|
||||
auto store = Value::Helper::store_ptr(update);
|
||||
|
||||
if(!desc)
|
||||
return false;
|
||||
|
||||
if(store->valid && mask[0])
|
||||
return true;
|
||||
|
||||
if(desc->code==TypeCode::Struct) {
|
||||
for(auto idx : range(size_t(1u), desc->size())) {
|
||||
if(store[idx].valid && mask[idx])
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}} // namespace pvxs::impl
|
||||
|
||||
@@ -16,6 +16,9 @@ namespace impl {
|
||||
PVXS_API
|
||||
BitMask request2mask(const FieldDesc* desc, const Value& pvRequest);
|
||||
|
||||
PVXS_API
|
||||
bool testmask(const Value& update, const BitMask& mask);
|
||||
|
||||
}} // namespace pvxs::impl
|
||||
|
||||
#endif // PVREQUEST_H
|
||||
|
||||
+16
-14
@@ -220,28 +220,30 @@ struct ServerMonitorControl : public server::MonitorControlOp
|
||||
if(!mon)
|
||||
return false;
|
||||
|
||||
Guard G(mon->lock);
|
||||
|
||||
if(val && mon->type && mon->type.get()!=Value::Helper::desc(val))
|
||||
throw std::logic_error("Type change not allowed in post(). Recommend pvxs::Value::cloneEmpty()");
|
||||
|
||||
if((mon->queue.size() < mon->limit) || force || !val) {
|
||||
mon->queue.push_back(val);
|
||||
if(testmask(val, mon->pvMask)) {
|
||||
Guard G(mon->lock);
|
||||
|
||||
} else if(!maybe) {
|
||||
// squash
|
||||
assert(mon->limit>0 && !mon->queue.empty());
|
||||
if((mon->queue.size() < mon->limit) || force || !val) {
|
||||
mon->queue.push_back(val);
|
||||
|
||||
mon->queue.back().assign(val);
|
||||
// TODO track overrun
|
||||
} else if(!maybe) {
|
||||
// squash
|
||||
assert(mon->limit>0 && !mon->queue.empty());
|
||||
|
||||
} else {
|
||||
// nope
|
||||
mon->queue.back().assign(val);
|
||||
// TODO track overrun
|
||||
|
||||
} else {
|
||||
// nope
|
||||
}
|
||||
|
||||
if(auto serv = server.lock())
|
||||
MonitorOp::maybeReply(serv.get(), mon);
|
||||
}
|
||||
|
||||
if(auto serv = server.lock())
|
||||
MonitorOp::maybeReply(serv.get(), mon);
|
||||
|
||||
return mon->queue.size() < mon->limit;
|
||||
}
|
||||
|
||||
|
||||
+32
-1
@@ -71,6 +71,36 @@ void testPvRequest()
|
||||
}
|
||||
}
|
||||
|
||||
void testPvMask()
|
||||
{
|
||||
auto val = nt::NTScalar{TypeCode::String}.create();
|
||||
|
||||
auto rdef = TypeDef(TypeCode::Struct, {
|
||||
members::Struct("field", {
|
||||
members::Struct("value", {}),
|
||||
})
|
||||
});
|
||||
|
||||
auto mask = request2mask(Value::Helper::desc(val), rdef.create());
|
||||
|
||||
testFalse(testmask(val, mask));
|
||||
|
||||
val["alarm.status"].mark();
|
||||
testFalse(testmask(val, mask));
|
||||
|
||||
val["value"].mark();
|
||||
testTrue(testmask(val, mask));
|
||||
|
||||
val["alarm.status"].unmark();
|
||||
testTrue(testmask(val, mask));
|
||||
|
||||
val.unmark();
|
||||
testFalse(testmask(val, mask));
|
||||
|
||||
val.mark();
|
||||
testTrue(testmask(val, mask));
|
||||
}
|
||||
|
||||
struct TestBuilder : client::detail::CommonBuilder<TestBuilder, client::detail::PRBase>
|
||||
{
|
||||
TestBuilder()
|
||||
@@ -349,10 +379,11 @@ void testArgs()
|
||||
|
||||
MAIN(testpvreq)
|
||||
{
|
||||
testPlan(30);
|
||||
testPlan(36);
|
||||
testSetup();
|
||||
logger_config_env();
|
||||
testPvRequest();
|
||||
testPvMask();
|
||||
testEmpty();
|
||||
testAssemble();
|
||||
testParseEmpty();
|
||||
|
||||
Reference in New Issue
Block a user