SharedPV monitor discard empty updates

This commit is contained in:
Michael Davidsaver
2020-08-10 12:09:55 -07:00
parent 9192ba3c33
commit 8c55bf7de7
4 changed files with 71 additions and 15 deletions
+20
View File
@@ -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
+3
View File
@@ -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
View File
@@ -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
View File
@@ -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();