From cc5d38293042cb2a37e4c61d4f20f2095951180e Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 21 Nov 2022 09:56:16 -0800 Subject: [PATCH] client: monitor yield "complete" updates Populate unchanged fields with most recently received value. --- src/clientmon.cpp | 35 +++++++++++++++++++++++++++++++++++ test/testmon.cpp | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/clientmon.cpp b/src/clientmon.cpp index eb76be6..ca20f05 100644 --- a/src/clientmon.cpp +++ b/src/clientmon.cpp @@ -549,6 +549,41 @@ void Connection::handle_MONITOR() } from_wire_valid(M, rxRegistry, data); + /* co-iterate data and prototype. + * copy marked from data -> prototype + * copy unmarked from prototype -> data + */ + { + auto delta = Value::Helper::store_ptr(data); + auto complete = Value::Helper::store_ptr(info->prototype); + auto N = Value::Helper::desc(info->prototype)->size(); + for(size_t i=0u; i < N; i++, delta++, complete++) + { + const auto src = delta->valid ? delta : complete; + auto dst = delta->valid ? complete : delta; + + switch(delta->code) { + case StoreType::Null: + break; + case StoreType::Bool: + case StoreType::UInteger: + case StoreType::Integer: + case StoreType::Real: + memcpy(&dst->store, &src->store, sizeof(src->store)); + break; + case StoreType::String: + dst->as() = src->as(); + break; + case StoreType::Array: + dst->as>() = src->as>(); + break; + case StoreType::Compound: + dst->as().copyIn(&src->store, StoreType::Compound); + break; + } + } + } + BitMask overrun; from_wire(M, overrun); for(auto i : range(overrun.wsize())) { diff --git a/test/testmon.cpp b/test/testmon.cpp index b0581a9..5225988 100644 --- a/test/testmon.cpp +++ b/test/testmon.cpp @@ -262,6 +262,36 @@ struct TestLifeCycle : public BasicTest testFail("Missing data update"); } } + + void testDelta() + { + testShow()<<__func__; + + if(auto val = pop(sub, evt)) { + testEq(val["value"].as(), 42); + testEq(val["alarm.severity"].as(), 0u); + testTrue(val["value"].isMarked(false)); + testFalse(val["alarm.severity"].isMarked(false)); + } else { + testFail("Missing data update"); + } + + // leave .value at 42 + { + auto update(initial.cloneEmpty()); + update["alarm.severity"] = 1; + mbox.post(update); + } + + if(auto val = pop(sub, evt)) { + testEq(val["value"].as(), 42); + testEq(val["alarm.severity"].as(), 1u); + testFalse(val["value"].isMarked(false)); + testTrue(val["alarm.severity"].isMarked(false)); + } else { + testFail("Missing data update"); + } + } }; struct TestReconn : public BasicTest @@ -332,7 +362,7 @@ struct TestReconn : public BasicTest MAIN(testmon) { - testPlan(32); + testPlan(41); testSetup(); logger_config_env(); BasicTest().orphan(); @@ -342,6 +372,7 @@ MAIN(testmon) TestLifeCycle().testBasic(true); TestLifeCycle().testBasic(false); TestLifeCycle().testSecond(); + TestLifeCycle().testDelta(); TestReconn().testReconn(false); TestReconn().testReconn(true); cleanup_for_valgrind();