examples: monitorme/spamme support pipeline=true
This commit is contained in:
@ -130,8 +130,6 @@ struct MonTracker : public epicsThreadRunable
|
||||
MonTracker::shared_pointer self(owner.lock());
|
||||
if(!self) return;
|
||||
|
||||
std::cout<<"monitorConnect "<<self->chan->getChannelName()<<" "<<status<<"\n";
|
||||
|
||||
if(status.isSuccess() && !self->alldone) {
|
||||
Guard G(self->mutex);
|
||||
|
||||
@ -154,22 +152,29 @@ struct MonTracker : public epicsThreadRunable
|
||||
MonTracker::shared_pointer self(owner.lock());
|
||||
if(!self) return;
|
||||
|
||||
Guard G(self->mutex);
|
||||
std::cout<<"channelDisconnect "<<self->chan->getChannelName()<<"\n";
|
||||
{
|
||||
Guard G(self->mutex);
|
||||
|
||||
self->cur_type.reset();
|
||||
self->alldone |= destroy;
|
||||
self->cur_type.reset();
|
||||
self->alldone |= destroy;
|
||||
|
||||
// no need to call self->op->stop()
|
||||
// monitor implicitly stopped on disconnect
|
||||
pvd::Status msts(self->op->stop());
|
||||
// no need to call self->op->stop()
|
||||
// monitor implicitly stopped on disconnect
|
||||
pvd::Status msts(self->op->stop());
|
||||
}
|
||||
try {
|
||||
monwork.push(owner);
|
||||
}catch(std::exception& e){
|
||||
Guard G(self->mutex);
|
||||
self->queued = false;
|
||||
std::cout<<"channelDisconnect failed to queue "<<e.what()<<"\n";
|
||||
}
|
||||
}
|
||||
|
||||
virtual void monitorEvent(pva::MonitorPtr const & monitor)
|
||||
{
|
||||
MonTracker::shared_pointer self(owner.lock());
|
||||
if(!self) return;
|
||||
std::cout<<"monitorEvent "<<self->chan->getChannelName()<<"\n";
|
||||
{
|
||||
Guard G(self->mutex);
|
||||
if(self->queued) return;
|
||||
@ -203,21 +208,30 @@ struct MonTracker : public epicsThreadRunable
|
||||
|
||||
virtual void run()
|
||||
{
|
||||
bool disconn;
|
||||
{
|
||||
Guard G(mutex);
|
||||
queued = false;
|
||||
disconn = !cur_type;
|
||||
}
|
||||
while(true) {
|
||||
pva::MonitorElementPtr elem(op->poll());
|
||||
if(!elem) break;
|
||||
try {
|
||||
std::cout<<"Event "<<chan->getChannelName()<<"\n"<<elem->pvStructurePtr<<"\n";
|
||||
pvd::PVField::shared_pointer fld(elem->pvStructurePtr->getSubField("value"));
|
||||
if(!fld)
|
||||
fld = elem->pvStructurePtr;
|
||||
std::cout<<"Event "<<chan->getChannelName()<<" "<<fld
|
||||
<<" Changed:"<<*elem->changedBitSet
|
||||
<<" overrun:"<<*elem->overrunBitSet<<"\n";
|
||||
} catch(...) {
|
||||
op->release(elem);
|
||||
throw;
|
||||
}
|
||||
op->release(elem);
|
||||
}
|
||||
if(disconn)
|
||||
std::cout<<"Disconnected\n";
|
||||
}
|
||||
};
|
||||
|
||||
@ -226,7 +240,8 @@ struct MonTracker : public epicsThreadRunable
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
double waitTime = -1.0;
|
||||
std::string providerName("pva");
|
||||
std::string providerName("pva"),
|
||||
requestStr("field()");
|
||||
typedef std::vector<std::string> pvs_t;
|
||||
pvs_t pvs;
|
||||
|
||||
@ -246,6 +261,13 @@ int main(int argc, char *argv[]) {
|
||||
std::cout << "--timeout requires value\n";
|
||||
return 1;
|
||||
}
|
||||
} else if(strcmp(argv[i], "-r")==0 || strcmp(argv[i], "--request")==0) {
|
||||
if(i<argc-1) {
|
||||
requestStr = argv[++i];
|
||||
} else {
|
||||
std::cout << "--request requires value\n";
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
std::cout<<"Unknown argument: "<<argv[i]<<"\n";
|
||||
}
|
||||
@ -263,7 +285,7 @@ int main(int argc, char *argv[]) {
|
||||
#endif
|
||||
|
||||
// build "pvRequest" which asks for all fields
|
||||
pvd::PVStructure::shared_pointer pvReq(pvd::createRequest("field()"));
|
||||
pvd::PVStructure::shared_pointer pvReq(pvd::createRequest(requestStr));
|
||||
|
||||
// explicitly select configuration from process environment
|
||||
pva::Configuration::shared_pointer conf(pva::ConfigurationBuilder()
|
||||
|
@ -46,9 +46,14 @@ struct SpamMonitor : public pva::Monitor,
|
||||
{
|
||||
const std::tr1::shared_ptr<SpamChannel> channel;
|
||||
const pva::MonitorRequester::shared_pointer requester;
|
||||
pvd::int32 maxQueue;
|
||||
bool pipeline;
|
||||
// Has the client seen poll()==NULL
|
||||
bool clientEmpty;
|
||||
epicsMutex mutex;
|
||||
|
||||
bool running;
|
||||
epicsUInt32 remoteQueue;
|
||||
std::deque<epics::pvData::MonitorElementPtr> filled, empty;
|
||||
pvd::PVStructure::shared_pointer value;
|
||||
epicsUInt32 counter;
|
||||
@ -58,19 +63,28 @@ struct SpamMonitor : public pva::Monitor,
|
||||
const pvd::PVStructure::shared_pointer &pvRequest)
|
||||
:channel(chan)
|
||||
,requester(requester)
|
||||
,maxQueue(0)
|
||||
,pipeline(false)
|
||||
,clientEmpty(true)
|
||||
,running(false)
|
||||
,remoteQueue(0)
|
||||
,counter(0)
|
||||
{
|
||||
pvd::int32 qsize = 0;
|
||||
pvd::PVScalar::shared_pointer queueSize(pvRequest->getSubField<pvd::PVScalar>("record._options.queueSize"));
|
||||
if(queueSize)
|
||||
qsize = queueSize->getAs<pvd::int32>();
|
||||
if(qsize<=0)
|
||||
qsize = 3;
|
||||
pvd::PVScalar::shared_pointer fld;
|
||||
|
||||
fld = pvRequest->getSubField<pvd::PVScalar>("record._options.queueSize");
|
||||
if(fld)
|
||||
maxQueue = fld->getAs<pvd::int32>();
|
||||
if(maxQueue<3)
|
||||
maxQueue = 3;
|
||||
|
||||
fld = pvRequest->getSubField<pvd::PVScalar>("record._options.pipeline");
|
||||
if(fld)
|
||||
pipeline = fld->getAs<pvd::boolean>();
|
||||
|
||||
pvd::PVDataCreatePtr create(pvd::getPVDataCreate());
|
||||
value = create->createPVStructure(spamtype);
|
||||
for(pvd::int32 i=0; i<qsize; i++)
|
||||
for(pvd::int32 i=0; i<maxQueue; i++)
|
||||
{
|
||||
pvd::MonitorElementPtr elem(new pvd::MonitorElement(create->createPVStructure(spamtype)));
|
||||
empty.push_back(elem);
|
||||
@ -87,9 +101,9 @@ struct SpamMonitor : public pva::Monitor,
|
||||
Guard G(mutex);
|
||||
run = running;
|
||||
running = true;
|
||||
clientEmpty = true;
|
||||
}
|
||||
if(!run)
|
||||
pushall();
|
||||
pushall();
|
||||
return pvd::Status::Ok;
|
||||
}
|
||||
virtual pvd::Status stop() OVERRIDE FINAL
|
||||
@ -108,6 +122,7 @@ struct SpamMonitor : public pva::Monitor,
|
||||
ret = filled.front();
|
||||
filled.pop_front();
|
||||
}
|
||||
clientEmpty = !ret;
|
||||
return ret;
|
||||
}
|
||||
virtual void release(const pva::MonitorElementPtr& elem) OVERRIDE FINAL
|
||||
@ -121,13 +136,24 @@ struct SpamMonitor : public pva::Monitor,
|
||||
pushall();
|
||||
}
|
||||
|
||||
virtual void reportRemoteQueueStatus(pvd::int32 freeElements) OVERRIDE FINAL
|
||||
{
|
||||
{
|
||||
Guard G(mutex);
|
||||
remoteQueue += freeElements;
|
||||
}
|
||||
pushall();
|
||||
}
|
||||
|
||||
void pushall()
|
||||
{
|
||||
bool signal = false;
|
||||
bool signal;
|
||||
{
|
||||
Guard G(mutex);
|
||||
|
||||
while(!empty.empty()) {
|
||||
signal = clientEmpty && filled.empty();
|
||||
|
||||
while(!empty.empty() && (!pipeline || remoteQueue>0)) {
|
||||
pva::MonitorElementPtr elem(empty.front());
|
||||
|
||||
pvd::PVIntPtr fld(value->getSubFieldT<pvd::PVInt>("value"));
|
||||
@ -138,10 +164,12 @@ struct SpamMonitor : public pva::Monitor,
|
||||
elem->changedBitSet->set(0);
|
||||
elem->overrunBitSet->clear();
|
||||
|
||||
signal |= filled.empty();
|
||||
filled.push_back(elem);
|
||||
empty.pop_front();
|
||||
remoteQueue--;
|
||||
}
|
||||
|
||||
signal &= !filled.empty();
|
||||
}
|
||||
if(signal)
|
||||
requester->monitorEvent(shared_from_this());
|
||||
|
Reference in New Issue
Block a user