207 lines
5.8 KiB
C++
207 lines
5.8 KiB
C++
/*
|
|
* Copyright information and license terms for this software can be
|
|
* found in the file LICENSE that is included with the distribution
|
|
*/
|
|
#include <iostream>
|
|
#include <pva/client.h>
|
|
#include <pv/caProvider.h>
|
|
|
|
#include <stdio.h>
|
|
#include <epicsStdlib.h>
|
|
#include <epicsGetopt.h>
|
|
#include <epicsThread.h>
|
|
#include <pv/logger.h>
|
|
#include <pv/lock.h>
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <sstream>
|
|
|
|
#include <pv/event.h>
|
|
#include <epicsExit.h>
|
|
|
|
#include "pvutils.h"
|
|
|
|
namespace pvd = epics::pvData;
|
|
namespace pva = epics::pvAccess;
|
|
|
|
namespace {
|
|
|
|
void usage (void)
|
|
{
|
|
fprintf (stderr, "\nUsage: pvinfo [options] <PV name>...\n\n"
|
|
"\noptions:\n"
|
|
" -h: Help: Print this message\n"
|
|
" -V: Print version and exit\n"
|
|
" -w <sec>: Wait time, specifies timeout, default is %f second(s)\n"
|
|
" -p <provider>: Set default provider name, default is '%s'\n"
|
|
" -d: Enable debug output\n"
|
|
" -c: Wait for clean shutdown and report used instance count (for expert users)"
|
|
"\nExample: pvinfo double01\n\n"
|
|
, timeout, defaultProvider.c_str());
|
|
}
|
|
|
|
int haderror;
|
|
|
|
struct GetInfo : public pvac::ClientChannel::InfoCallback,
|
|
public pvac::ClientChannel::ConnectCallback,
|
|
public Tracker
|
|
{
|
|
pvac::ClientChannel chan;
|
|
pvac::Operation op;
|
|
|
|
std::string peerName;
|
|
|
|
explicit GetInfo(pvac::ClientChannel& chan)
|
|
:chan(chan)
|
|
{
|
|
chan.addConnectListener(this);
|
|
}
|
|
virtual ~GetInfo()
|
|
{
|
|
chan.removeConnectListener(this);
|
|
}
|
|
|
|
virtual void connectEvent(const pvac::ConnectEvent& evt) OVERRIDE FINAL
|
|
{
|
|
if(evt.connected) {
|
|
Guard G(doneLock);
|
|
peerName = evt.peerName;
|
|
}
|
|
}
|
|
|
|
virtual void infoDone(const pvac::InfoEvent& evt) OVERRIDE FINAL
|
|
{
|
|
std::string pname;
|
|
{
|
|
Guard G(doneLock);
|
|
pname = peerName;
|
|
}
|
|
|
|
switch(evt.event) {
|
|
case pvac::InfoEvent::Cancel: break;
|
|
case pvac::InfoEvent::Fail:
|
|
std::cerr<<op.name()<<" Error: "<<evt.message<<"\n";
|
|
haderror = 1;
|
|
break;
|
|
case pvac::InfoEvent::Success: {
|
|
std::cout<<op.name()<<"\n"
|
|
"Server: "<<pname<<"\n"
|
|
"Type:\n";
|
|
pvd::format::indent_scope I(std::cout);
|
|
std::cout<<evt.type<<"\n";
|
|
}
|
|
}
|
|
done();
|
|
std::cout.flush();
|
|
}
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
int opt; /* getopt() current option */
|
|
bool debug = false;
|
|
|
|
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); /* Set stdout to line buffering */
|
|
|
|
while ((opt = getopt(argc, argv, ":hVw:p:dc")) != -1) {
|
|
switch (opt) {
|
|
case 'h': /* Print usage */
|
|
usage();
|
|
return 0;
|
|
case 'V': /* Print version */
|
|
{
|
|
fprintf(stdout, "pvAccess %u.%u.%u%s\n",
|
|
EPICS_PVA_MAJOR_VERSION,
|
|
EPICS_PVA_MINOR_VERSION,
|
|
EPICS_PVA_MAINTENANCE_VERSION,
|
|
(EPICS_PVA_DEVELOPMENT_FLAG)?"-SNAPSHOT":"");
|
|
fprintf(stdout, "pvData %u.%u.%u%s\n",
|
|
EPICS_PVD_MAJOR_VERSION,
|
|
EPICS_PVD_MINOR_VERSION,
|
|
EPICS_PVD_MAINTENANCE_VERSION,
|
|
(EPICS_PVD_DEVELOPMENT_FLAG)?"-SNAPSHOT":"");
|
|
fprintf(stdout, "Base %s\n", EPICS_VERSION_FULL);
|
|
return 0;
|
|
}
|
|
case 'w': /* Set PVA timeout value */
|
|
{
|
|
double temp;
|
|
if((epicsScanDouble(optarg, &temp)) != 1 || timeout <= 0.0)
|
|
{
|
|
fprintf(stderr, "'%s' is not a valid timeout value "
|
|
"- ignored. ('pvget -h' for help.)\n", optarg);
|
|
} else {
|
|
timeout = temp;
|
|
}
|
|
}
|
|
break;
|
|
case 'p': /* Set default provider */
|
|
defaultProvider = optarg;
|
|
break;
|
|
case 'd': /* Debug log level */
|
|
debug = true;
|
|
break;
|
|
case 'c': /* Clean-up and report used instance count */
|
|
break;
|
|
case '?':
|
|
fprintf(stderr,
|
|
"Unrecognized option: '-%c'. ('pvinfo -h' for help.)\n",
|
|
optopt);
|
|
return 1;
|
|
case ':':
|
|
fprintf(stderr,
|
|
"Option '-%c' requires an argument. ('pvinfo -h' for help.)\n",
|
|
optopt);
|
|
return 1;
|
|
default :
|
|
usage();
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
if (argc == optind)
|
|
{
|
|
fprintf(stderr, "No pv name(s) specified. ('pvinfo -h' for help.)\n");
|
|
return 1;
|
|
}
|
|
|
|
SET_LOG_LEVEL(debug ? pva::logLevelDebug : pva::logLevelError);
|
|
|
|
std::vector<std::tr1::shared_ptr<GetInfo> > infos;
|
|
|
|
pva::ca::CAClientFactory::start();
|
|
|
|
{
|
|
pvac::ClientProvider prov(defaultProvider);
|
|
|
|
for(int i = optind; i<argc; i++) {
|
|
pvac::ClientChannel chan(prov.connect(argv[i]));
|
|
std::tr1::shared_ptr<GetInfo> info(new GetInfo(chan));
|
|
info->op = chan.info(info.get());
|
|
infos.push_back(info);
|
|
}
|
|
|
|
Tracker::prepare(); // install signal handler
|
|
|
|
{
|
|
Guard G(Tracker::doneLock);
|
|
while(Tracker::inprog.size() && !Tracker::abort) {
|
|
UnGuard U(G);
|
|
if(timeout<=0)
|
|
Tracker::doneEvt.wait();
|
|
else if(!Tracker::doneEvt.wait(timeout)) {
|
|
haderror = 1;
|
|
std::cerr<<"Timeout\n";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return haderror ? 1 : 0;
|
|
}
|