pvaTestClient: put example
This commit is contained in:
@ -10,6 +10,17 @@ and again each time a channel becomes Connected.
|
||||
*/
|
||||
/**
|
||||
|
||||
@page examples_putme Client Put Example
|
||||
|
||||
This example demonstrates a client which issues a Put operation on startup,
|
||||
waits for acknowledgement that the put has been handled,
|
||||
then exits.
|
||||
|
||||
@include putme.cpp
|
||||
|
||||
*/
|
||||
/**
|
||||
|
||||
@page examples_monitorme Client Monitor Example
|
||||
|
||||
This example demonstrates a client which sets up a persistent Monitor operation.
|
||||
|
@ -29,6 +29,7 @@ See the @ref providers page.
|
||||
@section main_examples Examples
|
||||
|
||||
- @ref examples_getme
|
||||
- @ref examples_putme
|
||||
- @ref examples_monitorme
|
||||
|
||||
*/
|
||||
|
@ -5,6 +5,7 @@ include $(TOP)/configure/CONFIG
|
||||
PROD_LIBS += pvAccess pvData ca Com
|
||||
|
||||
TESTPROD_HOST += getme
|
||||
TESTPROD_HOST += putme
|
||||
TESTPROD_HOST += monitorme
|
||||
TESTPROD_HOST += spamme
|
||||
|
||||
|
223
examples/putme.cpp
Normal file
223
examples/putme.cpp
Normal file
@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <set>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <exception>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <signal.h>
|
||||
#define USE_SIGNAL
|
||||
#endif
|
||||
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsGuard.h>
|
||||
#include <epicsGetopt.h>
|
||||
|
||||
//! [Headers]
|
||||
#include <pv/configuration.h>
|
||||
#include <pv/clientFactory.h>
|
||||
#include <pv/caProvider.h>
|
||||
#include <pv/pvaTestClient.h>
|
||||
//! [Headers]
|
||||
|
||||
namespace pvd = epics::pvData;
|
||||
namespace pva = epics::pvAccess;
|
||||
|
||||
namespace {
|
||||
|
||||
typedef epicsGuard<epicsMutex> Guard;
|
||||
typedef epicsGuardRelease<epicsMutex> UnGuard;
|
||||
|
||||
epicsMutex mutex;
|
||||
epicsEvent done;
|
||||
size_t waitingFor;
|
||||
|
||||
#ifdef USE_SIGNAL
|
||||
void alldone(int num)
|
||||
{
|
||||
(void)num;
|
||||
done.signal();
|
||||
}
|
||||
#endif
|
||||
|
||||
struct PutTracker : public TestClientChannel::PutCallback
|
||||
{
|
||||
POINTER_DEFINITIONS(PutTracker);
|
||||
|
||||
TestOperation op;
|
||||
const std::string value;
|
||||
|
||||
PutTracker(TestClientChannel& channel,
|
||||
const pvd::PVStructure::const_shared_pointer& pvReq,
|
||||
const std::string& value)
|
||||
:op(channel.put(this, pvReq)) // put() starts here
|
||||
,value(value)
|
||||
{}
|
||||
|
||||
virtual ~PutTracker()
|
||||
{
|
||||
op.cancel();
|
||||
}
|
||||
|
||||
virtual pvd::PVStructure::const_shared_pointer putBuild(const epics::pvData::StructureConstPtr &build)
|
||||
{
|
||||
pvd::PVStructurePtr root(pvd::getPVDataCreate()->createPVStructure(build));
|
||||
|
||||
pvd::PVScalarPtr valfld(root->getSubFieldT<pvd::PVScalar>("value"));
|
||||
|
||||
valfld->putFrom(value);
|
||||
|
||||
std::cout<<"Put value "<<valfld<<"\n";
|
||||
return root;
|
||||
}
|
||||
|
||||
virtual void putDone(const TestPutEvent &evt)
|
||||
{
|
||||
switch(evt.event) {
|
||||
case TestPutEvent::Fail:
|
||||
std::cerr<<op.name()<<" Error: "<<evt.message<<"\n";
|
||||
break;
|
||||
case TestPutEvent::Cancel:
|
||||
std::cerr<<op.name()<<" Cancelled\n";
|
||||
break;
|
||||
case TestPutEvent::Success:
|
||||
std::cout<<op.name()<<" Done\n";
|
||||
}
|
||||
{
|
||||
Guard G(mutex);
|
||||
waitingFor--;
|
||||
}
|
||||
done.signal();
|
||||
}
|
||||
};
|
||||
|
||||
void usage()
|
||||
{
|
||||
std::cout<<"Usage: putme [-h] [-P <provider>] [-w <timeout>] [-r <request>] pvname=value ...\n";
|
||||
}
|
||||
|
||||
std::string strip(const std::string& inp)
|
||||
{
|
||||
size_t f=inp.find_first_not_of(" \t\n\r"),
|
||||
l=inp.find_last_not_of (" \t\n\r");
|
||||
if(f==inp.npos || f>l)
|
||||
throw std::invalid_argument("Empty string");
|
||||
return inp.substr(f, l-f+1);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
try {
|
||||
double waitTime = 5.0;
|
||||
std::string providerName("pva"), request("field()");
|
||||
|
||||
int opt;
|
||||
while( (opt=getopt(argc, argv, "hP:w:r:"))!=-1)
|
||||
{
|
||||
switch(opt) {
|
||||
case 'P':
|
||||
providerName = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
waitTime = pvd::castUnsafe<double, std::string>(optarg);
|
||||
break;
|
||||
case 'r':
|
||||
request = optarg;
|
||||
break;
|
||||
default:
|
||||
std::cerr<<"Unknown argument "<<opt<<"\n";
|
||||
/* fall through */
|
||||
case 'h':
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::vector<std::pair<std::string, std::string> > args_t;
|
||||
args_t args;
|
||||
|
||||
for(int i=optind; i<argc; i++)
|
||||
{
|
||||
std::string arg(argv[i]);
|
||||
size_t eq = arg.find('=');
|
||||
|
||||
if(eq==arg.npos) {
|
||||
std::cerr<<"Missing '=' in \""<<arg<<"\"\n";
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::string pv (strip(arg.substr(0, eq))),
|
||||
val(strip(arg.substr(eq+1)));
|
||||
args.push_back(std::make_pair(pv, val));
|
||||
}
|
||||
|
||||
// build "pvRequest" which asks for all fields
|
||||
pvd::PVStructure::const_shared_pointer pvReq(pvd::createRequest("field()"));
|
||||
|
||||
// explicitly select configuration from process environment
|
||||
pva::Configuration::shared_pointer conf(pva::ConfigurationBuilder()
|
||||
.push_env()
|
||||
.build());
|
||||
|
||||
// add "pva" provider to registry
|
||||
pva::ClientFactory::start();
|
||||
// add "ca" provider to registry
|
||||
pva::ca::CAClientFactory::start();
|
||||
|
||||
std::cout<<"Use provider: "<<providerName<<"\n";
|
||||
TestClientProvider provider(providerName, conf);
|
||||
|
||||
std::vector<PutTracker::shared_pointer> ops(args.size());
|
||||
|
||||
{
|
||||
Guard G(mutex);
|
||||
waitingFor = args.size();
|
||||
}
|
||||
|
||||
for(size_t i=0; i<args.size(); i++)
|
||||
{
|
||||
args_t::const_reference arg = args[i];
|
||||
|
||||
TestClientChannel chan(provider.connect(arg.first));
|
||||
|
||||
PutTracker::shared_pointer op(new PutTracker(chan, pvReq, arg.second));
|
||||
|
||||
ops.push_back(op);
|
||||
}
|
||||
|
||||
#ifdef USE_SIGNAL
|
||||
signal(SIGINT, alldone);
|
||||
signal(SIGTERM, alldone);
|
||||
signal(SIGQUIT, alldone);
|
||||
#endif
|
||||
|
||||
{
|
||||
Guard G(mutex);
|
||||
while(waitingFor) {
|
||||
UnGuard U(G);
|
||||
if(waitTime<0.0) {
|
||||
done.wait();
|
||||
} else if(!done.wait(waitTime)) {
|
||||
std::cerr<<"Timeout\n";
|
||||
break; // timeout
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} catch(std::exception& e){
|
||||
PRINT_EXCEPTION(e);
|
||||
std::cerr<<"Error: "<<e.what()<<"\n";
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -109,6 +109,7 @@ struct GetPutter : public pva::ChannelPutRequester,
|
||||
LOG(pva::logLevelInfo, "Lost exception in %s: %s", CURRENT_FUNCTION, e.what());
|
||||
}
|
||||
}
|
||||
// check putcb again after UnGuard
|
||||
if(putcb) {
|
||||
pvd::BitSet::shared_pointer all(new pvd::BitSet);
|
||||
all->set(0);
|
||||
@ -132,7 +133,7 @@ struct GetPutter : public pva::ChannelPutRequester,
|
||||
pva::ChannelPut::shared_pointer const & channelPut) OVERRIDE FINAL
|
||||
{
|
||||
Guard G(mutex);
|
||||
if(!getcb) return;
|
||||
if(!putcb) return;
|
||||
|
||||
if(!status.isOK()) {
|
||||
event.message = status.getMessage();
|
||||
|
Reference in New Issue
Block a user