From c06d4bb69abb4b77d68310d79c0ad584a07cbcca Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Mon, 18 Sep 2023 11:34:46 -0700 Subject: [PATCH] ioc: actually require +putorder to PUT --- ioc/fieldconfig.h | 4 ++- ioc/fielddefinition.h | 4 +-- ioc/groupconfigprocessor.cpp | 6 +++- ioc/groupprocessorcontext.cpp | 5 +++- ioc/groupsource.cpp | 2 +- test/image.db | 1 + test/ntenum.db | 2 +- test/testqgroup.cpp | 54 +++++++++++++++++------------------ 8 files changed, 43 insertions(+), 35 deletions(-) diff --git a/ioc/fieldconfig.h b/ioc/fieldconfig.h index b949f79..40565c4 100644 --- a/ioc/fieldconfig.h +++ b/ioc/fieldconfig.h @@ -12,6 +12,7 @@ #include #include +#include #include @@ -33,6 +34,8 @@ struct MappingInfo { static const char *name(type_t t); + int64_t putOrder = std::numeric_limits::min(); + uint32_t nsecMask = 0u; Value cval; @@ -48,7 +51,6 @@ class FieldConfig { public: std::string channel, trigger, structureId; MappingInfo info; - int64_t putOrder = 0; }; } // pvxs diff --git a/ioc/fielddefinition.h b/ioc/fielddefinition.h index e6d627d..80866a5 100644 --- a/ioc/fielddefinition.h +++ b/ioc/fielddefinition.h @@ -33,9 +33,7 @@ public: FieldDefinition(const FieldConfig& fieldConfig, const std::string& fieldName); - bool operator<(const FieldDefinition& o) const { - return putOrder < o.putOrder; - } + bool operator<(const FieldDefinition& o) const = delete; }; } // pvxs diff --git a/ioc/groupconfigprocessor.cpp b/ioc/groupconfigprocessor.cpp index 8c4cfed..ff81412 100644 --- a/ioc/groupconfigprocessor.cpp +++ b/ioc/groupconfigprocessor.cpp @@ -250,7 +250,11 @@ void GroupConfigProcessor::defineFields(GroupDefinition& groupDefinition, const void GroupConfigProcessor::defineFieldSortOrder() { for (auto&& groupDefinitionMapEntry: groupDefinitionMap) { auto& groupDefinition = groupDefinitionMapEntry.second; - std::sort(groupDefinition.fields.begin(), groupDefinition.fields.end()); + std::stable_sort(groupDefinition.fields.begin(), groupDefinition.fields.end(), + [](const FieldDefinition& l, const FieldDefinition& r) -> bool + { + return l.info.putOrder < r.info.putOrder; + }); groupDefinition.fieldMap.clear(); auto groupFieldIndex = 0; diff --git a/ioc/groupprocessorcontext.cpp b/ioc/groupprocessorcontext.cpp index 74da6ff..07f18b3 100644 --- a/ioc/groupprocessorcontext.cpp +++ b/ioc/groupprocessorcontext.cpp @@ -73,7 +73,10 @@ void GroupProcessorContext::assign(const Value& value) { groupField.trigger = value.as(); } else if (key == "+putorder") { - groupField.putOrder = value.as(); + auto po(value.as()); + if(po==std::numeric_limits::min()) + po += 1; + groupField.info.putOrder = po; } else if (key == "+const") { groupField.info.cval = value; diff --git a/ioc/groupsource.cpp b/ioc/groupsource.cpp index 10ed4b4..438e62d 100644 --- a/ioc/groupsource.cpp +++ b/ioc/groupsource.cpp @@ -491,7 +491,7 @@ void putGroupField(const Value& value, const GroupSecurityCache& groupSecurityCache) { // find the leaf node that the field refers to in the given value auto leafNode = field.findIn(value); - bool marked = leafNode.isMarked() && field.value; + bool marked = leafNode.isMarked() && field.value && field.info.putOrder!=std::numeric_limits::min(); // If the field references a valid part of the given value then we can send it to the database if (marked) { diff --git a/test/image.db b/test/image.db index 950d858..074b500 100644 --- a/test/image.db +++ b/test/image.db @@ -41,6 +41,7 @@ record(waveform, "$(N):ArrayData") { +id:"epics:nt/NTNDArray:1.0", "value":{+type:"any", +channel:"VAL", + +putorder:0, +trigger:"*"}, "":{+type:"meta", +channel:"SEVR"}, "x":{+type:"meta", +channel:"SEVR"} diff --git a/test/ntenum.db b/test/ntenum.db index 0356e2f..94ebd09 100644 --- a/test/ntenum.db +++ b/test/ntenum.db @@ -7,7 +7,7 @@ record(longout, "$(P):ENUM:INDEX") { "$(P):ENUM":{ +id:"epics:nt/NTEnum:1.0", "value":{+type:"structure", +id:"enum_t"}, - "value.index":{+type:"plain", +channel:"VAL"}, + "value.index":{+type:"plain", +channel:"VAL", +putorder:0}, "":{+type:"meta", +channel:"VAL"} } }) diff --git a/test/testqgroup.cpp b/test/testqgroup.cpp index d4e36f4..6729fe6 100644 --- a/test/testqgroup.cpp +++ b/test/testqgroup.cpp @@ -279,15 +279,6 @@ void testImage() " } timeStamp\n" " }\n" " ]\n" - " struct[] dimension = {2}[\n" - " struct {\n" - " int32_t size = 100\n" - " }\n" - " struct {\n" - " int32_t size = 100\n" - " }\n" - " ]\n" - " any value uint16_t[] = {10000}[0, 655, 1310, 1966, 2621, ...]\n" " struct {\n" " struct \"alarm_t\" {\n" " int32_t severity = 0\n" @@ -300,6 +291,15 @@ void testImage() " int32_t userTag = 0\n" " } timeStamp\n" " } x\n" + " struct[] dimension = {2}[\n" + " struct {\n" + " int32_t size = 100\n" + " }\n" + " struct {\n" + " int32_t size = 100\n" + " }\n" + " ]\n" + " any value uint16_t[] = {10000}[0, 655, 1310, 1966, 2621, ...]\n" "}\n"); testStrEq(std::string(SB()< uint16_t[] = {10000}[0, 655, 1310, 1966, 2621, ...]\n" - "x.alarm.severity int32_t = 0\n" - "x.alarm.status int32_t = 0\n" - "x.alarm.message string = \"\"\n" - "x.timeStamp.secondsPastEpoch int64_t = 643497678\n" - "x.timeStamp.nanoseconds int32_t = 102030\n"); + "value-> uint16_t[] = {10000}[0, 655, 1310, 1966, 2621, ...]\n"); TestSubscription sub(ctxt.monitor("img:Array2")); val = sub.waitForUpdate(); @@ -375,18 +375,18 @@ void testImage() "attribute[1].timeStamp.secondsPastEpoch int64_t = 631152000\n" "attribute[1].timeStamp.nanoseconds int32_t = 0\n" "attribute[1].timeStamp.userTag int32_t = 0\n" - "dimension struct[]\n" - "dimension[0] struct\n" - "dimension[0].size int32_t = 100\n" - "dimension[1] struct\n" - "dimension[1].size int32_t = 100\n" "value any\n" "value-> uint16_t[] = {10000}[0, 655, 1310, 1966, 2621, ...]\n" "x.alarm.severity int32_t = 0\n" "x.alarm.status int32_t = 0\n" "x.alarm.message string = \"\"\n" "x.timeStamp.secondsPastEpoch int64_t = 643497678\n" - "x.timeStamp.nanoseconds int32_t = 102030\n"); + "x.timeStamp.nanoseconds int32_t = 102030\n" + "dimension struct[]\n" + "dimension[0] struct\n" + "dimension[0].size int32_t = 100\n" + "dimension[1] struct\n" + "dimension[1].size int32_t = 100\n"); testTimeSec++; testdbPutFieldOk("img:ArrayData_.PROC", DBR_LONG, 0); @@ -421,18 +421,18 @@ void testImage() "attribute[1].timeStamp.secondsPastEpoch int64_t = 631152000\n" "attribute[1].timeStamp.nanoseconds int32_t = 0\n" "attribute[1].timeStamp.userTag int32_t = 0\n" - "dimension struct[]\n" - "dimension[0] struct\n" - "dimension[0].size int32_t = 100\n" - "dimension[1] struct\n" - "dimension[1].size int32_t = 100\n" "value any\n" "value-> uint16_t[] = {10000}[0, 655, 1310, 1966, 2621, ...]\n" "x.alarm.severity int32_t = 0\n" "x.alarm.status int32_t = 0\n" "x.alarm.message string = \"\"\n" "x.timeStamp.secondsPastEpoch int64_t = 643497681\n" - "x.timeStamp.nanoseconds int32_t = 102030\n"); + "x.timeStamp.nanoseconds int32_t = 102030\n" + "dimension struct[]\n" + "dimension[0] struct\n" + "dimension[0].size int32_t = 100\n" + "dimension[1] struct\n" + "dimension[1].size int32_t = 100\n"); sub.testEmpty();