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
|
@page examples_monitorme Client Monitor Example
|
||||||
|
|
||||||
This example demonstrates a client which sets up a persistent Monitor operation.
|
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
|
@section main_examples Examples
|
||||||
|
|
||||||
- @ref examples_getme
|
- @ref examples_getme
|
||||||
|
- @ref examples_putme
|
||||||
- @ref examples_monitorme
|
- @ref examples_monitorme
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -5,6 +5,7 @@ include $(TOP)/configure/CONFIG
|
|||||||
PROD_LIBS += pvAccess pvData ca Com
|
PROD_LIBS += pvAccess pvData ca Com
|
||||||
|
|
||||||
TESTPROD_HOST += getme
|
TESTPROD_HOST += getme
|
||||||
|
TESTPROD_HOST += putme
|
||||||
TESTPROD_HOST += monitorme
|
TESTPROD_HOST += monitorme
|
||||||
TESTPROD_HOST += spamme
|
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());
|
LOG(pva::logLevelInfo, "Lost exception in %s: %s", CURRENT_FUNCTION, e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check putcb again after UnGuard
|
||||||
if(putcb) {
|
if(putcb) {
|
||||||
pvd::BitSet::shared_pointer all(new pvd::BitSet);
|
pvd::BitSet::shared_pointer all(new pvd::BitSet);
|
||||||
all->set(0);
|
all->set(0);
|
||||||
@ -132,7 +133,7 @@ struct GetPutter : public pva::ChannelPutRequester,
|
|||||||
pva::ChannelPut::shared_pointer const & channelPut) OVERRIDE FINAL
|
pva::ChannelPut::shared_pointer const & channelPut) OVERRIDE FINAL
|
||||||
{
|
{
|
||||||
Guard G(mutex);
|
Guard G(mutex);
|
||||||
if(!getcb) return;
|
if(!putcb) return;
|
||||||
|
|
||||||
if(!status.isOK()) {
|
if(!status.isOK()) {
|
||||||
event.message = status.getMessage();
|
event.message = status.getMessage();
|
||||||
|
Reference in New Issue
Block a user