group monitor working
This commit is contained in:
@@ -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(...){
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user