diff --git a/pvAccessApp/rpcClient/rpcClient.cpp b/pvAccessApp/rpcClient/rpcClient.cpp index 32f6bf3..2315708 100644 --- a/pvAccessApp/rpcClient/rpcClient.cpp +++ b/pvAccessApp/rpcClient/rpcClient.cpp @@ -97,7 +97,7 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester } } - virtual void requestDone (const epics::pvData::Status &status, epics::pvData::PVStructure::shared_pointer const &pvResponse) + virtual void requestDone(const epics::pvData::Status &status, epics::pvData::PVStructure::shared_pointer const &pvResponse) { if (status.isSuccess()) { @@ -112,23 +112,22 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester Lock lock(m_pointerMutex); response = pvResponse; - // this is OK since calle holds also owns it + // this is OK since calle holds reference to it m_channelRPC.reset(); } - m_event.signal(); - } else { std::cerr << "[" << m_channelName << "] failed to RPC: " << status.toString() << std::endl; { Lock lock(m_pointerMutex); - // this is OK since caller holds also owns it + // this is OK since calle holds reference to it m_channelRPC.reset(); } } + m_event.signal(); } /* @@ -244,8 +243,6 @@ PVStructure::shared_pointer RPCClientImpl::request(PVStructure::shared_pointer p bool allOK = true; - //ClientFactory::start(); - if (m_connected || connect(timeOut)) { shared_ptr rpcRequesterImpl(new ChannelRPCRequesterImpl(m_channel->getChannelName())); @@ -275,8 +272,6 @@ PVStructure::shared_pointer RPCClientImpl::request(PVStructure::shared_pointer p throw epics::pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR, errMsg); } - //ClientFactory::stop(); - if (!allOK) { throw epics::pvAccess::RPCRequestException(Status::STATUSTYPE_ERROR, "RPC request failed"); @@ -289,6 +284,8 @@ PVStructure::shared_pointer RPCClientImpl::request(PVStructure::shared_pointer p RPCClient::shared_pointer RPCClientFactory::create(const std::string & serviceName) { + ClientFactory::start(); + return RPCClient::shared_pointer(new RPCClientImpl(serviceName)); } diff --git a/pvAccessApp/rpcClient/rpcClient.h b/pvAccessApp/rpcClient/rpcClient.h index ce80c68..4179897 100644 --- a/pvAccessApp/rpcClient/rpcClient.h +++ b/pvAccessApp/rpcClient/rpcClient.h @@ -19,6 +19,8 @@ # undef rpcClientEpicsExportSharedSymbols #endif +#include + #include namespace epics @@ -43,6 +45,7 @@ namespace pvAccess * @param pvArgument the argument for the rpc * @param timeout the time in seconds to wait for the response * @return request response. + * @throws RPCRequestException exception thrown on error on timeout. */ virtual epics::pvData::PVStructure::shared_pointer request(epics::pvData::PVStructure::shared_pointer pvRequest, double timeOut) = 0; @@ -67,11 +70,11 @@ namespace pvAccess /** * Performs complete blocking RPC call, opening a channel and connecting to the * service and sending the request. - * The PVStructure sent on connection is null. * * @param serviceName the name of the service to connect to * @param request the request sent to the service * @return the result of the RPC call. + * @throws RPCRequestException exception thrown on error on timeout. */ epics::pvData::PVStructure::shared_pointer sendRequest(const std::string & serviceName, epics::pvData::PVStructure::shared_pointer request, double timeOut); diff --git a/testApp/remote/Makefile b/testApp/remote/Makefile index 3dc2a39..b067758 100644 --- a/testApp/remote/Makefile +++ b/testApp/remote/Makefile @@ -81,6 +81,10 @@ PROD_HOST += rpcServiceExample rpcServiceExample_SRCS += rpcServiceExample.cpp rpcServiceExample_LIBS += pvAccess pvData pvMB Com +PROD_HOST += rpcClientExample +rpcClientExample_SRCS += rpcClientExample.cpp +rpcClientExample_LIBS += pvAccess pvData pvMB Com + TESTSCRIPTS_HOST += $(TESTS:%=%.t) include $(TOP)/configure/RULES diff --git a/testApp/remote/rpcClientExample.cpp b/testApp/remote/rpcClientExample.cpp new file mode 100644 index 0000000..96792c3 --- /dev/null +++ b/testApp/remote/rpcClientExample.cpp @@ -0,0 +1,40 @@ +/** + * 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 +#include + +using namespace epics::pvData; +using namespace epics::pvAccess; + +static StructureConstPtr requestStructure = + getFieldCreate()->createFieldBuilder()-> + add("a", pvString)-> + add("b", pvString)-> + createStructure(); + +#define TIMEOUT 3.0 + +int main() +{ + PVStructure::shared_pointer request = getPVDataCreate()->createPVStructure(requestStructure); + request->getSubField("a")->put("3.14"); + request->getSubField("b")->put("2.71"); + + RPCClient::shared_pointer client = RPCClientFactory::create("sum"); + + try + { + PVStructure::shared_pointer result = client->request(request, TIMEOUT); + std::cout << *result << std::endl; + } catch (RPCRequestException &e) + { + std::cout << e.what() << std::endl; + return 1; + } + + return 0; +} \ No newline at end of file diff --git a/testApp/remote/rpcServiceExample.cpp b/testApp/remote/rpcServiceExample.cpp index cab6dbe..a24f9d5 100644 --- a/testApp/remote/rpcServiceExample.cpp +++ b/testApp/remote/rpcServiceExample.cpp @@ -4,26 +4,16 @@ * in file LICENSE that is included with this distribution. */ -#include +#include #include using namespace epics::pvData; using namespace epics::pvAccess; - - -static StructureConstPtr createResultField() -{ - FieldCreatePtr fieldCreate = getFieldCreate(); - - StringArray fieldNames; - fieldNames.push_back("c"); - FieldConstPtrArray fields; - fields.push_back(fieldCreate->createScalar(pvDouble)); - return fieldCreate->createStructure(fieldNames, fields); -} - -static StructureConstPtr resultStructure = createResultField(); +static StructureConstPtr resultStructure = + getFieldCreate()->createFieldBuilder()-> + add("c", pvDouble)-> + createStructure(); class SumServiceImpl : public RPCService @@ -31,12 +21,16 @@ class SumServiceImpl : PVStructure::shared_pointer request(PVStructure::shared_pointer const & args) throw (RPCRequestException) { - // TODO error handling - double a = atof(args->getStringField("a")->get().c_str()); - double b = atof(args->getStringField("b")->get().c_str()); + PVString::shared_pointer fa = args->getSubField("a"); + PVString::shared_pointer fb = args->getSubField("b"); + if (!fa || !fb) + throw RPCRequestException(Status::STATUSTYPE_ERROR, "'string a' and 'string b' fields required"); + + double a = atof(fa->get().c_str()); + double b = atof(fb->get().c_str()); PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); - result->getDoubleField("c")->put(a+b); + result->getSubField("c")->put(a+b); return result; } };