group monitor working

This commit is contained in:
Michael Davidsaver
2016-03-17 18:37:22 -04:00
parent 11b6659c60
commit 3dd40dcf76
4 changed files with 88 additions and 25 deletions

View File

@@ -125,7 +125,7 @@ struct PDBProcessor
curgroup->members.push_back(GroupMemberInfo(recbase + dbf, pvf));
curgroup->members.back().index = curgroup->members.size()-1;
curgroup->members_map[curgroup->name] = curgroup->members.back().index;
curgroup->members_map[pvf] = curgroup->members.back().index;
if(PDBProviderDebug>2) {
fprintf(stderr, " pdb map '%s.%s' <-> '%s'\n",
@@ -164,20 +164,10 @@ struct PDBProcessor
Splitter sep(trigs.c_str(), ',');
std::string target;
if(PDBProviderDebug>2)
fprintf(stderr, " pdb trg '%s.%s' -> ",
curgroup->name.c_str(), pvf.c_str());
while(sep.snip(target)) {
curgroup->hastriggers = true;
it->second.insert(target);
if(PDBProviderDebug<=2) continue;
fprintf(stderr, "'%s.%s'", curgroup->name.c_str(), target.c_str());
if(!!sep) fprintf(stderr, ", ");
}
if(PDBProviderDebug>2)
fprintf(stderr, "\n");
}
}
@@ -200,12 +190,19 @@ struct PDBProcessor
}
GroupMemberInfo& srcmem = info.members[it2x->second];
if(PDBProviderDebug>2)
fprintf(stderr, " pdb trg '%s.%s' -> ",
info.name.c_str(), src.c_str());
FOREACH(it3, end3, targets) { // for each trigger target
const std::string& target = *it3;
if(target=="*") {
for(size_t i=0; i<srcmem.triggers.size(); i++)
for(size_t i=0; i<info.members.size(); i++) {
srcmem.triggers.insert(i);
if(PDBProviderDebug>2)
fprintf(stderr, "%s, ", info.members[i].pvfldname.c_str());
}
} else {
@@ -219,8 +216,12 @@ struct PDBProcessor
// and finally, update source BitSet
srcmem.triggers.insert(targetmem.index);
if(PDBProviderDebug>2)
fprintf(stderr, "%s, ", info.members[targetmem.index].pvfldname.c_str());
}
}
if(PDBProviderDebug>2) fprintf(stderr, "\n");
}
} else {
if(PDBProviderDebug>1) fprintf(stderr, " pdb default triggers for '%s'\n", info.name.c_str());
@@ -407,8 +408,11 @@ PDBProvider::PDBProvider()
info.evt_PROPERTY.create(event_context, info.chan, &pdb_group_event, DBE_PROPERTY);
if(!info.triggers.empty())
if(!info.triggers.empty()) {
printf("##### setup VALUE %s\n", dbChannelName(info.chan));
info.evt_VALUE.create(event_context, info.chan, &pdb_group_event, DBE_VALUE|DBE_ALARM);
} else
printf("##### skip VALUE %s\n", dbChannelName(info.chan));
}
}
}catch(...){

View File

@@ -14,7 +14,7 @@ DBCH::DBCH(dbChannel *ch) :chan(ch)
throw std::invalid_argument("Failed to open channel");
}
if(!chan)
throw std::invalid_argument("Invalid channel");
throw std::invalid_argument(std::string("Invalid channel ")+dbChannelName(ch));
}
DBCH::DBCH(const std::string& name)
@@ -24,7 +24,7 @@ DBCH::DBCH(const std::string& name)
throw std::invalid_argument("Invalid channel");
if(dbChannelOpen(chan)) {
dbChannelDelete(chan);
throw std::invalid_argument("Failed to open channel");
throw std::invalid_argument("Failed to open channel "+name);
}
}
@@ -35,7 +35,7 @@ DBCH::DBCH(const char *name)
throw std::invalid_argument("Invalid channel");
if(dbChannelOpen(chan)) {
dbChannelDelete(chan);
throw std::invalid_argument("Failed to open channel");
throw std::invalid_argument(std::string("Failed to open channel ")+name);
}
}

View File

