pvaTestClient: simple blocking get/rpc

This commit is contained in:
Michael Davidsaver
2017-07-11 18:12:37 +02:00
parent 99f747bf9f
commit fb28d467d2
8 changed files with 159 additions and 3 deletions

View File

@ -9,6 +9,8 @@ TESTPROD_HOST += putme
TESTPROD_HOST += monitorme
TESTPROD_HOST += spamme
TESTPROD_HOST += miniget
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

32
examples/miniget.cpp Normal file
View File

@ -0,0 +1,32 @@
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
// The simplest possible PVA get
#include <iostream>
#include "pv/clientFactory.h"
#include "pv/pvaTestClient.h"
int main(int argc, char *argv[])
{
try {
if(argc<=1) {
std::cerr<<"Usage: "<<argv[0]<<" <pvname>\n";
return 1;
}
epics::pvAccess::ClientFactory::start();
TestClientProvider provider("pva");
TestClientChannel channel(provider.connect(argv[1]));
std::cout<<channel.name()<<" : "<<channel.get()<<"\n";
}catch(std::exception& e){
std::cerr<<"Error: "<<e.what()<<"\n";
return 1;
}
}

View File

@ -4,7 +4,6 @@ include $(TOP)/configure/CONFIG
LIBRARY += pvAccessIOC
pvAccessIOC_LIBS += pvAccess
pvAccessIOC_LIBS += $(LIB_LIBS)
INC += pv/syncChannelFind.h

View File

@ -5,6 +5,7 @@ SRC_DIRS += $(PVACCESS_SRC)/testing
INC += pv/pvaTestClient.h
LIBSRCS += pvaTestClient.cpp
LIBSRCS += pvaTestClientSync.cpp
LIBSRCS += pvaTestClientGet.cpp
LIBSRCS += pvaTestClientRPC.cpp
LIBSRCS += pvaTestClientMonitor.cpp

View File

@ -5,6 +5,8 @@
#ifndef PVATESTCLIENT_H
#define PVATESTCLIENT_H
#include <stdexcept>
#include <epicsMutex.h>
#include <pv/pvData.h>
@ -106,6 +108,11 @@ struct epicsShareClass TestConnectEvent
bool connected;
};
struct epicsShareClass TestTimeout : public std::runtime_error
{
TestTimeout();
};
//! Represents a single channel
class epicsShareClass TestClientChannel
{
@ -128,6 +135,8 @@ public:
const Options& opt = Options());
~TestClientChannel();
std::string name() const;
//! callback for get() and rpc()
struct epicsShareClass GetCallback {
virtual ~GetCallback() {}
@ -139,12 +148,24 @@ public:
TestOperation get(GetCallback* cb,
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
//! Block and retrieve current PV value
//! @throws TestTimeout or std::runtime_error
epics::pvData::PVStructure::const_shared_pointer
get(double timeout = 3.0,
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
//! Start an RPC call
//! @param cb Completion notification callback. Must outlive TestOperation (call TestOperation::cancel() to force release)
TestOperation rpc(GetCallback* cb,
const epics::pvData::PVStructure::const_shared_pointer& arguments,
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
epics::pvData::PVStructure::const_shared_pointer
rpc(double timeout,
const epics::pvData::PVStructure::const_shared_pointer& arguments,
epics::pvData::PVStructure::const_shared_pointer pvRequest = epics::pvData::PVStructure::const_shared_pointer());
//! callbacks for put()
struct epicsShareClass PutCallback {
virtual ~PutCallback() {}

View File

@ -20,6 +20,10 @@ namespace pva = epics::pvAccess;
typedef epicsGuard<epicsMutex> Guard;
TestTimeout::TestTimeout()
:std::runtime_error("Timeout")
{}
struct TestClientChannel::Impl : public pva::ChannelRequester
{
epicsMutex mutex;
@ -78,7 +82,6 @@ TestOperation::TestOperation(const std::tr1::shared_ptr<Impl>& i)
TestOperation::~TestOperation() {}
std::string TestOperation::name() const
{
return impl ? impl->name() : "<NULL>";
@ -103,6 +106,11 @@ TestClientChannel::TestClientChannel(const std::tr1::shared_ptr<pva::ChannelProv
TestClientChannel::~TestClientChannel() {}
std::string TestClientChannel::name() const
{
return impl ? impl->channel->getChannelName() : "<NONE>";
}
void TestClientChannel::addConnectListener(ConnectCallback* cb)
{
if(!impl) throw std::logic_error("Dead Channel");

View File

@ -5,6 +5,7 @@
#include <epicsMutex.h>
#include <epicsGuard.h>
#include <epicsEvent.h>
#include <pv/current_function.h>
#include <pv/pvData.h>
@ -188,7 +189,6 @@ TestClientChannel::get(TestClientChannel::GetCallback* cb,
return TestOperation(ret);
}
TestOperation
TestClientChannel::put(PutCallback* cb,
epics::pvData::PVStructure::const_shared_pointer pvRequest)

View File

@ -0,0 +1,93 @@
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
#include <epicsMutex.h>
#include <epicsGuard.h>
#include <epicsEvent.h>
#include <pv/current_function.h>
#include <pv/pvData.h>
#include <pv/bitSet.h>
#define epicsExportSharedSymbols
#include "pv/logger.h"
#include "pv/pvaTestClient.h"
#include "pv/pvAccess.h"
namespace pvd = epics::pvData;
namespace pva = epics::pvAccess;
typedef epicsGuard<epicsMutex> Guard;
typedef epicsGuardRelease<epicsMutex> UnGuard;
namespace {
struct GetWait : TestClientChannel::GetCallback
{
epicsMutex mutex;
epicsEvent event;
bool done;
TestGetEvent result;
GetWait() :done(false) {}
virtual ~GetWait() {}
virtual void getDone(const TestGetEvent& evt)
{
{
Guard G(mutex);
if(done) {
LOG(pva::logLevelWarn, "oops, double event to GetCallback");
} else {
result = evt;
done = true;
}
}
event.signal();
}
};
} //namespace
pvd::PVStructure::const_shared_pointer
TestClientChannel::get(double timeout,
pvd::PVStructure::const_shared_pointer pvRequest)
{
GetWait waiter;
TestOperation op(get(&waiter, pvRequest));
{
Guard G(waiter.mutex);
while(!waiter.done) {
UnGuard U(G);
if(!waiter.event.wait(timeout)) {
op.cancel();
throw TestTimeout();
}
}
}
if(waiter.result.event==TestGetEvent::Success)
return waiter.result.value;
else
throw std::runtime_error(waiter.result.message);
}
pvd::PVStructure::const_shared_pointer
TestClientChannel::rpc(double timeout,
const epics::pvData::PVStructure::const_shared_pointer& arguments,
epics::pvData::PVStructure::const_shared_pointer pvRequest)
{
GetWait waiter;
TestOperation op(rpc(&waiter, arguments, pvRequest));
{
Guard G(waiter.mutex);
while(!waiter.done) {
UnGuard U(G);
if(!waiter.event.wait(timeout)) {
op.cancel();
throw TestTimeout();
}
}
}
if(waiter.result.event==TestGetEvent::Success)
return waiter.result.value;
else
throw std::runtime_error(waiter.result.message);
}