diff --git a/pvAccessApp/Makefile b/pvAccessApp/Makefile index 5bf90aa..493a266 100644 --- a/pvAccessApp/Makefile +++ b/pvAccessApp/Makefile @@ -85,6 +85,10 @@ SRC_DIRS += $(PVACCESS)/rpcClient INC += rpcClient.h LIBSRCS += rpcClient.cpp +SRC_DIRS += $(PVACCESS)/ca +INC += caProvider.h +LIBSRCS += caProvider.cpp + SRC_DIRS += $(PVACCESS)/mb INC += pvAccessMB.h LIBSRCS += pvAccessMB.cpp @@ -92,5 +96,6 @@ LIBSRCS += pvAccessMB.cpp LIBRARY = pvAccess pvAccess_LIBS += Com pvAccess_LIBS += pvData +pvAccess_LIBS += ca include $(TOP)/configure/RULES diff --git a/pvAccessApp/ca/caProvider.cpp b/pvAccessApp/ca/caProvider.cpp new file mode 100644 index 0000000..dbf12fc --- /dev/null +++ b/pvAccessApp/ca/caProvider.cpp @@ -0,0 +1,111 @@ +/** + * 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 + +#include + +using namespace epics::pvData; +using namespace epics::pvAccess; + +#define EXCEPTION_GUARD(code) try { code; } \ + catch (std::exception &e) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what()); } \ + catch (...) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__); } + +CAChannelProvider::CAChannelProvider() +{ + initialize(); +} + +CAChannelProvider::~CAChannelProvider() +{ +} + +epics::pvData::String CAChannelProvider::getProviderName() +{ + return "ca"; +} + +void CAChannelProvider::destroy() +{ + /* Shut down Channel Access */ + ca_context_destroy(); +} + +ChannelFind::shared_pointer CAChannelProvider::channelFind( + epics::pvData::String const & channelName, + ChannelFindRequester::shared_pointer const & channelFindRequester) +{ + if (channelName.empty()) + throw std::invalid_argument("empty channel name"); + + if (!channelFindRequester) + throw std::invalid_argument("null requester"); + + Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented"); + ChannelFind::shared_pointer nullChannelFind; + EXCEPTION_GUARD(channelFindRequester->channelFindResult(errorStatus, nullChannelFind, false)); + return nullChannelFind; +} + +Channel::shared_pointer CAChannelProvider::createChannel( + epics::pvData::String const & channelName, + ChannelRequester::shared_pointer const & channelRequester, + short priority) +{ + static String emptyString; + return createChannel(channelName, channelRequester, priority, emptyString); +} + +Channel::shared_pointer CAChannelProvider::createChannel( + epics::pvData::String const & channelName, + ChannelRequester::shared_pointer const & channelRequester, + short priority, + epics::pvData::String const & address) +{ + if (!address.empty()) + throw std::invalid_argument("CA does not support 'address' parameter"); + + // TODO + Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented"); + Channel::shared_pointer nullChannel; + EXCEPTION_GUARD(channelRequester->channelCreated(errorStatus, nullChannel)); + return nullChannel; + + // NOTE it's up to internal code to respond w/ error to requester and return 0 in case of errors +} + +void CAChannelProvider::configure(epics::pvData::PVStructure::shared_pointer /*configuration*/) +{ +} + +void CAChannelProvider::flush() +{ +} + +void CAChannelProvider::poll() +{ +} + +void CAChannelProvider::initialize() +{ + /* Create Channel Access */ + int result = ca_context_create(ca_disable_preemptive_callback); + if (result != ECA_NORMAL) { + throw std::runtime_error(std::string("CA error %s occurred while trying " + "to start channel access:") + ca_message(result)); + } + + // TODO create a ca_poll thread +} + +ChannelProvider::shared_pointer createCAChannelProvider() +{ + ChannelProvider::shared_pointer ptr(new CAChannelProvider()); + return ptr; +} + diff --git a/pvAccessApp/ca/caProvider.h b/pvAccessApp/ca/caProvider.h new file mode 100644 index 0000000..7853434 --- /dev/null +++ b/pvAccessApp/ca/caProvider.h @@ -0,0 +1,57 @@ +/** + * 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. + */ + +#ifndef CAPROVIDER_H +#define CAPROVIDER_H + +#include + +namespace epics { +namespace pvAccess { + +class CAChannelProvider : + public ChannelProvider +{ +public: + + CAChannelProvider(); + virtual ~CAChannelProvider(); + + virtual epics::pvData::String getProviderName(); + + virtual void destroy(); + + virtual ChannelFind::shared_pointer channelFind( + epics::pvData::String const & channelName, + ChannelFindRequester::shared_pointer const & channelFindRequester); + + + virtual Channel::shared_pointer createChannel( + epics::pvData::String const & channelName, + ChannelRequester::shared_pointer const & channelRequester, + short priority); + + virtual Channel::shared_pointer createChannel( + epics::pvData::String const & channelName, + ChannelRequester::shared_pointer const & channelRequester, + short priority, + epics::pvData::String const & address); + + virtual void configure(epics::pvData::PVStructure::shared_pointer configuration); + virtual void flush(); + virtual void poll(); + +private: + + void initialize(); +}; + +extern ChannelProvider::shared_pointer createCAChannelProvider(); + + +}} + +#endif /* CAPROVIDER_H */ diff --git a/pvAccessCPP.files b/pvAccessCPP.files index 07ceeac..a035c5a 100644 --- a/pvAccessCPP.files +++ b/pvAccessCPP.files @@ -187,3 +187,5 @@ README runTestServer TODO testApp/remote/pvinfo.cpp +pvAccessApp/ca/caProvider.h +pvAccessApp/ca/caProvider.cpp