@@ -273,23 +273,16 @@ void testSingleMonitor(const PDBProvider::shared_pointer& prov)
PVMonitor mon(prov, "rec1");
mon.mon->start();
// start() will trigger two updates, one for DBE_VALUE|DBE_ALARM
// and another for DBE_PROPERTY
testOk1(mon.monreq->waitForEvent());
testDiag("Initial event");
PVMonitor::Element e(mon);
// TODO: correctly check the first update
// no mather which DBE_* arrives first...
e = mon.poll();
testOk1(!!e);
while(!(e = mon.poll())) {
testDiag("Wait initial event (part 2)");
mon.monreq->waitForEvent();
}
testOk1(!!e);
if(!!e) testEqual(toString(*e.elem->changedBitSet), "{0, 1, 3, 4, 11, 12, 14, 15, 17, 18}");
else testFail("oops");
testFieldEqual<pvd::PVDouble>(e, "value", 1.0);
testFieldEqual<pvd::PVDouble>(e, "display.limitHigh", 100.0);
testFieldEqual<pvd::PVDouble>(e, "display.limitLow", -100.0);
@@ -378,6 +371,59 @@ void testGroupMonitor(const PDBProvider::shared_pointer& prov)
testFieldEqual<pvd::PVDouble>(e, "fld1.value", 32.0);
}
void testGroupMonitorTriggers(const PDBProvider::shared_pointer& prov)
{
testDiag("test group monitor w/ triggers");
testdbPutFieldOk("rec5", DBR_DOUBLE, 5.0);
testdbPutFieldOk("rec6", DBR_DOUBLE, 6.0);
testdbPutFieldOk("rec5.RVAL", DBR_LONG, 50);
testDiag("subscribe to grp2");
PVMonitor mon(prov, "grp2");
PVMonitor::Element e(mon);
testOk1(mon.mon->start().isOK());
testDiag("Wait for initial event");
testOk1(mon.monreq->waitForEvent());
testDiag("Initial event");
e = mon.poll();
testOk1(!!e);
if(!!e) testEqual(toString(*e.elem->changedBitSet), "{0, 2, 4, 5, 12, 13, 15, 16, 18, 19, 32, 33, 35, 36, 38, 39, 42, 44, 45, 52, 53, 55, 56, 58, 59}");
else testFail("oops");
testFieldEqual<pvd::PVDouble>(e, "fld1.value", 5.0);
testFieldEqual<pvd::PVDouble>(e, "fld2.value", 6.0);
testFieldEqual<pvd::PVInt>(e, "fld3.value", 0); // not triggered -> no update. only get/set
e = mon.poll();
testOk1(!e);
testdbPutFieldOk("rec5.RVAL", DBR_LONG, 60); // no trigger -> no event
testdbPutFieldOk("rec5", DBR_DOUBLE, 15.0); // no trigger -> no event
testdbPutFieldOk("rec6", DBR_DOUBLE, 16.0); // event triggered
testDiag("Wait for event");
testOk1(mon.monreq->waitForEvent());
testDiag("event");
e = mon.poll();
testOk1(!!e);
if(!!e) testEqual(toString(*e.elem->changedBitSet), "{2, 4, 5, 42, 44, 45}");
else testFail("oops");
testFieldEqual<pvd::PVDouble>(e, "fld1.value", 15.0);
testFieldEqual<pvd::PVDouble>(e, "fld2.value", 16.0);
testFieldEqual<pvd::PVInt>(e, "fld3.value", 0); // not triggered -> no update. only get/set
e = mon.poll();
testOk1(!e);
}
} // namespace
extern "C"
@@ -405,6 +451,7 @@ MAIN(testpdb)
testSingleMonitor(prov);
testGroupMonitor(prov);
testGroupMonitorTriggers(prov);
}catch(...){
prov->destroy();
throw;

View File

@@ -20,3 +20,15 @@ record(ai, "rec4") {
field(RVAL, "40")
info(pdbGroup, "grp1|fld3=VAL|fld4=RVAL")
}
record(ai, "rec5") {
field(VAL, "5.0")
field(RVAL, "50")
info(pdbGroup, "grp2|fld1=VAL|fld3=RVAL")
}
record(ai, "rec6") {
field(VAL, "6.0")
field(RVAL, "60")
info(pdbGroup, "grp2|fld2=VAL")
info(pdbTrigger, "grp2|fld2>fld1,fld2")
}