pdb: meta mapping

This commit is contained in:
Michael Davidsaver
2017-09-28 18:27:40 -05:00
parent e084a9e943
commit b839d5dc6d
5 changed files with 67 additions and 29 deletions

View File

@ -36,8 +36,7 @@ record(waveform, "$(N):ArrayData") {
"$(N):Array":{
+id:"epics:nt/NTNDArray:1.0",
"value":{+type:"any", +channel:"VAL", +trigger:"*"},
"alarm.severity":{+type:"plain", +channel:"SEVR"},
"alarm.status":{+type:"plain", +channel:"STAT"}
"":{+type:"meta", +channel:"SEVR"}
}
})
}

View File

@ -21,12 +21,19 @@ typedef std::map<std::string, options_t> config_t;
struct context {
std::string msg;
std::string group, field, key;
unsigned depth; // number of '{'s
// depth 0 - invalid
// depth 1 - top Object
// depth 2 - Group
// depth 3 - field
context() :depth(0u) {}
GroupConfig conf;
void can_assign()
{
if(group.empty() || field.empty())
if(depth<2 || depth>3)
throw std::runtime_error("Can't assign value in this context");
}
@ -34,7 +41,7 @@ struct context {
can_assign();
GroupConfig::Group& grp = conf.groups[group];
if(key.empty()) {
if(depth==2) {
if(field=="+atomic") {
grp.atomic = value.as<pvd::boolean>();
grp.atomic_set = true;
@ -48,7 +55,7 @@ struct context {
}
field.clear();
} else {
} else if(depth==3) {
GroupConfig::Field& fld = grp.fields[field];
if(key=="+type") {
@ -125,8 +132,9 @@ int conf_string(void * ctx, const unsigned char * stringVal,
int conf_start_map(void * ctx)
{
TRY {
if(!self->group.empty() && !self->field.empty() && !self->key.empty())
throw std::runtime_error("Too deep");
self->depth++;
if(self->depth>3)
throw std::runtime_error("Group field def. can't contain Object (too deep)");
return 1;
}CATCH()
}
@ -135,16 +143,16 @@ int conf_map_key(void * ctx, const unsigned char * key,
unsigned int stringLen)
{
TRY {
if(stringLen==0)
throw std::runtime_error("empty key");
if(stringLen==0 && self->depth!=2)
throw std::runtime_error("empty group or key name not allowed");
std::string name((const char*)key, stringLen);
if(self->group.empty())
if(self->depth==1)
self->group.swap(name);
else if(self->field.empty())
else if(self->depth==2)
self->field.swap(name);
else if(self->key.empty())
else if(self->depth==3)
self->key.swap(name);
else
throw std::logic_error("Too deep!!");
@ -158,10 +166,15 @@ int conf_end_map(void * ctx)
TRY {
assert(self->key.empty()); // cleared in assign()
if(!self->field.empty())
if(self->depth==3)
self->key.clear();
else if(self->depth==2)
self->field.clear();
else if(!self->group.empty())
else if(self->depth==1)
self->group.clear();
else
throw std::logic_error("Invalid depth");
self->depth--;
return 1;
}CATCH()

View File

@ -363,13 +363,14 @@ PDBProvider::PDBProvider(const epics::pvAccess::Configuration::shared_pointer &)
// parse down attachment point to build/traverse structure
FieldName parts(mem.pvfldname);
assert(!parts.empty());
for(size_t j=0; j<parts.size()-1; j++) {
if(parts[j].isArray())
builder = builder->addNestedStructureArray(parts[j].name);
else
builder = builder->addNestedStructure(parts[j].name);
if(!parts.empty()) {
for(size_t j=0; j<parts.size()-1; j++) {
if(parts[j].isArray())
builder = builder->addNestedStructureArray(parts[j].name);
else
builder = builder->addNestedStructure(parts[j].name);
}
}
if(!mem.structID.empty())
@ -381,10 +382,15 @@ PDBProvider::PDBProvider(const epics::pvAccess::Configuration::shared_pointer &)
chan.swap(temp);
}
builder = mem.builder->dtype(builder, parts.back().name, chan);
if(!parts.empty())
builder = mem.builder->dtype(builder, parts.back().name, chan);
else
builder = mem.builder->dtype(builder, "", chan);
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->endNested();
if(!parts.empty()) {
for(size_t j=0; j<parts.size()-1; j++)
builder = builder->endNested();
}
if(!mem.pvname.empty()) {
members_map[mem.pvfldname] = J;
@ -611,6 +617,8 @@ PDBProvider::createChannel(std::string const & channelName,
FieldName::FieldName(const std::string& pv)
{
if(pv.empty())
return;
Splitter S(pv.c_str(), '.');
std::string part;
while(S.snip(part)) {

View File

@ -400,7 +400,7 @@ void putAll(const PVC &pv, unsigned dbe, db_field_log *pfl)
}
}
void findNSMask(pvCommon& pvmeta, dbChannel *chan, const epics::pvData::PVStructurePtr& pvalue)
void findNSMask(pvTimeAlarm& pvmeta, dbChannel *chan, const epics::pvData::PVStructurePtr& pvalue)
{
pdbRecordIterator info(chan);
const char *UT = info.info("Q:time:tag");
@ -741,7 +741,9 @@ struct PVIFMeta : public PVIF
pvd::PVStructurePtr field(std::dynamic_pointer_cast<pvd::PVStructure>(fld));
if(!field)
throw std::logic_error("PVIFMeta attached type mis-match");
meta.chan = channel;
attachTime(meta, field);
findNSMask(meta, channel, field);
if(enclosing) {
meta.maskALWAYS.clear();
meta.maskALWAYS.set(enclosing->getFieldOffset());
@ -788,8 +790,15 @@ struct MetaBuilder : public PVIFBuilder
dbChannel *channel)
{
pvd::StandardFieldPtr std(pvd::getStandardField());
return builder->add("alarm", std->alarm())
->add("timeStamp", std->timeStamp());
if(fld.empty()) {
return builder->add("alarm", std->alarm())
->add("timeStamp", std->timeStamp());
} else {
return builder->addNestedStructure(fld)
->add("alarm", std->alarm())
->add("timeStamp", std->timeStamp())
->endNested();
}
}
// Attach to a structure instance.
@ -800,7 +809,7 @@ struct MetaBuilder : public PVIFBuilder
const FieldName& fldname) OVERRIDE FINAL
{
if(!channel)
throw std::runtime_error("+type:\"any\" requires +channel:");
throw std::runtime_error("+type:\"meta\" requires +channel:");
pvd::PVField *enclosing = 0;
pvd::PVFieldPtr fld(fldname.lookup(root, &enclosing));

View File

@ -19,9 +19,12 @@ void test_parse()
" \"fld\":{\n"
" \"+type\": \"simple\","
" \"+putorder\": -4"
" },\n"
" \"\":{\n"
" \"+type\": \"top\""
" }\n"
" },\n"
" \"fld2\":{\n"
" \"grpb\":{\n"
" }\n"
"}";
@ -36,12 +39,18 @@ void test_parse()
testEqual(conf.groups["grpa"].fields["fld"].type, "simple");
testEqual(conf.groups["grpa"].fields["fld"].channel, "");
testEqual(conf.groups["grpa"].fields["fld"].putorder, -4);
testEqual(conf.groups["grpa"].fields[""].type, "top");
}
void test_fail()
{
testDiag("test_fail()");
{
GroupConfig conf;
testThrows(std::runtime_error, GroupConfig::parse("{", conf));
}
{
GroupConfig conf;
testThrows(std::runtime_error, GroupConfig::parse("{\"G\":{\"F\":{\"K\":{}}}}", conf));
@ -56,7 +65,7 @@ void test_fail()
MAIN(testanyscalar)
{
testPlan(8);
testPlan(10);
try {
test_parse();
test_fail();