├── configure ├── RULES.ioc ├── RULES_DIRS ├── RULES_TOP ├── RULES ├── CONFIG_PVACCESS_VERSION ├── CONFIG_PVACCESS_MODULE ├── Makefile ├── CONFIG ├── CONFIG_SITE └── RELEASE ├── src ├── ioc │ ├── PVACommonRegister.dbd │ ├── PVAClientRegister.dbd │ ├── PVAServerRegister.dbd │ ├── pv │ │ ├── iocreftrack.h │ │ └── syncChannelFind.h │ ├── PVAClientRegister.cpp │ ├── Makefile │ └── reftrackioc.cpp ├── mb │ ├── Makefile │ └── pv │ │ └── pvAccessMB.h ├── factory │ └── Makefile ├── remoteClient │ └── Makefile ├── rpcClient │ └── Makefile ├── rpcService │ ├── Makefile │ ├── rpcService.cpp │ └── pv │ │ ├── rpcServer.h │ │ └── rpcService.h ├── pipelineService │ ├── Makefile │ ├── pipelineService.cpp │ └── pv │ │ ├── pipelineServer.h │ │ └── pipelineService.h ├── pva │ ├── Makefile │ ├── pvaVersionNum.h@ │ ├── pv │ │ ├── clientFactory.h │ │ ├── pvaDefs.h │ │ ├── pvaConstants.h │ │ └── pvaVersion.h │ ├── clientFactory.cpp │ └── pvaVersion.cpp ├── client │ ├── Makefile │ └── clientInfo.cpp ├── utils │ ├── wildcard.cpp │ ├── pv │ │ ├── likely.h │ │ ├── wildcard.h │ │ ├── hexDump.h │ │ ├── requester.h │ │ ├── destroyable.h │ │ ├── logger.h │ │ ├── referenceCountingLock.h │ │ ├── inetAddressUtil.h │ │ └── introspectionRegistry.h │ ├── Makefile │ ├── requester.cpp │ ├── logger.cpp │ ├── referenceCountingLock.cpp │ └── hexDump.cpp ├── ca │ ├── Makefile │ ├── caContext.h │ ├── pv │ │ └── caProvider.h │ ├── notifierConveyor.h │ ├── caContext.cpp │ ├── notifierConveyor.cpp │ ├── caProviderPvt.h │ └── dbdToPv.h ├── remote │ ├── Makefile │ ├── pv │ │ ├── securityImpl.h │ │ ├── transportRegistry.h │ │ ├── beaconHandler.h │ │ └── serializationHelper.h │ ├── abstractResponseHandler.cpp │ ├── beaconHandler.cpp │ ├── serializationHelper.cpp │ └── blockingUDPConnector.cpp ├── server │ ├── Makefile │ ├── beaconServerStatusProvider.cpp │ ├── pv │ │ ├── beaconServerStatusProvider.h │ │ ├── serverChannelImpl.h │ │ ├── baseChannelRequester.h │ │ └── beaconEmitter.h │ └── serverChannelImpl.cpp └── Makefile ├── documentation ├── .gitignore ├── pvtools.dox ├── images │ └── EPICS_white_logo_v02.png ├── _static │ └── css │ │ └── custom.css ├── ownership.dot ├── Makefile ├── index.rst ├── mainpage.dox ├── commit-gh.sh ├── examples.dox ├── conf.py └── client_ownership.dot ├── testApp ├── rtemsTestData.c ├── qemuRunTest.sh ├── rtemsTestHarness.c ├── remote │ ├── testClientFactory.cpp │ ├── rpcWildServiceExample.cpp │ ├── rpcClientExample.cpp │ ├── Makefile │ ├── rpcServiceExample.cpp │ ├── testServerContext.cpp │ ├── rpcServiceAsyncExample.cpp │ ├── pipelineServiceExample.cpp │ └── testRAII.cpp ├── utils │ ├── testAtomicBoolean.cpp │ ├── testHexDump.cpp │ ├── Makefile │ ├── showauth.cpp │ ├── testWildcard.cpp │ └── testFairQueue.cpp ├── pvAccessAllTests.c └── Makefile ├── .gitmodules ├── pvtoolsSrc ├── pvmonitor.cpp ├── Makefile ├── pvutils.h └── pvutils.cpp ├── .gitignore ├── testCa ├── qemuRunTest.sh ├── rtemsTestHarness.c ├── pvCaAllTests.c └── Makefile ├── .ci-local └── defaults.set ├── .readthedocs.yml ├── Makefile ├── runTestServer ├── README.md ├── examples ├── miniget.cpp ├── Makefile ├── miniput.cpp ├── minimonitor.cpp └── mailbox.cpp ├── COPYRIGHT ├── LICENSE ├── notes.md.txt └── .appveyor.yml /configure/RULES.ioc: -------------------------------------------------------------------------------- 1 | #RULES.ioc 2 | include $(CONFIG)/RULES.ioc 3 | -------------------------------------------------------------------------------- /src/ioc/PVACommonRegister.dbd: -------------------------------------------------------------------------------- 1 | registrar("refTrackRegistrar") 2 | -------------------------------------------------------------------------------- /configure/RULES_DIRS: -------------------------------------------------------------------------------- 1 | #RULES_DIRS 2 | include $(CONFIG)/RULES_DIRS 3 | -------------------------------------------------------------------------------- /configure/RULES_TOP: -------------------------------------------------------------------------------- 1 | #RULES_TOP 2 | include $(CONFIG)/RULES_TOP 3 | 4 | -------------------------------------------------------------------------------- /src/ioc/PVAClientRegister.dbd: -------------------------------------------------------------------------------- 1 | registrar("registerStartPVAClient") 2 | -------------------------------------------------------------------------------- /documentation/.gitignore: -------------------------------------------------------------------------------- 1 | *.tag 2 | *.db 3 | *.tmp 4 | html/ 5 | latex/ 6 | -------------------------------------------------------------------------------- /documentation/pvtools.dox: -------------------------------------------------------------------------------- 1 | /** @page pvtools Command Line Utilities 2 | 3 | 4 | 5 | */ -------------------------------------------------------------------------------- /testApp/rtemsTestData.c: -------------------------------------------------------------------------------- 1 | /* no test data */ 2 | const void* epicsRtemsFSImage = 0; 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule ".ci"] 2 | path = .ci 3 | url = https://github.com/epics-base/ci-scripts 4 | -------------------------------------------------------------------------------- /pvtoolsSrc/pvmonitor.cpp: -------------------------------------------------------------------------------- 1 | #define PVMONITOR 2 | #define EXECNAME "pvmonitor" 3 | #include "pvget.cpp" 4 | -------------------------------------------------------------------------------- /src/ioc/PVAServerRegister.dbd: -------------------------------------------------------------------------------- 1 | registrar("registerStartPVAServer") 2 | include "PVACommonRegister.dbd" 3 | -------------------------------------------------------------------------------- /src/mb/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/mb 4 | 5 | INC += pv/pvAccessMB.h 6 | -------------------------------------------------------------------------------- /documentation/images/EPICS_white_logo_v02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/epics-base/pvAccessCPP/HEAD/documentation/images/EPICS_white_logo_v02.png -------------------------------------------------------------------------------- /configure/RULES: -------------------------------------------------------------------------------- 1 | # RULES 2 | 3 | include $(CONFIG)/RULES 4 | 5 | # Library should be rebuilt because LIBOBJS may have changed. 6 | $(LIBNAME): ../Makefile 7 | -------------------------------------------------------------------------------- /src/factory/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/factory 4 | 5 | pvAccess_SRCS += ChannelAccessFactory.cpp 6 | -------------------------------------------------------------------------------- /src/remoteClient/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/remoteClient 4 | 5 | pvAccess_SRCS += clientContextImpl.cpp 6 | -------------------------------------------------------------------------------- /documentation/_static/css/custom.css: -------------------------------------------------------------------------------- 1 | .wy-side-nav-search { 2 | background-color: #18334B; 3 | } 4 | 5 | .wy-side-nav-search input[type="text"] { 6 | border-color: #18334b; 7 | } -------------------------------------------------------------------------------- /src/rpcClient/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/rpcClient 4 | 5 | INC += pv/rpcClient.h 6 | 7 | pvAccess_SRCS += rpcClient.cpp 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /cfg/ 2 | /bin/ 3 | /lib/ 4 | /db/ 5 | /dbd/ 6 | /html/ 7 | /include/ 8 | /templates/ 9 | /configure/*.local 10 | envPaths 11 | O.*/ 12 | /QtC-* 13 | *.orig 14 | *.log 15 | .*.swp 16 | -------------------------------------------------------------------------------- /testCa/qemuRunTest.sh: -------------------------------------------------------------------------------- 1 | qemu-system-i386 --kernel O.RTEMS-pc386/rtemsTestHarness -netdev user,id=mynet0 -device ne2k_isa,netdev=mynet0 -redir tcp:5075::5075 -redir udp:5076::5076 -m 1024 --no-reboot -curses 2 | -------------------------------------------------------------------------------- /testApp/qemuRunTest.sh: -------------------------------------------------------------------------------- 1 | qemu-system-i386 --kernel O.RTEMS-pc386/rtemsTestHarness -netdev user,id=mynet0 -device ne2k_isa,netdev=mynet0 -redir tcp:5075::5075 -redir udp:5076::5076 -m 1024 --no-reboot -curses 2 | -------------------------------------------------------------------------------- /src/ioc/pv/iocreftrack.h: -------------------------------------------------------------------------------- 1 | #ifndef IOCREFTRACK_H 2 | #define IOCREFTRACK_H 3 | 4 | #include 5 | 6 | namespace epics {namespace pvAccess { 7 | 8 | epicsShareExtern void refTrackRegistrar(); 9 | 10 | }} 11 | 12 | #endif // IOCREFTRACK_H 13 | -------------------------------------------------------------------------------- /src/rpcService/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/rpcService 4 | 5 | INC += pv/rpcService.h 6 | INC += pv/rpcServer.h 7 | 8 | pvAccess_SRCS += rpcService.cpp 9 | pvAccess_SRCS += rpcServer.cpp 10 | -------------------------------------------------------------------------------- /.ci-local/defaults.set: -------------------------------------------------------------------------------- 1 | # EPICS Base 2 | BASE_DIRNAME=base 3 | BASE_REPONAME=epics-base 4 | BASE_REPOOWNER=epics-base 5 | BASE_VARNAME=EPICS_BASE 6 | BASE_RECURSIVE=NO 7 | 8 | MODULES=PVDATA 9 | 10 | PVDATA_REPONAME=pvDataCPP 11 | PVDATA_REPOOWNER=epics-base 12 | -------------------------------------------------------------------------------- /documentation/ownership.dot: -------------------------------------------------------------------------------- 1 | digraph ownership { 2 | MyClient [shape=box]; 3 | Channel; 4 | ChannelRequester [shape=box]; 5 | MyClient -> Channel [color=red]; 6 | Channel -> ChannelRequester [color=red, style=dashed]; 7 | ChannelRequester -> MyClient [color=green]; 8 | } 9 | -------------------------------------------------------------------------------- /src/pipelineService/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/pipelineService 4 | 5 | INC += pv/pipelineService.h 6 | INC += pv/pipelineServer.h 7 | 8 | pvAccess_SRCS += pipelineService.cpp 9 | pvAccess_SRCS += pipelineServer.cpp 10 | -------------------------------------------------------------------------------- /src/pva/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/pva 4 | 5 | INC += pv/pvaConstants.h 6 | INC += pv/pvaDefs.h 7 | INC += pv/pvaVersion.h 8 | INC += pv/pvaVersionNum.h 9 | INC += pv/clientFactory.h 10 | 11 | pvAccess_SRCS += pvaVersion.cpp 12 | pvAccess_SRCS += clientFactory.cpp 13 | -------------------------------------------------------------------------------- /src/pipelineService/pipelineService.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #define epicsExportSharedSymbols 8 | #include 9 | -------------------------------------------------------------------------------- /testCa/rtemsTestHarness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright information and license terms for this software can be 3 | * found in the file LICENSE that is included with the distribution 4 | */ 5 | 6 | extern void pvCaAllTests(void); 7 | 8 | int main(int argc, char **argv) 9 | { 10 | pvCaAllTests(); /* calls epicsExit(0) */ 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /testApp/rtemsTestHarness.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright information and license terms for this software can be 3 | * found in the file LICENSE that is included with the distribution 4 | */ 5 | 6 | extern void pvAccessAllTests(void); 7 | 8 | int main(int argc, char **argv) 9 | { 10 | pvAccessAllTests(); /* calls epicsExit(0) */ 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /src/pva/pvaVersionNum.h@: -------------------------------------------------------------------------------- 1 | #ifndef VERSION_H_ 2 | # error include pvaVersion.h, not this header 3 | #endif 4 | #define EPICS_PVA_MAJOR_VERSION @EPICS_PVA_MAJOR_VERSION@ 5 | #define EPICS_PVA_MINOR_VERSION @EPICS_PVA_MINOR_VERSION@ 6 | #define EPICS_PVA_MAINTENANCE_VERSION @EPICS_PVA_MAINTENANCE_VERSION@ 7 | #define EPICS_PVA_DEVELOPMENT_FLAG @EPICS_PVA_DEVELOPMENT_FLAG@ 8 | -------------------------------------------------------------------------------- /documentation/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: gen 3 | 4 | clean: 5 | rm -rf doxygen_sqlite3.db html 6 | 7 | gen: libstdc++.tag 8 | doxygen 9 | 10 | commit: gen 11 | touch html/.nojekyll 12 | ./commit-gh.sh documentation/html/ html/.nojekyll html/*.* html/search/*.* 13 | 14 | libstdc++.tag: 15 | wget -O $@ https://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag 16 | 17 | .PHONY: all clean gen commit 18 | -------------------------------------------------------------------------------- /configure/CONFIG_PVACCESS_VERSION: -------------------------------------------------------------------------------- 1 | # Version number for the PV Access API and shared library 2 | 3 | EPICS_PVA_MAJOR_VERSION = 7 4 | EPICS_PVA_MINOR_VERSION = 1 5 | EPICS_PVA_MAINTENANCE_VERSION = 8 6 | 7 | # Development flag, set to zero for release versions 8 | 9 | EPICS_PVA_DEVELOPMENT_FLAG = 1 10 | 11 | # Immediately after a release the MAINTENANCE_VERSION 12 | # will be incremented and the DEVELOPMENT_FLAG set to 1 13 | -------------------------------------------------------------------------------- /testApp/remote/testClientFactory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | epics::pvAccess::ClientFactory::start(); 8 | epics::pvAccess::ChannelProviderRegistry::clients()->getProvider("pva"); 9 | epics::pvAccess::ClientFactory::stop(); 10 | 11 | //epicsThreadSleep ( 3.0 ); 12 | //epicsExitCallAtExits(); 13 | 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /testCa/pvCaAllTests.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Run all caProvider tests 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | int testCaProvider(void); 11 | int testConveyor(void); 12 | 13 | void pvCaAllTests(void) 14 | { 15 | testHarness(); 16 | runTest(testConveyor); 17 | runTest(testCaProvider); 18 | 19 | epicsExit(0); /* Trigger test harness */ 20 | } 21 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Build documentation in the documentation/ directory with Sphinx 9 | sphinx: 10 | configuration: documentation/conf.py 11 | 12 | # Build documentation with MkDocs 13 | #mkdocs: 14 | # configuration: mkdocs.yml 15 | 16 | # Optionally build your docs in additional formats such as PDF and ePub 17 | formats: all 18 | -------------------------------------------------------------------------------- /src/client/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/client 4 | 5 | INC += pv/monitor.h 6 | INC += pv/pvAccess.h 7 | INC += pva/client.h 8 | 9 | pvAccess_SRCS += pvAccess.cpp 10 | pvAccess_SRCS += monitor.cpp 11 | pvAccess_SRCS += client.cpp 12 | pvAccess_SRCS += clientSync.cpp 13 | pvAccess_SRCS += clientGet.cpp 14 | pvAccess_SRCS += clientPut.cpp 15 | pvAccess_SRCS += clientRPC.cpp 16 | pvAccess_SRCS += clientMonitor.cpp 17 | pvAccess_SRCS += clientInfo.cpp 18 | -------------------------------------------------------------------------------- /documentation/index.rst: -------------------------------------------------------------------------------- 1 | pvAccess (C++) Library 2 | ====================== 3 | 4 | .. toctree:: 5 | :hidden: 6 | 7 | EPICS Website 8 | EPICS Documentation Home 9 | 10 | 11 | .. toctree:: 12 | :maxdepth: 1 13 | :caption: pvAccessCPP 14 | 15 | Reference Manual and API Documentation 16 | Source Code Repository on GitHub 17 | -------------------------------------------------------------------------------- /configure/CONFIG_PVACCESS_MODULE: -------------------------------------------------------------------------------- 1 | #************************************************************************* 2 | # EPICS BASE is distributed subject to a Software License Agreement found 3 | # in file LICENSE that is included with this distribution. 4 | #************************************************************************* 5 | 6 | # LIbraries needed to link a pvAccess tool 7 | EPICS_BASE_PVA_CORE_LIBS = pvAccessIOC pvAccessCA pvAccess pvData 8 | 9 | # pvAccess depends on netapi32 10 | PROD_SYS_LIBS_WIN32 += netapi32 11 | -------------------------------------------------------------------------------- /src/utils/wildcard.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #define epicsExportSharedSymbols 10 | #include 11 | 12 | using namespace epics::pvAccess; 13 | 14 | int 15 | Wildcard::wildcardfit (const char *wildcard, const char *test) 16 | { 17 | return epicsStrGlobMatch(test, wildcard); 18 | } 19 | -------------------------------------------------------------------------------- /src/utils/pv/likely.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef LIKELY_H_ 8 | #define LIKELY_H_ 9 | 10 | #if defined(__GNUC__) && __GNUC__ >= 3 11 | #define likely(x) __builtin_expect (x, 1) 12 | #define unlikely(x) __builtin_expect (x, 0) 13 | #else 14 | #define likely(x) (x) 15 | #define unlikely(x) (x) 16 | #endif 17 | 18 | #endif /* LIKELY_H_ */ 19 | -------------------------------------------------------------------------------- /src/ioc/PVAClientRegister.cpp: -------------------------------------------------------------------------------- 1 | /*PVAClientRegister.cpp */ 2 | /** 3 | * Copyright - See the COPYRIGHT that is included with this distribution. 4 | * EPICS pvData is distributed subject to a Software License Agreement found 5 | * in file LICENSE that is included with this distribution. 6 | */ 7 | /** 8 | * @author mrk 9 | * @date 2013.08.05 10 | */ 11 | 12 | /* Author: Marty Kraimer */ 13 | 14 | #include 15 | 16 | static void registerStartPVAClient(void) {} 17 | 18 | extern "C" { 19 | epicsExportRegistrar(registerStartPVAClient); 20 | } 21 | -------------------------------------------------------------------------------- /configure/Makefile: -------------------------------------------------------------------------------- 1 | #************************************************************************* 2 | # EPICS BASE is distributed subject to a Software License Agreement found 3 | # in file LICENSE that is included with this distribution. 4 | #************************************************************************* 5 | TOP=.. 6 | 7 | include $(TOP)/configure/CONFIG 8 | 9 | CFG += CONFIG_PVACCESS_VERSION 10 | CFG += CONFIG_PVACCESS_MODULE 11 | 12 | TARGETS = $(CONFIG_TARGETS) 13 | CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) 14 | 15 | include $(TOP)/configure/RULES 16 | -------------------------------------------------------------------------------- /src/pva/pv/clientFactory.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef CLIENTFACTORY_H 8 | #define CLIENTFACTORY_H 9 | 10 | #include 11 | 12 | namespace epics { 13 | namespace pvAccess { 14 | 15 | class epicsShareClass ClientFactory { 16 | public: 17 | static void start(); 18 | static void stop(); 19 | }; 20 | 21 | } 22 | } 23 | 24 | #endif /* CLIENTFACTORY_H */ 25 | -------------------------------------------------------------------------------- /src/ca/Makefile: -------------------------------------------------------------------------------- 1 | TOP = ../.. 2 | include $(TOP)/configure/CONFIG 3 | 4 | LIBRARY += pvAccessCA 5 | pvAccessCA_LIBS += pvAccess pvData ca Com 6 | 7 | SHRLIB_VERSION ?= $(EPICS_PVA_MAJOR_VERSION).$(EPICS_PVA_MINOR_VERSION).$(EPICS_PVA_MAINTENANCE_VERSION) 8 | 9 | # needed for Windows 10 | LIB_SYS_LIBS_WIN32 += netapi32 ws2_32 11 | 12 | INC += pv/caProvider.h 13 | 14 | pvAccessCA_SRCS += caProvider.cpp 15 | pvAccessCA_SRCS += caContext.cpp 16 | pvAccessCA_SRCS += caChannel.cpp 17 | pvAccessCA_SRCS += dbdToPv.cpp 18 | pvAccessCA_SRCS += notifierConveyor.cpp 19 | 20 | include $(TOP)/configure/RULES 21 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for the EPICS V4 pvAccess module 2 | 3 | TOP = . 4 | include $(TOP)/configure/CONFIG 5 | 6 | DIRS := configure 7 | 8 | DIRS += src 9 | src_DEPEND_DIRS = configure 10 | 11 | DIRS += src/ca 12 | src/ca_DEPEND_DIRS = src 13 | 14 | DIRS += src/ioc 15 | src/ioc_DEPEND_DIRS = src 16 | 17 | DIRS += pvtoolsSrc 18 | pvtoolsSrc_DEPEND_DIRS = src src/ca 19 | 20 | DIRS += testApp 21 | testApp_DEPEND_DIRS = src 22 | 23 | 24 | DIRS += testCa 25 | testCa_DEPEND_DIRS = src src/ca 26 | 27 | 28 | DIRS += examples 29 | examples_DEPEND_DIRS += src src/ca 30 | 31 | include $(TOP)/configure/RULES_TOP 32 | -------------------------------------------------------------------------------- /src/pva/clientFactory.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #define epicsExportSharedSymbols 12 | #include 13 | 14 | using namespace epics::pvData; 15 | using namespace epics::pvAccess; 16 | 17 | void ClientFactory::start() 18 | { 19 | // 'pva' registration in ChannelAccessFactory.cpp 20 | } 21 | 22 | void ClientFactory::stop() {} 23 | -------------------------------------------------------------------------------- /runTestServer: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "X$EPICS_BASE" = "X" ]; then 4 | echo "Environment variable EPICS_BASE not set." 5 | exit 1 6 | fi 7 | 8 | if [ "X$EPICS_HOST_ARCH" = "X" ]; then 9 | EPICS_HOST_ARCH=`$EPICS_BASE/startup/EpicsHostArch` 10 | if [ "X$EPICS_HOST_ARCH" = "X" ]; then 11 | echo "Environment variable EPICS_HOST_ARCH not set, failed to auto-detect." 12 | exit 1 13 | fi 14 | echo "Environment variable EPICS_HOST_ARCH not set, detected $EPICS_HOST_ARCH." 15 | fi 16 | 17 | # testServer 18 | echo "Starting pvAccess C++ test server..." 19 | ./bin/$EPICS_HOST_ARCH/testServer $* 20 | -------------------------------------------------------------------------------- /src/remote/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/remote 4 | 5 | INC += pv/security.h 6 | INC += pv/serializationHelper.h 7 | 8 | pvAccess_SRCS += blockingUDPTransport.cpp 9 | pvAccess_SRCS += blockingUDPConnector.cpp 10 | pvAccess_SRCS += beaconHandler.cpp 11 | pvAccess_SRCS += blockingTCPConnector.cpp 12 | pvAccess_SRCS += channelSearchManager.cpp 13 | pvAccess_SRCS += abstractResponseHandler.cpp 14 | pvAccess_SRCS += blockingTCPAcceptor.cpp 15 | pvAccess_SRCS += transportRegistry.cpp 16 | pvAccess_SRCS += serializationHelper.cpp 17 | pvAccess_SRCS += codec.cpp 18 | pvAccess_SRCS += security.cpp 19 | -------------------------------------------------------------------------------- /testApp/utils/testAtomicBoolean.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | using namespace epics::pvAccess; 7 | 8 | MAIN(testAtomicBoolean) 9 | { 10 | testPlan(5); 11 | testDiag("Tests for AtomicBoolean"); 12 | 13 | AtomicBoolean ab; 14 | 15 | testOk(ab.get() == false, "Initial state"); 16 | ab.set(); 17 | testOk(ab.get() == true, "Set to true"); 18 | ab.set(); 19 | testOk(ab.get() == true, "Set to true (again)"); 20 | ab.clear(); 21 | testOk(ab.get() == false, "Set to false"); 22 | ab.clear(); 23 | testOk(ab.get() == false, "Set to again"); 24 | 25 | return testDone(); 26 | } 27 | -------------------------------------------------------------------------------- /src/server/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_SRC)/server 4 | 5 | INC += pv/serverContext.h 6 | INC += pv/beaconServerStatusProvider.h 7 | INC += pva/server.h 8 | INC += pva/sharedstate.h 9 | 10 | pvAccess_SRCS += responseHandlers.cpp 11 | pvAccess_SRCS += serverContext.cpp 12 | pvAccess_SRCS += serverChannelImpl.cpp 13 | pvAccess_SRCS += baseChannelRequester.cpp 14 | pvAccess_SRCS += beaconEmitter.cpp 15 | pvAccess_SRCS += beaconServerStatusProvider.cpp 16 | pvAccess_SRCS += server.cpp 17 | pvAccess_SRCS += sharedstate_pv.cpp 18 | pvAccess_SRCS += sharedstate_channel.cpp 19 | pvAccess_SRCS += sharedstate_rpc.cpp 20 | pvAccess_SRCS += sharedstate_put.cpp 21 | -------------------------------------------------------------------------------- /testApp/utils/testHexDump.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | using namespace epics::pvData; 10 | using namespace epics::pvAccess; 11 | 12 | MAIN(testHexDump) 13 | { 14 | testPlan(1); 15 | testDiag("Tests for hexDump"); 16 | 17 | char TO_DUMP[] = "pvAccess dump test\0\1\2\3\4\5\6\xfd\xfe\xff"; 18 | 19 | std::ostringstream msg; 20 | msg<API components @endhtmlonly 8 | - @ref pvarelease_notes 9 | - API documentation 10 | - @ref pvac page 11 | - @ref pvas page 12 | - @ref providers page 13 | - @ref pvtools 14 | 15 | @section main_examples API usage Examples 16 | 17 | - Simple synchronous (blocking) examples 18 | - @ref examples_miniget 19 | - @ref examples_miniput 20 | - @ref examples_minimonitor 21 | - More complete callback based examples 22 | - @ref examples_getme 23 | - @ref examples_putme 24 | - @ref examples_monitorme 25 | - @ref examples_mailbox 26 | */ 27 | 28 | #endif /* MAINPAGE_H */ 29 | -------------------------------------------------------------------------------- /examples/miniget.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright information and license terms for this software can be 3 | * found in the file LICENSE that is included with the distribution 4 | */ 5 | // The simplest possible PVA get 6 | 7 | #include 8 | 9 | #include "pva/client.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | try { 14 | if(argc<=1) { 15 | std::cerr<<"Usage: "<\n"; 16 | return 1; 17 | } 18 | 19 | pvac::ClientProvider provider("pva"); 20 | 21 | pvac::ClientChannel channel(provider.connect(argv[1])); 22 | 23 | std::cout< 5 | #include 6 | #include 7 | 8 | namespace epics { 9 | namespace pvAccess { 10 | 11 | /** 12 | * Globally unique ID. 13 | */ 14 | struct ServerGUID { 15 | char value[12]; 16 | }; 17 | 18 | typedef epicsInt32 pvAccessID; 19 | 20 | class AtomicBoolean 21 | { 22 | public: 23 | AtomicBoolean() : val(false) {} 24 | 25 | void set() { 26 | epicsGuard G(mutex); 27 | val = true; 28 | } 29 | void clear() { 30 | epicsGuard G(mutex); 31 | val = false; 32 | } 33 | 34 | bool get() const { 35 | epicsGuard G(mutex); 36 | return val; 37 | } 38 | private: 39 | bool val; 40 | mutable epicsMutex mutex; 41 | }; 42 | 43 | }} 44 | 45 | #endif // PVADEFS_H 46 | -------------------------------------------------------------------------------- /testApp/pvAccessAllTests.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Run pvData tests as a batch. 3 | * 4 | * Do *not* include performance measurements here, they don't help to 5 | * prove functionality (which is the point of this convenience routine). 6 | */ 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* utils */ 14 | int testAtomicBoolean(void); 15 | int testHexDump(void); 16 | int testInetAddressUtils(void); 17 | 18 | /* remote */ 19 | int testCodec(void); 20 | int testChannelAccess(void); 21 | 22 | void pvAccessAllTests(void) 23 | { 24 | testHarness(); 25 | 26 | /* utils */ 27 | runTest(testAtomicBoolean); 28 | runTest(testHexDump); 29 | runTest(testInetAddressUtils); 30 | 31 | /* remote */ 32 | runTest(testCodec); 33 | runTest(testChannelAccess); 34 | 35 | epicsExit(0); /* Trigger test harness */ 36 | } 37 | -------------------------------------------------------------------------------- /src/remote/pv/securityImpl.h: -------------------------------------------------------------------------------- 1 | #ifndef SECURITYIMPL_H 2 | #define SECURITYIMPL_H 3 | 4 | #include 5 | 6 | #include "security.h" 7 | 8 | namespace epics { 9 | namespace pvAccess { 10 | 11 | 12 | class AuthNZHandler : 13 | public ResponseHandler 14 | { 15 | EPICS_NOT_COPYABLE(AuthNZHandler) 16 | public: 17 | AuthNZHandler(Context* context) : 18 | ResponseHandler(context, "authNZ message") 19 | { 20 | } 21 | 22 | virtual ~AuthNZHandler() {} 23 | 24 | virtual void handleResponse(osiSockAddr* responseFrom, 25 | Transport::shared_pointer const & transport, 26 | epics::pvData::int8 version, 27 | epics::pvData::int8 command, 28 | size_t payloadSize, 29 | epics::pvData::ByteBuffer* payloadBuffer); 30 | }; 31 | 32 | }} 33 | 34 | #endif // SECURITYIMPL_H 35 | -------------------------------------------------------------------------------- /configure/CONFIG: -------------------------------------------------------------------------------- 1 | # CONFIG - Load build configuration data 2 | # 3 | # Do not make changes to this file! 4 | 5 | # Allow user to override where the build rules come from 6 | RULES = $(EPICS_BASE) 7 | 8 | # RELEASE files point to other application tops 9 | include $(TOP)/configure/RELEASE 10 | -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common 11 | ifdef T_A 12 | -include $(TOP)/configure/RELEASE.Common.$(T_A) 13 | -include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A) 14 | endif 15 | 16 | CONFIG = $(RULES)/configure 17 | include $(CONFIG)/CONFIG 18 | 19 | # Override the Base definition: 20 | INSTALL_LOCATION = $(TOP) 21 | 22 | # CONFIG_SITE files contain other build configuration settings 23 | include $(TOP)/configure/CONFIG_SITE 24 | -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common 25 | ifdef T_A 26 | -include $(TOP)/configure/CONFIG_SITE.Common.$(T_A) 27 | -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) 28 | endif 29 | 30 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | include $(TOP)/configure/CONFIG 4 | 5 | PROD_LIBS += pvAccessCA ca pvAccess pvData Com 6 | PROD_SYS_LIBS_WIN32 += netapi32 ws2_32 7 | 8 | TESTPROD_HOST += getme 9 | getme_SRCS = getme.cpp 10 | 11 | TESTPROD_HOST += putme 12 | putme_SRCS = putme.cpp 13 | 14 | TESTPROD_HOST += monitorme 15 | monitorme_SRCS = monitorme.cpp 16 | 17 | TESTPROD_HOST += spamme 18 | spamme_SRCS = spamme.cpp 19 | 20 | TESTPROD_HOST += mailbox 21 | mailbox_SRCS += mailbox.cpp 22 | 23 | TESTPROD_HOST += epicschat 24 | epicschat_SRCS += epicschat.cpp 25 | 26 | TESTPROD_HOST += lazycounter 27 | lazycounter_SRCS += lazycounter.cpp 28 | 29 | TESTPROD_HOST += miniget 30 | miniget_SRCS = miniget.cpp 31 | 32 | TESTPROD_HOST += miniput 33 | miniput_SRCS = miniput.cpp 34 | 35 | TESTPROD_HOST += minimonitor 36 | minimonitor_SRCS = minimonitor.cpp 37 | 38 | include $(TOP)/configure/RULES 39 | #---------------------------------------- 40 | # ADD RULES AFTER THIS LINE 41 | 42 | -------------------------------------------------------------------------------- /pvtoolsSrc/Makefile: -------------------------------------------------------------------------------- 1 | TOP=.. 2 | 3 | include $(TOP)/configure/CONFIG 4 | 5 | USR_CPPFLAGS += -I$(TOP)/src/utils 6 | USR_CPPFLAGS += -I$(TOP)/src/remote 7 | 8 | PROD_DEFAULT += pvget 9 | pvget_SRCS += pvget.cpp 10 | pvget_SRCS += pvutils.cpp 11 | 12 | PROD_DEFAULT += pvmonitor 13 | pvmonitor_SRCS += pvmonitor.cpp 14 | pvmonitor_SRCS += pvutils.cpp 15 | 16 | PROD_DEFAULT += pvput 17 | pvput_SRCS += pvput.cpp 18 | pvput_SRCS += pvutils.cpp 19 | 20 | PROD_DEFAULT += pvcall 21 | pvcall_SRCS += pvcall.cpp 22 | pvcall_SRCS += pvutils.cpp 23 | 24 | PROD_DEFAULT += pvinfo 25 | pvinfo_SRCS += pvinfo.cpp 26 | pvinfo_SRCS += pvutils.cpp 27 | 28 | PROD_DEFAULT += pvlist 29 | pvlist_SRCS += pvlist.cpp 30 | 31 | PROD_LIBS += pvAccessCA pvAccess pvData ca Com 32 | 33 | PROD_SYS_LIBS_WIN32 += netapi32 ws2_32 34 | 35 | PROD_vxWorks = -nil- 36 | PROD_RTEMS = -nil- 37 | PROD_iOS = -nil- 38 | 39 | include $(TOP)/configure/RULES 40 | #---------------------------------------- 41 | # ADD RULES AFTER THIS LINE 42 | 43 | -------------------------------------------------------------------------------- /examples/miniput.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright information and license terms for this software can be 3 | * found in the file LICENSE that is included with the distribution 4 | */ 5 | // The simplest possible PVA put 6 | 7 | #include 8 | 9 | #include "pva/client.h" 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | try { 14 | if(argc<=2) { 15 | std::cerr<<"Usage: "< \n"; 16 | return 1; 17 | } 18 | 19 | pvac::ClientProvider provider("pva"); 20 | 21 | pvac::ClientChannel channel(provider.connect(argv[1])); 22 | 23 | std::cout<<"Before "< 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #include 16 | 17 | #define epicsExportSharedSymbols 18 | #include 19 | 20 | using std::string; 21 | 22 | namespace epics { namespace pvAccess { 23 | 24 | 25 | string getMessageTypeName(MessageType messageType) 26 | { 27 | switch(messageType) { 28 | case infoMessage: return "info"; 29 | case warningMessage: return "warning"; 30 | case errorMessage: return "error"; 31 | case fatalErrorMessage: return "fatalError"; 32 | default: return "unknown"; 33 | } 34 | } 35 | 36 | void Requester::message(std::string const & message,MessageType messageType) 37 | { 38 | std::cerr << "[" << getRequesterName() << "] " << getMessageTypeName(messageType) << " : " << message << "\n"; 39 | } 40 | 41 | }} 42 | -------------------------------------------------------------------------------- /src/mb/pv/pvAccessMB.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef _PVACCESSMB_H_ 8 | #define _PVACCESSMB_H_ 9 | 10 | /* this header is deprecated */ 11 | 12 | #define MB_DECLARE(NAME, SIZE) 13 | #define MB_DECLARE_EXTERN(NAME) 14 | 15 | #define MB_POINT_ID(NAME, STAGE, STAGE_DESC, ID) 16 | 17 | #define MB_INC_AUTO_ID(NAME) 18 | #define MB_POINT(NAME, STAGE, STAGE_DESC) 19 | 20 | #define MB_POINT_CONDITIONAL(NAME, STAGE, STAGE_DESC, COND) 21 | 22 | #define MB_NORMALIZE(NAME) 23 | 24 | #define MB_STATS(NAME, STREAM) 25 | #define MB_STATS_OPT(NAME, STAGE_ONLY, SKIP_FIRST_N_SAMPLES, STREAM) 26 | 27 | #define MB_CSV_EXPORT(NAME, STREAM) 28 | #define MB_CSV_EXPORT_OPT(NAME, STAGE_ONLY, SKIP_FIRST_N_SAMPLES, STREAM) 29 | #define MB_CSV_IMPORT(NAME, STREAM) 30 | 31 | #define MB_PRINT(NAME, STREAM) 32 | #define MB_PRINT_OPT(NAME, STAGE_ONLY, SKIP_FIRST_N_SAMPLES, STREAM) 33 | 34 | #define MB_INIT 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /testApp/utils/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_TEST)/utils 4 | 5 | TESTPROD_HOST += testAtomicBoolean 6 | testAtomicBoolean_SRCS = testAtomicBoolean.cpp 7 | testHarness_SRCS += testAtomicBoolean.cpp 8 | TESTS += testAtomicBoolean 9 | 10 | TESTPROD_HOST += testHexDump 11 | testHexDump_SRCS = testHexDump.cpp 12 | testHarness_SRCS += testHexDump.cpp 13 | TESTS += testHexDump 14 | 15 | TESTPROD_HOST += testInetAddressUtils 16 | testInetAddressUtils_SRCS = testInetAddressUtils.cpp 17 | testHarness_SRCS += testInetAddressUtils.cpp 18 | TESTS += testInetAddressUtils 19 | 20 | TESTPROD_HOST += configurationTest 21 | configurationTest_SRCS += configurationTest.cpp 22 | #testHarness_SRCS += configurationTest.cpp 23 | TESTS += configurationTest 24 | 25 | TESTPROD_HOST += testFairQueue 26 | testFairQueue_SRCS += testFairQueue 27 | TESTS += testFairQueue 28 | 29 | TESTPROD_HOST += testWildcard 30 | testWildcard_SRCS = testWildcard.cpp 31 | testHarness_SRCS += testWildcard.cpp 32 | TESTS += testWildcard 33 | 34 | TESTPROD_HOST += showauth 35 | showauth_SRCS += showauth.cpp 36 | -------------------------------------------------------------------------------- /src/rpcService/rpcService.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #define epicsExportSharedSymbols 8 | #include 9 | 10 | namespace pvd = epics::pvData; 11 | 12 | namespace epics{namespace pvAccess{ 13 | 14 | void RPCService::request( 15 | pvd::PVStructure::shared_pointer const & args, 16 | RPCResponseCallback::shared_pointer const & callback) 17 | { 18 | assert(callback && args); 19 | pvd::PVStructure::shared_pointer ret; 20 | pvd::Status sts; 21 | try { 22 | ret = request(args); 23 | }catch(RPCRequestException& e){ 24 | sts = e.asStatus(); 25 | throw; 26 | }catch(std::exception& e){ 27 | sts = pvd::Status::error(e.what()); 28 | } 29 | if(!ret) { 30 | sts = pvd::Status(pvd::Status::STATUSTYPE_FATAL, "RPCService.request(PVStructure) returned null."); 31 | } 32 | callback->requestDone(sts, ret); 33 | } 34 | 35 | }} // namespace epics::pvAccess 36 | -------------------------------------------------------------------------------- /configure/CONFIG_SITE: -------------------------------------------------------------------------------- 1 | # CONFIG_SITE 2 | 3 | # Make any application-specific changes to the EPICS build 4 | # configuration variables in this file. 5 | # 6 | # Host/target specific settings can be specified in files named 7 | # CONFIG_SITE.$(EPICS_HOST_ARCH).Common 8 | # CONFIG_SITE.Common.$(T_A) 9 | # CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) 10 | 11 | # CHECK_RELEASE controls the consistency checking of the support 12 | # applications pointed to by the RELEASE* files. 13 | # Normally CHECK_RELEASE should be set to YES. 14 | # Set CHECK_RELEASE to NO to disable checking completely. 15 | # Set CHECK_RELEASE to WARN to perform consistency checking but 16 | # continue building anyway if conflicts are found. 17 | CHECK_RELEASE = YES 18 | 19 | # To install files into a location other than $(TOP) define 20 | # INSTALL_LOCATION here. 21 | #INSTALL_LOCATION= 22 | 23 | -include $(TOP)/../CONFIG_SITE.local 24 | -include $(TOP)/configure/CONFIG_SITE.local 25 | 26 | # MSVC - skip defining min()/max() macros 27 | USR_CPPFLAGS_WIN32 += -DNOMINMAX 28 | 29 | ifdef WITH_COVERAGE 30 | USR_CPPFLAGS += --coverage 31 | USR_LDFLAGS += --coverage 32 | endif 33 | -------------------------------------------------------------------------------- /documentation/commit-gh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e -x 3 | # Usage: commit-gh 4 | # 5 | # Creates a commit containing only the files in the sub-directory provided as an argument 6 | # 7 | # Does not disturb the working copy or index 8 | 9 | prefix="$1" 10 | shift 11 | 12 | # Commit to this branch 13 | BRANCH=refs/heads/gh-pages 14 | 15 | # Use the main branch description as the gh-pages commit message 16 | MSG=`git describe --tags --always` 17 | 18 | # Scratch space 19 | TDIR=`mktemp -d -p $PWD` 20 | 21 | # Automatic cleanup of scratch space 22 | trap 'rm -rf $TDIR' INT TERM QUIT EXIT 23 | 24 | export GIT_INDEX_FILE="$TDIR/index" 25 | 26 | # Add listed files to a new (empty) index 27 | git update-index --add "$@" 28 | 29 | # Write the index into the repo, get tree hash 30 | TREE=`git write-tree --prefix="$prefix"` 31 | 32 | echo "TREE $TREE" 33 | git cat-file -p $TREE 34 | 35 | # Create a commit with our new tree 36 | # Reference current branch head as parent (if any) 37 | CMT=`git commit-tree -m "$MSG" $TREE` 38 | 39 | echo "COMMIT $CMT" 40 | git cat-file -p $CMT 41 | 42 | # Update the branch with the new commit tree hash 43 | git update-ref $BRANCH $CMT 44 | 45 | echo "Done" 46 | -------------------------------------------------------------------------------- /src/utils/pv/wildcard.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | /******************************************************************* 8 | * Implementation of glob-style wildcard pattern matching. 9 | * Supported wild-card characters: '*', '?' 10 | */ 11 | 12 | #ifndef WILDCARD_H 13 | #define WILDCARD_H 14 | 15 | #include 16 | 17 | namespace epics { 18 | namespace pvAccess { 19 | 20 | /** 21 | * Class which implements wildcard patterns and checks to see 22 | * if a string matches a given pattern. 23 | */ 24 | class epicsShareClass Wildcard 25 | { 26 | 27 | public: 28 | 29 | /** 30 | * This function implements wildcard pattern matching. 31 | * @param wildcard Wildcard pattern to be used. 32 | * @param test Value to test against the wildcard. 33 | * @return 0 if wildcard does not match test. 1 - if wildcard 34 | * matches test. 35 | */ 36 | static int wildcardfit (const char *wildcard, const char *test); 37 | }; 38 | 39 | } 40 | } 41 | 42 | 43 | #endif 44 | 45 | -------------------------------------------------------------------------------- /src/ca/caContext.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef INC_caContext_H 8 | #define INC_caContext_H 9 | 10 | #include 11 | #include 12 | 13 | namespace epics { 14 | namespace pvAccess { 15 | namespace ca { 16 | 17 | 18 | class Attach; 19 | class CAContext; 20 | typedef std::tr1::shared_ptr CAContextPtr; 21 | 22 | class CAContext 23 | { 24 | public: 25 | CAContext(); 26 | ~CAContext(); 27 | private: 28 | ca_client_context* ca_context; 29 | 30 | private: // Internal API 31 | friend class Attach; 32 | ca_client_context* attach(); 33 | void detach(ca_client_context* restore); 34 | }; 35 | 36 | class Attach 37 | { 38 | public: 39 | explicit Attach(const CAContextPtr & to) : 40 | context(*to), saved_context(context.attach()) {} 41 | ~Attach() { 42 | context.detach(saved_context); 43 | } 44 | private: 45 | CAContext & context; 46 | ca_client_context* saved_context; 47 | }; 48 | 49 | }}} 50 | 51 | #endif // INC_caContext_H 52 | -------------------------------------------------------------------------------- /src/server/beaconServerStatusProvider.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #define epicsExportSharedSymbols 8 | #include 9 | #include 10 | 11 | using namespace epics::pvData; 12 | 13 | namespace epics { 14 | namespace pvAccess { 15 | 16 | DefaultBeaconServerStatusProvider::DefaultBeaconServerStatusProvider(ServerContext::shared_pointer const & context) 17 | :_status(getPVDataCreate()->createPVStructure(getFieldCreate()->createFieldBuilder() 18 | ->add("connections", pvInt) 19 | ->add("connections", pvInt) 20 | ->add("allocatedMemory", pvLong) 21 | ->add("freeMemory", pvLong) 22 | ->add("threads", pvInt) 23 | ->add("deadlocks", pvInt) 24 | ->add("averageSystemLoad", pvDouble) 25 | ->createStructure())) 26 | {} 27 | 28 | DefaultBeaconServerStatusProvider::~DefaultBeaconServerStatusProvider() {} 29 | 30 | PVField::shared_pointer DefaultBeaconServerStatusProvider::getServerStatusData() 31 | { 32 | //TODO implement (fill data) 33 | return _status; 34 | } 35 | 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /testApp/utils/showauth.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace pva = epics::pvAccess; 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | int ret = 0; 19 | try { 20 | std::vector name(256u); 21 | if(osiGetUserName(&name[0], name.size())!=osiGetUserNameSuccess) 22 | throw std::runtime_error("Unable to determine username"); 23 | 24 | name[name.size()-1] = '\0'; 25 | 26 | const char *user = argc<=1 ? &name[0] : argv[1]; 27 | 28 | std::cout<<"User: "< 14 | #include 15 | 16 | namespace epics { 17 | namespace pvAccess { 18 | namespace ca { 19 | 20 | /** 21 | * @brief CAClientFactory registers a channel provider for operations over the 22 | * CA network protocol. 23 | * 24 | * A single instance is created the first time CAClientFactory::start is called. 25 | * 26 | * The single instance calls: 27 | * ca_context_create(ca_enable_preemptive_callback); 28 | * 29 | * The thread that calls start, or a ca auxillary thread, are the only threads 30 | * that can call the ca_* functions. 31 | * 32 | * NOTE: Notifications for connection changes and monitor, get, and put events 33 | * are made from separate threads to prevent deadlocks. 34 | * 35 | */ 36 | class epicsShareClass CAClientFactory 37 | { 38 | public: 39 | /** @brief start provider ca 40 | * 41 | */ 42 | static void start(); 43 | /** @brief stop provider ca 44 | * 45 | * This does nothing. 46 | */ 47 | static void stop(); 48 | }; 49 | 50 | }}} 51 | 52 | #endif /* CAPROVIDER_H */ 53 | -------------------------------------------------------------------------------- /COPYRIGHT: -------------------------------------------------------------------------------- 1 | This software is in part copyrighted by the various organizations and 2 | individuals listed below. Permission to use it is set out in the file 3 | LICENSE that accompanies the software. 4 | 5 | In no event shall any copyright holder be liable to any party for 6 | direct, indirect, special, incidental, or consequential damages arising 7 | out of the use of this software, its documentation, or any derivatives 8 | thereof, even if they have been advised of the possibility of such 9 | damage. 10 | 11 | The copyright holders specifically disclaim any warranties, including, 12 | but not limited to, the implied warranties of merchantability, fitness 13 | for a particular purpose, and non-infringement. This software is 14 | provided on an "as is" basis, and the copyright holders have no 15 | obligation either collectively or individually to provide maintenance, 16 | support, updates, enhancements, or modifications. 17 | 18 | Copyright (c) 2006 - 2015 19 | 20 | Martin R. Kraimer 21 | The University of Chicago, as Operator of Argonne National Laboratory. 22 | Deutsches Elektronen-Synchroton, Member of the Helmholtz Association, 23 | (DESY), HAMBURG, GERMANY, 24 | BERLINER SPEICHERRING GESELLSCHAFT FUER SYNCHROTRONSTRAHLUNG M.B.H. 25 | (BESSY), BERLIN, GERMANY. 26 | COSYLAB (Control System Laboratory), Ljubljana Slovenia 27 | Brookhaven Science Associates, as Operator of Brookhaven 28 | National Laboratory. 29 | Diamond Light Source Ltd. 30 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for the pvAccess library 2 | 3 | TOP = .. 4 | include $(TOP)/configure/CONFIG 5 | 6 | EXPANDVARS += EPICS_PVA_MAJOR_VERSION 7 | EXPANDVARS += EPICS_PVA_MINOR_VERSION 8 | EXPANDVARS += EPICS_PVA_MAINTENANCE_VERSION 9 | EXPANDVARS += EPICS_PVA_DEVELOPMENT_FLAG 10 | 11 | EXPANDFLAGS += $(foreach var,$(EXPANDVARS),-D$(var)="$(strip $($(var)))") 12 | 13 | PVACCESS_SRC = $(TOP)/src 14 | 15 | include $(PVACCESS_SRC)/pva/Makefile 16 | include $(PVACCESS_SRC)/utils/Makefile 17 | include $(PVACCESS_SRC)/client/Makefile 18 | include $(PVACCESS_SRC)/factory/Makefile 19 | include $(PVACCESS_SRC)/remote/Makefile 20 | include $(PVACCESS_SRC)/remoteClient/Makefile 21 | include $(PVACCESS_SRC)/server/Makefile 22 | include $(PVACCESS_SRC)/rpcService/Makefile 23 | include $(PVACCESS_SRC)/rpcClient/Makefile 24 | include $(PVACCESS_SRC)/pipelineService/Makefile 25 | include $(PVACCESS_SRC)/mb/Makefile 26 | 27 | LIBRARY += pvAccess 28 | 29 | pvAccess_LIBS += pvData 30 | LIB_LIBS += Com 31 | 32 | SHRLIB_VERSION ?= $(EPICS_PVA_MAJOR_VERSION).$(EPICS_PVA_MINOR_VERSION).$(EPICS_PVA_MAINTENANCE_VERSION) 33 | 34 | # needed for Windows 35 | LIB_SYS_LIBS_WIN32 += netapi32 ws2_32 36 | 37 | include $(TOP)/configure/RULES 38 | 39 | # Can't use EXPAND as generated headers must appear 40 | # in O.Common, but EXPAND emits rules for O.$(T_A) 41 | ../O.Common/pv/pvaVersionNum.h: ../pva/pvaVersionNum.h@ 42 | $(MKDIR) $(COMMON_DIR)/pv 43 | $(EXPAND_TOOL) $(EXPANDFLAGS) $($@_EXPANDFLAGS) $< $@ 44 | -------------------------------------------------------------------------------- /testApp/remote/rpcWildServiceExample.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace epics::pvData; 11 | using namespace epics::pvAccess; 12 | 13 | static Structure::const_shared_pointer resultStructure = 14 | getFieldCreate()->createFieldBuilder()-> 15 | add("channelName", pvString)-> 16 | createStructure(); 17 | 18 | class WildServiceImpl : 19 | public RPCService 20 | { 21 | PVStructure::shared_pointer request(PVStructure::shared_pointer const & pvArguments) 22 | { 23 | // requires NTURI as argument 24 | if (pvArguments->getStructure()->getID() != "epics:nt/NTURI:1.0") 25 | throw RPCRequestException(Status::STATUSTYPE_ERROR, "RPC argument must be a NTURI normative type"); 26 | 27 | std::string channelName = pvArguments->getSubField("path")->get(); 28 | 29 | // create return structure and set data 30 | PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); 31 | result->getSubField("channelName")->put(channelName); 32 | return result; 33 | } 34 | }; 35 | 36 | int main() 37 | { 38 | RPCServer server; 39 | 40 | server.registerService("wild*", RPCService::shared_pointer(new WildServiceImpl())); 41 | // you can register as many services as you want here ... 42 | 43 | server.printInfo(); 44 | server.run(); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /testCa/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for the ca tests 2 | 3 | TOP = .. 4 | include $(TOP)/configure/CONFIG 5 | 6 | # Access to uninstalled headers 7 | USR_CPPFLAGS += -I$(TOP)/src/ca 8 | 9 | TESTPROD_HOST += testConveyor 10 | testConveyor_SRCS += testConveyor.cpp 11 | TESTS += testConveyor 12 | 13 | TESTPROD_HOST += testCaProvider 14 | testCaProvider_SRCS += testCaProvider.cpp 15 | 16 | PROD_LIBS += pvAccess pvAccessCA pvData $(EPICS_BASE_IOC_LIBS) 17 | PROD_SYS_LIBS_WIN32 += netapi32 ws2_32 18 | 19 | ifdef BASE_3_16 20 | PROD_SRCS_RTEMS += rtemsTestData.c 21 | testCaProvider_SRCS += testIoc_registerRecordDeviceDriver.cpp 22 | REGRDDFLAGS = -l 23 | 24 | TESTS += testCaProvider 25 | TESTFILES += ../testCaProvider.db $(COMMON_DIR)/testIoc.dbd 26 | 27 | # Build test scripts for hosts 28 | TESTSCRIPTS_HOST += $(TESTS:%=%.t) 29 | 30 | ifneq ($(filter $(T_A),$(CROSS_COMPILER_RUNTEST_ARCHS)),) 31 | TESTPROD = $(TESTPROD_HOST) 32 | TESTSCRIPTS = $(TESTSCRIPTS_HOST) 33 | endif 34 | 35 | # Ensure EPICS_HOST_ARCH is set in the environment 36 | export EPICS_HOST_ARCH 37 | 38 | caTestHarness_SRCS += testConveyor.cpp 39 | caTestHarness_SRCS += $(testCaProvider_SRCS) 40 | caTestHarness_SRCS += pvCaAllTests.c 41 | 42 | # Build harness for vxWorks and RTEMS 43 | PROD_vxWorks = caTestHarness 44 | PROD_RTEMS = caTestHarness 45 | caTestHarness_SRCS_RTEMS += rtemsTestHarness.c 46 | endif 47 | 48 | include $(TOP)/configure/RULES 49 | 50 | ifdef BASE_3_16 51 | $(COMMON_DIR)/testIoc.dbd: $(EPICS_BASE)/dbd/softIoc.dbd 52 | $(RM) $@ 53 | $(CP) $< $@ 54 | 55 | rtemsTestData.c : $(TESTFILES) $(TOOLS)/epicsMakeMemFs.pl 56 | $(PERL) $(TOOLS)/epicsMakeMemFs.pl $@ epicsRtemsFSImage $(TESTFILES) 57 | endif 58 | -------------------------------------------------------------------------------- /src/utils/logger.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #define epicsExportSharedSymbols 22 | #include 23 | 24 | using namespace epics::pvData; 25 | using std::ofstream; 26 | using std::ios; 27 | using std::endl; 28 | 29 | namespace epics { 30 | namespace pvAccess { 31 | 32 | #define TIMETEXTLEN 32 33 | 34 | static pvAccessLogLevel g_pvAccessLogLevel = logLevelInfo; 35 | 36 | void pvAccessLog(pvAccessLogLevel level, const char* format, ...) 37 | { 38 | // TODO lock 39 | if (level >= g_pvAccessLogLevel) 40 | { 41 | char timeText[TIMETEXTLEN]; 42 | epicsTimeStamp tsNow; 43 | 44 | epicsTimeGetCurrent(&tsNow); 45 | epicsTimeToStrftime(timeText, TIMETEXTLEN, "%Y-%m-%dT%H:%M:%S.%03f", &tsNow); 46 | 47 | printf("%s ", timeText); 48 | 49 | va_list arg; 50 | va_start(arg, format); 51 | vprintf(format, arg); 52 | va_end(arg); 53 | 54 | printf("\n"); 55 | fflush(stdout); // needed for WIN32 56 | } 57 | } 58 | 59 | void pvAccessSetLogLevel(pvAccessLogLevel level) 60 | { 61 | g_pvAccessLogLevel = level; 62 | } 63 | 64 | bool pvAccessIsLoggable(pvAccessLogLevel level) 65 | { 66 | return level >= g_pvAccessLogLevel; 67 | } 68 | 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/ioc/pv/syncChannelFind.h: -------------------------------------------------------------------------------- 1 | /* syncChannelFind.h */ 2 | /** 3 | * Copyright - See the COPYRIGHT that is included with this distribution. 4 | * EPICS pvData is distributed subject to a Software License Agreement found 5 | * in file LICENSE that is included with this distribution. 6 | */ 7 | /** 8 | * @author Marty Kraimer 9 | * @date 2014.02 10 | */ 11 | /** 12 | * This is an implementation of ChannelFind that is appropriate for all channel 13 | * providers that can synchronously determine if the provider has the channel. 14 | */ 15 | #ifndef SYNCCHANNELFIND_H 16 | #define SYNCCHANNELFIND_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifdef epicsExportSharedSymbols 24 | # define syncChannelFindEpicsExportSharedSymbols 25 | # undef epicsExportSharedSymbols 26 | #endif 27 | #include 28 | #ifdef syncChannelFindEpicsExportSharedSymbols 29 | # define epicsExportSharedSymbols 30 | # undef syncChannelFindEpicsExportSharedSymbols 31 | #endif 32 | 33 | #include 34 | #include 35 | 36 | 37 | namespace epics { 38 | namespace pvAccess { 39 | 40 | class SyncChannelFind : public ChannelFind 41 | { 42 | public: 43 | typedef std::tr1::shared_ptr shared_pointer; 44 | 45 | SyncChannelFind(ChannelProvider::shared_pointer &provider) : m_provider(provider) 46 | { 47 | } 48 | 49 | virtual ~SyncChannelFind() {} 50 | 51 | virtual void destroy() {} 52 | 53 | virtual ChannelProvider::shared_pointer getChannelProvider() 54 | { 55 | return m_provider.lock(); 56 | }; 57 | 58 | virtual void cancel() {} 59 | 60 | private: 61 | ChannelProvider::weak_pointer m_provider; 62 | }; 63 | 64 | 65 | 66 | 67 | } 68 | } 69 | #endif /* SYNCCHANNELFIND_H */ 70 | -------------------------------------------------------------------------------- /configure/RELEASE: -------------------------------------------------------------------------------- 1 | # RELEASE - Location of external support modules 2 | # 3 | # IF YOU CHANGE ANY PATHS in this file or make API changes to 4 | # any modules it refers to, you should do a "make rebuild" in 5 | # this application's top level directory. 6 | # 7 | # The EPICS build process does not check dependencies against 8 | # any files from outside the application, so it is safest to 9 | # rebuild it completely if any modules it depends on change. 10 | # 11 | # Host- or target-specific settings can be given in files named 12 | # RELEASE.$(EPICS_HOST_ARCH).Common 13 | # RELEASE.Common.$(T_A) 14 | # RELEASE.$(EPICS_HOST_ARCH).$(T_A) 15 | # 16 | # This file is parsed by both GNUmake and an EPICS Perl script, 17 | # so it may ONLY contain definititions of paths to other support 18 | # modules, variable definitions that are used in module paths, 19 | # and include statements that pull in other RELEASE files. 20 | # Variables may be used before their values have been set. 21 | # Build variables that are NOT used in paths should be set in 22 | # the CONFIG_SITE file. 23 | 24 | # Variables and paths to dependent modules: 25 | #MODULES = /path/to/modules 26 | #MYMODULE = $(MODULES)/my-module 27 | 28 | # If building the EPICS modules individually, set these: 29 | #EPICS_PVDATA = $(MODULES)/pvData 30 | #EPICS_DATABASE = $(MODULES)/database 31 | #EPICS_CA = $(MODULES)/ca 32 | #EPICS_LIBCOM = $(MODULES)/libcom 33 | #EPICS_BASE = $(MODULES)/core 34 | 35 | # Set RULES here if you want to use build rules from elsewhere: 36 | #RULES = $(MODULES)/build-rules 37 | 38 | # These allow developers to override the RELEASE variable settings 39 | # without having to modify the configure/RELEASE file itself. 40 | -include $(TOP)/../RELEASE.local 41 | -include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local 42 | -include $(TOP)/configure/RELEASE.local 43 | -------------------------------------------------------------------------------- /src/utils/pv/hexDump.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef HEXDUMP_H_ 8 | #define HEXDUMP_H_ 9 | 10 | #include 11 | 12 | #ifdef epicsExportSharedSymbols 13 | # define hexDumpEpicsExportSharedSymbols 14 | # undef epicsExportSharedSymbols 15 | #endif 16 | 17 | #include 18 | 19 | #ifdef hexDumpEpicsExportSharedSymbols 20 | # define epicsExportSharedSymbols 21 | # undef hexDumpEpicsExportSharedSymbols 22 | #endif 23 | 24 | #include 25 | 26 | namespace epics { 27 | namespace pvData { 28 | class ByteBuffer; 29 | } 30 | namespace pvAccess { 31 | 32 | class epicsShareClass HexDump { 33 | const char* buf; 34 | size_t buflen; 35 | size_t _limit; 36 | unsigned _groupBy; 37 | unsigned _perLine; 38 | public: 39 | HexDump(const char* buf, size_t len); 40 | explicit HexDump(const pvData::ByteBuffer& buf, size_t size=(size_t)-1, size_t offset=0u); 41 | ~HexDump(); 42 | 43 | //! safety limit on max bytes printed 44 | inline HexDump& limit(size_t n=(size_t)-1) { _limit = n; return *this; } 45 | //! insert a space after this many bytes 46 | inline HexDump& bytesPerGroup(size_t n=(size_t)-1) { _groupBy = n; return *this; } 47 | //! start a new line after this many bytes 48 | inline HexDump& bytesPerLine(size_t n=(size_t)-1) { _perLine = n; return *this; } 49 | 50 | epicsShareFunc 51 | friend std::ostream& operator<<(std::ostream& strm, const HexDump& hex); 52 | }; 53 | 54 | epicsShareFunc 55 | std::ostream& operator<<(std::ostream& strm, const HexDump& hex); 56 | 57 | } 58 | } 59 | 60 | #endif /* HEXDUMP_H_ */ 61 | -------------------------------------------------------------------------------- /testApp/remote/rpcClientExample.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace epics::pvData; 11 | using namespace epics::pvAccess; 12 | 13 | static StructureConstPtr requestStructure = 14 | getFieldCreate()->createFieldBuilder()-> 15 | add("a", pvString)-> 16 | add("b", pvString)-> 17 | createStructure(); 18 | 19 | #define TIMEOUT 3.0 20 | 21 | int main() 22 | { 23 | PVStructure::shared_pointer request = getPVDataCreate()->createPVStructure(requestStructure); 24 | request->getSubField("a")->put("3.14"); 25 | request->getSubField("b")->put("2.71"); 26 | 27 | std::cout<<"simple sync way, allows multiple RPC calls on the client instance\n"; 28 | try 29 | { 30 | RPCClient::shared_pointer client = RPCClient::create("sum"); 31 | PVStructure::shared_pointer result = client->request(request, TIMEOUT); 32 | std::cout << *result << std::endl; 33 | } catch (std::exception &e) 34 | { 35 | std::cout << "Error: " << e.what() << std::endl; 36 | return 1; 37 | } 38 | 39 | std::cout<<"async way, allows multiple RPC calls on the client instance\n"; 40 | try 41 | { 42 | RPCClient::shared_pointer client = RPCClient::create("sum"); 43 | client->issueRequest(request); 44 | // go get some coffee 45 | PVStructure::shared_pointer result = client->waitResponse(TIMEOUT); 46 | std::cout << *result << std::endl; 47 | } catch (std::exception &e) 48 | { 49 | std::cout << "Error:" << e.what() << std::endl; 50 | return 1; 51 | } 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /src/remote/abstractResponseHandler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | #define epicsExportSharedSymbols 13 | #include 14 | #include 15 | 16 | using namespace epics::pvData; 17 | 18 | namespace epics { 19 | namespace pvAccess { 20 | 21 | size_t ResponseHandler::num_instances; 22 | 23 | ResponseHandler::ResponseHandler(Context* context, const std::string& description) 24 | :_description(description) 25 | ,_debugLevel(context->getConfiguration()->getPropertyAsInteger(PVACCESS_DEBUG, 0)) // actually $EPICS_PVA_DEBUG 26 | { 27 | REFTRACE_INCREMENT(num_instances); 28 | } 29 | 30 | ResponseHandler::~ResponseHandler() 31 | { 32 | REFTRACE_DECREMENT(num_instances); 33 | } 34 | 35 | void ResponseHandler::handleResponse(osiSockAddr* responseFrom, 36 | Transport::shared_pointer const & transport, int8 version, int8 command, 37 | size_t payloadSize, ByteBuffer* payloadBuffer) { 38 | if(_debugLevel >= 3) { // TODO make a constant of sth (0 - off, 1 - debug, 2 - more/trace, 3 - messages) 39 | char ipAddrStr[24]; 40 | ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr)); 41 | 42 | std::ios::fmtflags initialflags = std::cerr.flags(); 43 | std::cerr<<"Message ["<getRemoteName() 45 | <<" : "<<_description<<"\n" 46 | < 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | namespace epics { 18 | namespace pvAccess { 19 | namespace ca { 20 | 21 | class Notification; 22 | typedef std::tr1::shared_ptr NotificationPtr; 23 | typedef std::tr1::weak_ptr NotificationWPtr; 24 | 25 | class NotifierClient; 26 | typedef std::tr1::shared_ptr NotifierClientPtr; 27 | typedef std::tr1::weak_ptr NotifierClientWPtr; 28 | 29 | class NotifierClient 30 | { 31 | public: 32 | virtual ~NotifierClient() {}; 33 | virtual void notifyClient() = 0; 34 | }; 35 | 36 | class Notification 37 | { 38 | public: 39 | Notification(void) : queued(false) {} 40 | explicit Notification(NotifierClientPtr const &c) : 41 | client(c), queued(false) {} 42 | void setClient(NotifierClientPtr const &client) { 43 | this->client = client; 44 | } 45 | private: 46 | NotifierClientWPtr client; 47 | bool queued; 48 | friend class NotifierConveyor; 49 | }; 50 | 51 | class epicsShareClass NotifierConveyor : 52 | public epicsThreadRunable 53 | { 54 | public: 55 | NotifierConveyor() : halt(false) {} 56 | ~NotifierConveyor(); 57 | virtual void run(); 58 | void start(); 59 | void notifyClient(NotificationPtr const ¬ificationPtr); 60 | 61 | private: 62 | std::tr1::shared_ptr thread; 63 | epicsMutex mutex; 64 | epicsEvent workToDo; 65 | std::queue workQueue; 66 | bool halt; 67 | }; 68 | 69 | }}} 70 | 71 | #endif /* INC_notifierConveyor_H */ 72 | -------------------------------------------------------------------------------- /src/utils/pv/requester.h: -------------------------------------------------------------------------------- 1 | /* requester.h */ 2 | /* 3 | * Copyright information and license terms for this software can be 4 | * found in the file LICENSE that is included with the distribution 5 | */ 6 | /** 7 | * @author mrk 8 | */ 9 | #ifndef REQUESTER_H 10 | #define REQUESTER_H 11 | #include 12 | 13 | #ifdef epicsExportSharedSymbols 14 | # define requesterEpicsExportSharedSymbols 15 | # undef epicsExportSharedSymbols 16 | #endif 17 | 18 | #include 19 | #include 20 | 21 | #ifdef requesterEpicsExportSharedSymbols 22 | # define epicsExportSharedSymbols 23 | # undef requesterEpicsExportSharedSymbols 24 | #endif 25 | 26 | 27 | #include 28 | 29 | namespace epics { namespace pvAccess { 30 | 31 | class Requester; 32 | typedef std::tr1::shared_ptr RequesterPtr; 33 | 34 | enum MessageType { 35 | infoMessage,warningMessage,errorMessage,fatalErrorMessage 36 | }; 37 | #define MESSAGE_TYPE_COUNT 4 38 | 39 | epicsShareExtern std::string getMessageTypeName(MessageType messageType); 40 | 41 | /** @brief Callback class for passing messages to a requester. 42 | */ 43 | class epicsShareClass Requester { 44 | public: 45 | POINTER_DEFINITIONS(Requester); 46 | virtual ~Requester(){} 47 | /** 48 | * The requester must have a name. 49 | * @return The requester's name. 50 | */ 51 | virtual std::string getRequesterName() = 0; 52 | /** Push notification 53 | */ 54 | virtual void message(std::string const & message,MessageType messageType = errorMessage); 55 | }; 56 | 57 | }} 58 | namespace epics { namespace pvData { 59 | using ::epics::pvAccess::Requester; 60 | using ::epics::pvAccess::RequesterPtr; 61 | using ::epics::pvAccess::MessageType; 62 | using ::epics::pvAccess::getMessageTypeName; 63 | using ::epics::pvAccess::infoMessage; 64 | using ::epics::pvAccess::warningMessage; 65 | using ::epics::pvAccess::errorMessage; 66 | using ::epics::pvAccess::fatalErrorMessage; 67 | }} 68 | #endif /* REQUESTER_H */ 69 | -------------------------------------------------------------------------------- /src/utils/pv/destroyable.h: -------------------------------------------------------------------------------- 1 | /* destroyable.h */ 2 | /* 3 | * Copyright information and license terms for this software can be 4 | * found in the file LICENSE that is included with the distribution 5 | */ 6 | /** 7 | * @author mse 8 | */ 9 | #ifndef DESTROYABLE_H 10 | #define DESTROYABLE_H 11 | 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | namespace epics { namespace pvAccess { 19 | 20 | 21 | /** 22 | * @brief Instance declaring destroy method. 23 | */ 24 | class epicsShareClass Destroyable { 25 | public: 26 | POINTER_DEFINITIONS(Destroyable); 27 | /** 28 | * Destroy this instance. 29 | */ 30 | virtual void destroy() {}; 31 | 32 | protected: 33 | virtual ~Destroyable() {} 34 | public: 35 | 36 | /** for use with shared_ptr<> when wrapping 37 | * 38 | @code 39 | shared_ptr inner(new foo), 40 | outer(inner.get, Destroyable::cleaner(inner)); 41 | @endcode 42 | 43 | @warning Do not use this trick in combination with enable_shared_from_this 44 | as it is _undefined_ whether the hidden weak_ptr will be the original 45 | or wrapped reference. 46 | */ 47 | class cleaner { 48 | Destroyable::shared_pointer ptr; 49 | public: 50 | cleaner(const Destroyable::shared_pointer& ptr) :ptr(ptr) {} 51 | void operator()(Destroyable*) { 52 | Destroyable::shared_pointer P; 53 | P.swap(ptr); 54 | P->destroy(); 55 | } 56 | }; 57 | }; 58 | 59 | }} 60 | namespace epics { namespace pvData { 61 | typedef ::epics::pvAccess::Destroyable Destroyable EPICS_DEPRECATED; 62 | }} 63 | #endif /* DESTROYABLE_H */ 64 | -------------------------------------------------------------------------------- /testApp/utils/testWildcard.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | using epics::pvAccess::Wildcard; 13 | 14 | static 15 | void testWildcardCases() 16 | { 17 | testDiag("Test testWildcardCases()"); 18 | 19 | testOk1(Wildcard::wildcardfit("*", "test")); 20 | testOk1(Wildcard::wildcardfit("*", "")); 21 | testOk1(!Wildcard::wildcardfit("?", "")); 22 | testOk1(Wildcard::wildcardfit("?", "a")); 23 | testOk1(Wildcard::wildcardfit("*?", "test")); 24 | testOk1(Wildcard::wildcardfit("?*", "test")); 25 | testOk1(Wildcard::wildcardfit("?*?", "test")); 26 | testOk1(!Wildcard::wildcardfit("?", "")); 27 | testOk1(!Wildcard::wildcardfit("?*?", "")); 28 | 29 | //testOk1(Wildcard::wildcardfit("[-aa-]*", "01 abAZ")); 30 | //testOk1(Wildcard::wildcardfit("[\\!a\\-bc]*", "!!!b-bb-")); 31 | testOk1(Wildcard::wildcardfit("*zz", "zz")); 32 | //testOk1(Wildcard::wildcardfit("[abc]*zz", "zz")); 33 | 34 | //testOk1(!Wildcard::wildcardfit("[!abc]*a[def]", "xyzbd")); 35 | //testOk1(Wildcard::wildcardfit("[!abc]*a[def]", "xyzad")); 36 | //testOk1(Wildcard::wildcardfit("[a-g]l*i?", "gloria")); 37 | //testOk1(Wildcard::wildcardfit("[!abc]*e", "smile")); 38 | //testOk1(Wildcard::wildcardfit("[-z]", "a")); 39 | //testOk1(!Wildcard::wildcardfit("[]", "")); 40 | //testOk1(Wildcard::wildcardfit("[a-z]*", "java")); 41 | testOk1(Wildcard::wildcardfit("*.*", "command.com")); 42 | testOk1(!Wildcard::wildcardfit("*.*", "/var/etc")); 43 | //testOk1(Wildcard::wildcardfit("**?*x*[abh-]*Q", "XYZxabbauuZQ")); 44 | } 45 | 46 | MAIN(testWildcard) 47 | { 48 | testPlan(12); 49 | testDiag("Tests for Wildcard util"); 50 | 51 | testWildcardCases(); 52 | return testDone(); 53 | } 54 | -------------------------------------------------------------------------------- /testApp/remote/Makefile: -------------------------------------------------------------------------------- 1 | # This is a Makefile fragment, see ../Makefile 2 | 3 | SRC_DIRS += $(PVACCESS_TEST)/remote 4 | 5 | TESTPROD_HOST += testChannelAccess 6 | testChannelAccess_SRCS = channelAccessIFTest.cpp 7 | testHarness_SRCS += channelAccessIFTest.cpp 8 | ifneq (RTEMS,$(OS_CLASS)) 9 | TESTS += testChannelAccess 10 | endif 11 | 12 | TESTPROD_HOST += testCodec 13 | testCodec_SRCS = testCodec 14 | testHarness_SRCS += testCodec.cpp 15 | TESTS += testCodec 16 | 17 | TESTPROD_HOST += testRPC 18 | testRPC_SRCS += testRPC.cpp 19 | TESTS += testRPC 20 | 21 | TESTPROD_HOST += testRemoteClientImpl 22 | testRemoteClientImpl_SRCS += testRemoteClientImpl.cpp 23 | 24 | TESTPROD_HOST += testChannelConnect 25 | testChannelConnect_SRCS += testChannelConnect.cpp 26 | 27 | TESTPROD_HOST += testServerContext 28 | testServerContext_SRCS += testServerContext.cpp 29 | TESTS += testServerContext 30 | 31 | TESTPROD_HOST += testmonitorfifo 32 | testmonitorfifo_SRCS += testmonitorfifo.cpp 33 | TESTS += testmonitorfifo 34 | 35 | TESTPROD_HOST += testsharedstate 36 | testsharedstate_SRCS += testsharedstate.cpp 37 | TESTS += testsharedstate 38 | 39 | TESTPROD_HOST += testServer 40 | testServer_SRCS += testServer.cpp 41 | 42 | TESTPROD_HOST += testGetPerformance 43 | testGetPerformance_SRCS += testGetPerformance.cpp 44 | 45 | TESTPROD_HOST += testMonitorPerformance 46 | testMonitorPerformance_SRCS += testMonitorPerformance.cpp 47 | 48 | TESTPROD_HOST += rpcServiceExample 49 | rpcServiceExample_SRCS += rpcServiceExample.cpp 50 | 51 | TESTPROD_HOST += rpcServiceAsyncExample 52 | rpcServiceAsyncExample_SRCS += rpcServiceAsyncExample.cpp 53 | 54 | TESTPROD_HOST += rpcWildServiceExample 55 | rpcWildServiceExample_SRCS += rpcWildServiceExample.cpp 56 | 57 | TESTPROD_HOST += rpcClientExample 58 | rpcClientExample_SRCS += rpcClientExample.cpp 59 | 60 | TEESTPROD_HOST += pipelineServiceExample 61 | pipelineServiceExample_SRCS += pipelineServiceExample.cpp 62 | 63 | TESTPROD_HOST += testClientFactory 64 | testClientFactory_SRCS += testClientFactory.cpp 65 | 66 | TESTPROD_HOST += testRAII 67 | testRAII_SRCS += testRAII.cpp 68 | -------------------------------------------------------------------------------- /testApp/utils/testFairQueue.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | namespace { 15 | 16 | struct Qnode : public epics::pvAccess::fair_queue::entry { 17 | unsigned i; 18 | Qnode(unsigned i):i(i) {} 19 | }; 20 | 21 | } // namespace 22 | 23 | static unsigned Ninput[] = {0,0,0,1,0,2,1,0,1,0,0}; 24 | static unsigned Nexpect[] = {0,1,2,0,1,0,1,0,0,0,0}; 25 | 26 | static 27 | void testOrder() 28 | { 29 | epics::pvAccess::fair_queue Q; 30 | typedef epics::pvAccess::fair_queue::value_type value_type; 31 | 32 | std::vector unique, inputs, outputs; 33 | unique.resize(3); 34 | unique[0].reset(new Qnode(0)); 35 | unique[1].reset(new Qnode(1)); 36 | unique[2].reset(new Qnode(2)); 37 | 38 | testDiag("Queueing"); 39 | 40 | for(unsigned i=0; ii); 54 | } 55 | } 56 | 57 | testOk(outputs.size()==NELEMENTS(Nexpect), "sizes match actual %u expected %u", 58 | (unsigned)outputs.size(), (unsigned)NELEMENTS(Nexpect)); 59 | 60 | for(unsigned i=0; i=outputs.size()) { 62 | testFail("output truncated"); 63 | continue; 64 | } 65 | testOk(outputs[i]->i==Nexpect[i], "[%u] %u == %u", 66 | i, (unsigned)outputs[i]->i, Nexpect[i]); 67 | } 68 | } 69 | 70 | MAIN(testFairQueue) 71 | { 72 | testPlan(12); 73 | testOrder(); 74 | return testDone(); 75 | } 76 | -------------------------------------------------------------------------------- /src/server/pv/beaconServerStatusProvider.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef BEACONSERVERSTATUSPROVIDER_H 8 | #define BEACONSERVERSTATUSPROVIDER_H 9 | 10 | #ifdef epicsExportSharedSymbols 11 | # define beaconServerStatusProviderEpicsExportSharedSymbols 12 | # undef epicsExportSharedSymbols 13 | #endif 14 | 15 | #include 16 | #include 17 | 18 | #ifdef beaconServerStatusProviderEpicsExportSharedSymbols 19 | # define epicsExportSharedSymbols 20 | # undef beaconServerStatusProviderEpicsExportSharedSymbols 21 | #endif 22 | 23 | #include 24 | 25 | namespace epics { 26 | namespace pvAccess { 27 | 28 | class ServerContext; 29 | 30 | /** 31 | * BeaconServerStatusProvider 32 | */ 33 | class epicsShareClass BeaconServerStatusProvider 34 | { 35 | public: 36 | typedef std::tr1::shared_ptr shared_pointer; 37 | typedef std::tr1::shared_ptr const_shared_pointer; 38 | 39 | virtual ~BeaconServerStatusProvider() {}; 40 | 41 | /** 42 | * Gets server status data. 43 | */ 44 | virtual epics::pvData::PVField::shared_pointer getServerStatusData() = 0; 45 | }; 46 | 47 | /** 48 | * DefaultBeaconServerStatusProvider 49 | */ 50 | class epicsShareClass DefaultBeaconServerStatusProvider : public BeaconServerStatusProvider 51 | { 52 | public: 53 | /** 54 | * Constructor. 55 | * @param context PVA context. 56 | */ 57 | // DefaultBeaconServerStatusProvider(ServerContext::shared_pointer const & context); 58 | DefaultBeaconServerStatusProvider(std::tr1::shared_ptr const & context); 59 | /** 60 | * Destructor. 61 | */ 62 | virtual ~DefaultBeaconServerStatusProvider(); 63 | 64 | virtual epics::pvData::PVField::shared_pointer getServerStatusData(); 65 | 66 | private: 67 | epics::pvData::PVStructure::shared_pointer _status; 68 | }; 69 | 70 | } 71 | } 72 | 73 | #endif /* BEACONSERVERSTATUSPROVIDER_H */ 74 | -------------------------------------------------------------------------------- /src/pva/pvaVersion.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #define epicsExportSharedSymbols 10 | #include 11 | #include 12 | 13 | using std::stringstream; 14 | using std::string; 15 | 16 | namespace epics { 17 | namespace pvAccess { 18 | 19 | const std::string PVACCESS_DEFAULT_PROVIDER("local"); 20 | const std::string PVACCESS_ALL_PROVIDERS(""); 21 | const std::string PVACCESS_DEBUG("EPICS_PVA_DEBUG"); 22 | 23 | Version::Version(std::string const & productName, 24 | std::string const & implementationLangugage, 25 | int majorVersion, int minorVersion, 26 | int maintenanceVersion, bool developmentFlag) : 27 | _productName(productName), 28 | _implementationLanguage(implementationLangugage), 29 | _majorVersion(majorVersion), 30 | _minorVersion(minorVersion), 31 | _maintenanceVersion(maintenanceVersion), 32 | _developmentFlag(developmentFlag) 33 | { 34 | } 35 | 36 | const std::string Version::getProductName() const { 37 | return _productName; 38 | } 39 | 40 | const std::string Version::getImplementationLanguage() const { 41 | return _implementationLanguage; 42 | } 43 | 44 | int Version::getMajorVersion() const { 45 | return _majorVersion; 46 | } 47 | 48 | int Version::getMinorVersion() const { 49 | return _minorVersion; 50 | } 51 | 52 | int Version::getMaintenanceVersion() const { 53 | return _maintenanceVersion; 54 | } 55 | 56 | bool Version::isDevelopmentVersion() const { 57 | return _developmentFlag; 58 | } 59 | 60 | const string Version::getVersionString() const { 61 | stringstream ret; 62 | ret< 9 | #include 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | typedef epicsGuard Guard; 21 | typedef epicsGuardRelease UnGuard; 22 | namespace pvd = epics::pvData; 23 | namespace pva = epics::pvAccess; 24 | 25 | #define COMMON_OPTIONS \ 26 | "options:\n" \ 27 | " -h: Help: Print this message\n" \ 28 | " -V: Print version and exit\n" \ 29 | " -r : Request, specifies what fields to return and options, default is '%s'\n" \ 30 | " -w : Wait time, specifies timeout, default is %f second(s)\n" \ 31 | " -p : Set default provider name, default is '%s'\n" \ 32 | " -M : Output mode. default is 'nt'\n" \ 33 | " -v: Show entire structure (implies Raw mode)\n" \ 34 | " -q: Quiet mode, print only error messages\n" \ 35 | " -d: Enable debug output\n" 36 | 37 | extern double timeout; 38 | extern bool debugFlag; 39 | 40 | extern pvd::PVStructure::Formatter::format_t outmode; 41 | extern int verbosity; 42 | 43 | extern std::string request; 44 | extern std::string defaultProvider; 45 | 46 | struct Tracker { 47 | static epicsMutex doneLock; 48 | static epicsEvent doneEvt; 49 | typedef std::set inprog_t; 50 | static inprog_t inprog; 51 | static bool abort; 52 | 53 | Tracker() 54 | { 55 | Guard G(doneLock); 56 | inprog.insert(this); 57 | } 58 | ~Tracker() 59 | { 60 | done(); 61 | } 62 | void done() 63 | { 64 | { 65 | Guard G(doneLock); 66 | inprog.erase(this); 67 | } 68 | doneEvt.signal(); 69 | } 70 | 71 | static void prepare(); 72 | EPICS_NOT_COPYABLE(Tracker) 73 | }; 74 | 75 | void jarray(pvd::shared_vector& out, const char *inp); 76 | 77 | 78 | #endif /* PVUTILS_H */ 79 | -------------------------------------------------------------------------------- /src/pipelineService/pv/pipelineServer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef PIPELINESERVER_H 8 | #define PIPELINESERVER_H 9 | 10 | #ifdef epicsExportSharedSymbols 11 | # define pipelineServerEpicsExportSharedSymbols 12 | # undef epicsExportSharedSymbols 13 | #endif 14 | 15 | #include 16 | 17 | #ifdef pipelineServerEpicsExportSharedSymbols 18 | # define epicsExportSharedSymbols 19 | # undef pipelineServerEpicsExportSharedSymbols 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | namespace epics { 29 | namespace pvAccess { 30 | 31 | class PipelineChannelProvider; 32 | 33 | class epicsShareClass PipelineServer : 34 | public std::tr1::enable_shared_from_this 35 | { 36 | private: 37 | 38 | ServerContext::shared_pointer m_serverContext; 39 | std::tr1::shared_ptr m_channelProviderImpl; 40 | 41 | // TODO no thread poll implementation 42 | 43 | public: 44 | POINTER_DEFINITIONS(PipelineServer); 45 | 46 | PipelineServer(); 47 | 48 | virtual ~PipelineServer(); 49 | 50 | void registerService(std::string const & serviceName, PipelineService::shared_pointer const & service); 51 | 52 | void unregisterService(std::string const & serviceName); 53 | 54 | void run(int seconds = 0); 55 | 56 | /// Method requires usage of std::tr1::shared_ptr. This instance must be 57 | /// owned by a shared_ptr instance. 58 | void runInNewThread(int seconds = 0); 59 | 60 | void destroy(); 61 | 62 | /** 63 | * Display basic information about the context. 64 | */ 65 | void printInfo(); 66 | 67 | }; 68 | 69 | epicsShareFunc Channel::shared_pointer createPipelineChannel(ChannelProvider::shared_pointer const & provider, 70 | std::string const & channelName, 71 | ChannelRequester::shared_pointer const & channelRequester, 72 | PipelineService::shared_pointer const & pipelineService); 73 | 74 | } 75 | } 76 | 77 | #endif /* PIPELINESERVER_H */ 78 | -------------------------------------------------------------------------------- /src/ca/caContext.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #define epicsExportSharedSymbols 11 | #include "caContext.h" 12 | 13 | namespace epics { 14 | namespace pvAccess { 15 | namespace ca { 16 | 17 | CAContext::CAContext() 18 | { 19 | ca_client_context *thread_context = ca_current_context(); 20 | if (thread_context) 21 | ca_detach_context(); 22 | int result = ca_context_create(ca_enable_preemptive_callback); 23 | if (result != ECA_NORMAL) 24 | throw std::runtime_error("Can't create CA context"); 25 | 26 | this->ca_context = ca_current_context(); 27 | detach(thread_context); 28 | } 29 | 30 | ca_client_context* CAContext::attach() 31 | { 32 | ca_client_context *thread_context = ca_current_context(); 33 | if (thread_context) 34 | ca_detach_context(); 35 | 36 | int result = ca_attach_context(this->ca_context); 37 | if (result != ECA_NORMAL) { 38 | if (thread_context) { 39 | result = ca_attach_context(thread_context); 40 | if (result != ECA_NORMAL) 41 | std::cerr << "Lost thread's CA context" << std::endl; 42 | } 43 | throw std::runtime_error("Can't attach to my CA context"); 44 | } 45 | return thread_context; 46 | } 47 | 48 | void CAContext::detach(ca_client_context* restore) \ 49 | { 50 | ca_client_context *thread_context = ca_current_context(); 51 | if (thread_context != this->ca_context) 52 | std::cerr << "CA context was changed!" << std::endl; 53 | 54 | ca_detach_context(); 55 | 56 | if (restore) { 57 | int result = ca_attach_context(restore); 58 | if (result != ECA_NORMAL) 59 | std::cerr << "Lost thread's CA context" << std::endl; 60 | } 61 | } 62 | 63 | CAContext::~CAContext() 64 | { 65 | ca_client_context *thread_context = attach(); 66 | ca_context_destroy(); 67 | 68 | if (thread_context) { 69 | int result = ca_attach_context(thread_context); 70 | if (result != ECA_NORMAL) 71 | std::cerr << "Lost thread's CA context" << std::endl; 72 | } 73 | } 74 | 75 | }}} 76 | -------------------------------------------------------------------------------- /src/utils/pv/logger.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef LOGGER_H_ 8 | #define LOGGER_H_ 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | namespace epics { 16 | namespace pvAccess { 17 | 18 | typedef enum { logLevelAll = 0, logLevelTrace, logLevelDebug, logLevelInfo, 19 | logLevelWarn, logLevelError, logLevelFatal, logLevelOff 20 | } pvAccessLogLevel; 21 | /* 22 | ALL 23 | The ALL has the lowest possible rank and is intended to turn on all logging. 24 | TRACE 25 | The TRACE Level designates finer-grained informational events than the DEBUG 26 | DEBUG 27 | The DEBUG Level designates fine-grained informational events that are most useful to debug an application. 28 | INFO 29 | The INFO level designates informational messages that highlight the progress of the application at coarse-grained level. 30 | WARN 31 | The WARN level designates potentially harmful situations. 32 | ERROR 33 | The ERROR level designates error events that might still allow the application to continue running. 34 | FATAL 35 | The FATAL level designates very severe error events that will presumably lead the application to abort. 36 | OFF 37 | The OFF has the highest possible rank and is intended to turn off logging. 38 | */ 39 | 40 | 41 | epicsShareFunc void pvAccessLog(pvAccessLogLevel level, const char* format, ...) EPICS_PRINTF_STYLE(2, 3); 42 | epicsShareFunc void pvAccessSetLogLevel(pvAccessLogLevel level); 43 | epicsShareFunc bool pvAccessIsLoggable(pvAccessLogLevel level); 44 | 45 | #if defined (__GNUC__) && __GNUC__ < 3 46 | #define LOG(level, format, ARGS...) pvAccessLog(level, format, ##ARGS) 47 | #else 48 | #define LOG(level, format, ...) pvAccessLog(level, format, ##__VA_ARGS__) 49 | #endif 50 | #define SET_LOG_LEVEL(level) pvAccessSetLogLevel(level) 51 | #define IS_LOGGABLE(level) pvAccessIsLoggable(level) 52 | 53 | // EPICS errlog 54 | //#define LOG errlogSevPrintf 55 | //#define SET_LOG_LEVEL(level) errlogSetSevToLog(level) 56 | 57 | // none 58 | //#define LOG(level, fmt, ...) 59 | //#define SET_LOG_LEVEL(level) 60 | 61 | } 62 | } 63 | 64 | #endif /* LOGGER_H_ */ 65 | -------------------------------------------------------------------------------- /src/rpcService/pv/rpcServer.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef RPCSERVER_H 8 | #define RPCSERVER_H 9 | 10 | #ifdef epicsExportSharedSymbols 11 | # define rpcServerEpicsExportSharedSymbols 12 | # undef epicsExportSharedSymbols 13 | #endif 14 | 15 | #include 16 | 17 | #ifdef rpcServerEpicsExportSharedSymbols 18 | # define epicsExportSharedSymbols 19 | # undef rpcServerEpicsExportSharedSymbols 20 | #endif 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | 28 | namespace epics { 29 | namespace pvAccess { 30 | 31 | class ServerContext; 32 | class RPCChannelProvider; 33 | 34 | //! Serves (only) RPCServiceAsync and RPCService instances. 35 | class epicsShareClass RPCServer : 36 | public std::tr1::enable_shared_from_this 37 | { 38 | private: 39 | 40 | std::tr1::shared_ptr m_serverContext; 41 | std::tr1::shared_ptr m_channelProviderImpl; 42 | 43 | public: 44 | POINTER_DEFINITIONS(RPCServer); 45 | 46 | explicit RPCServer(const Configuration::const_shared_pointer& conf = Configuration::const_shared_pointer()); 47 | 48 | virtual ~RPCServer(); 49 | 50 | void registerService(std::string const & serviceName, RPCServiceAsync::shared_pointer const & service); 51 | 52 | void unregisterService(std::string const & serviceName); 53 | 54 | void run(int seconds = 0); 55 | 56 | /// Method requires usage of std::tr1::shared_ptr. This instance must be 57 | /// owned by a shared_ptr instance. 58 | void runInNewThread(int seconds = 0); 59 | 60 | void destroy(); 61 | 62 | /** 63 | * Display basic information about the context. 64 | */ 65 | void printInfo(); 66 | 67 | const std::tr1::shared_ptr& getServer() const { return m_serverContext; } 68 | }; 69 | 70 | epicsShareFunc Channel::shared_pointer createRPCChannel(ChannelProvider::shared_pointer const & provider, 71 | std::string const & channelName, 72 | ChannelRequester::shared_pointer const & channelRequester, 73 | RPCServiceAsync::shared_pointer const & rpcService); 74 | 75 | } 76 | } 77 | 78 | #endif /* RPCSERVER_H */ 79 | -------------------------------------------------------------------------------- /src/server/pv/serverChannelImpl.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef SERVERCHANNEL_H_ 8 | #define SERVERCHANNEL_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace epics { 16 | namespace pvAccess { 17 | 18 | class BaseChannelRequester; 19 | 20 | class ServerChannel 21 | { 22 | public: 23 | POINTER_DEFINITIONS(ServerChannel); 24 | 25 | static size_t num_instances; 26 | 27 | /** 28 | * Create server channel for given process variable. 29 | * @param channel local channel. 30 | * @param cid channel CID. 31 | * @param sid channel SID. 32 | * @param css channel security session. 33 | */ 34 | ServerChannel(Channel::shared_pointer const & channel, 35 | const ChannelRequester::shared_pointer& requester, 36 | pvAccessID cid, pvAccessID sid); 37 | ~ServerChannel(); 38 | 39 | const Channel::shared_pointer& getChannel() const { return _channel; } 40 | 41 | pvAccessID getCID() const { return _cid; } 42 | 43 | pvAccessID getSID() const { return _sid; } 44 | 45 | void registerRequest(pvAccessID id, const std::tr1::shared_ptr& request); 46 | 47 | void unregisterRequest(pvAccessID id); 48 | 49 | void installGetField(const GetFieldRequester::shared_pointer& gf); 50 | void completeGetField(GetFieldRequester *req); 51 | 52 | //! may return NULL 53 | std::tr1::shared_ptr getRequest(pvAccessID id); 54 | 55 | void destroy(); 56 | 57 | void printInfo() const; 58 | 59 | void printInfo(FILE *fd) const; 60 | private: 61 | const Channel::shared_pointer _channel; 62 | 63 | const ChannelRequester::shared_pointer _requester; 64 | 65 | const pvAccessID _cid, _sid; 66 | 67 | //! keep alive in-progress GetField() 68 | GetFieldRequester::shared_pointer _active_requester; 69 | 70 | typedef std::map > _requests_t; 71 | _requests_t _requests; 72 | 73 | bool _destroyed; 74 | 75 | mutable epics::pvData::Mutex _mutex; 76 | }; 77 | 78 | } 79 | } 80 | 81 | 82 | #endif /* SERVERCHANNEL_H_ */ 83 | -------------------------------------------------------------------------------- /src/ioc/reftrackioc.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * EPICS pvData is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include 17 | 18 | namespace { 19 | 20 | void showRefs(const epics::RefSnapshot& snap, int lvl, bool delta) 21 | { 22 | for(epics::RefSnapshot::const_iterator it = snap.begin(), end = snap.end(); 23 | it != end; ++it) 24 | { 25 | if(it->second.current==0 && it->second.delta==0 && lvl<=0) continue; 26 | if(delta && it->second.delta==0 && lvl<=0) continue; 27 | if(delta) { 28 | printf(" %s : %zu (delta %ld)\n", 29 | it->first.c_str(), it->second.current, it->second.delta); 30 | } else { 31 | printf(" %s : %zu\n", it->first.c_str(), it->second.current); 32 | } 33 | } 34 | } 35 | 36 | #define CATCH() catch(std::exception& e){printf("Error %s\n", e.what());} 37 | 38 | void refshow(int lvl) 39 | { 40 | try { 41 | epics::RefSnapshot snap; 42 | snap.update(); 43 | 44 | showRefs(snap, lvl, false); 45 | }CATCH() 46 | } 47 | 48 | // No locking. assume only interactive iocsh use 49 | static epics::RefSnapshot savedSnap; 50 | 51 | void refsave() 52 | { 53 | try { 54 | epics::RefSnapshot snap; 55 | snap.update(); 56 | 57 | savedSnap.swap(snap); 58 | }CATCH() 59 | } 60 | 61 | void refdiff(int lvl) 62 | { 63 | epics::RefSnapshot snap; 64 | snap.update(); 65 | 66 | showRefs(snap-savedSnap, lvl, true); 67 | } 68 | 69 | static epics::RefMonitor gblmon; 70 | 71 | void refmon(double period, int lvl) 72 | { 73 | if(period==0) { 74 | gblmon.stop(); 75 | } else if(period>0) { 76 | gblmon.start(period); 77 | } 78 | } 79 | 80 | } // namespace 81 | 82 | namespace epics {namespace pvAccess { 83 | 84 | void refTrackRegistrar() 85 | { 86 | epics::iocshRegister("refshow", "detail level"); 87 | epics::iocshRegister<&refsave>("refsave"); 88 | epics::iocshRegister("refdiff", "detail level"); 89 | epics::iocshRegister("refmon", "update period", "detail level"); 90 | } 91 | 92 | }} 93 | 94 | extern "C" { 95 | using namespace epics::pvAccess; 96 | epicsExportRegistrar(refTrackRegistrar); 97 | } 98 | -------------------------------------------------------------------------------- /testApp/remote/rpcServiceExample.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace epics::pvData; 11 | using namespace epics::pvAccess; 12 | 13 | static Structure::const_shared_pointer resultStructure = 14 | getFieldCreate()->createFieldBuilder()-> 15 | add("c", pvDouble)-> 16 | createStructure(); 17 | 18 | // s1 starts with s2 check 19 | static bool starts_with(const std::string& s1, const std::string& s2) { 20 | return s2.size() <= s1.size() && s1.compare(0, s2.size(), s2) == 0; 21 | } 22 | 23 | class SumServiceImpl : 24 | public RPCService 25 | { 26 | PVStructure::shared_pointer request(PVStructure::shared_pointer const & pvArguments) 27 | { 28 | // NTURI support 29 | PVStructure::shared_pointer args( 30 | (starts_with(pvArguments->getStructure()->getID(), "epics:nt/NTURI:1.")) ? 31 | pvArguments->getSubField("query") : 32 | pvArguments 33 | ); 34 | 35 | // get fields and check their existence 36 | PVScalar::shared_pointer af = args->getSubField("a"); 37 | PVScalar::shared_pointer bf = args->getSubField("b"); 38 | if (!af || !bf) 39 | throw RPCRequestException(Status::STATUSTYPE_ERROR, "scalar 'a' and 'b' fields are required"); 40 | 41 | // get the numbers (and convert if neccessary) 42 | double a, b; 43 | try 44 | { 45 | a = af->getAs(); 46 | b = bf->getAs(); 47 | } 48 | catch (std::exception &e) 49 | { 50 | throw RPCRequestException(Status::STATUSTYPE_ERROR, 51 | std::string("failed to convert arguments to double: ") + e.what()); 52 | } 53 | 54 | // create return structure and set data 55 | PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); 56 | result->getSubFieldT("c")->put(a+b); 57 | return result; 58 | } 59 | }; 60 | 61 | int main() 62 | { 63 | RPCServer server; 64 | 65 | server.registerService("sum", RPCService::shared_pointer(new SumServiceImpl())); 66 | // you can register as many services as you want here ... 67 | 68 | server.printInfo(); 69 | server.run(); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /src/remote/beaconHandler.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #define epicsExportSharedSymbols 8 | #include 9 | #include 10 | 11 | using namespace std; 12 | using namespace epics::pvData; 13 | using namespace epics::pvAccess; 14 | 15 | namespace epics { 16 | namespace pvAccess { 17 | 18 | BeaconHandler::BeaconHandler(Context::shared_pointer const & context, 19 | const osiSockAddr* responseFrom) : 20 | _context(Context::weak_pointer(context)), 21 | _mutex(), 22 | _serverGUID(), 23 | _serverChangeCount(-1), 24 | _first(true) 25 | { 26 | 27 | } 28 | 29 | BeaconHandler::~BeaconHandler() 30 | { 31 | } 32 | 33 | void BeaconHandler::beaconNotify(osiSockAddr* /*from*/, int8 remoteTransportRevision, 34 | TimeStamp* timestamp, ServerGUID const & guid, int16 sequentalID, 35 | int16 changeCount, 36 | const PVFieldPtr& /*data*/) 37 | { 38 | bool networkChanged = updateBeacon(remoteTransportRevision, timestamp, guid, sequentalID, changeCount); 39 | // TODO: reduce search timers 40 | (void)networkChanged; 41 | } 42 | 43 | bool BeaconHandler::updateBeacon(int8 /*remoteTransportRevision*/, TimeStamp* /*timestamp*/, 44 | ServerGUID const & guid, int16 /*sequentalID*/, int16 changeCount) 45 | { 46 | Lock guard(_mutex); 47 | // first beacon notification check 48 | if (_first) 49 | { 50 | _first = false; 51 | _serverGUID = guid; 52 | _serverChangeCount = changeCount; 53 | 54 | // new server up.. 55 | _context.lock()->newServerDetected(); 56 | 57 | return false; 58 | } 59 | 60 | bool networkChange = (memcmp(_serverGUID.value, guid.value, sizeof(guid.value)) != 0); 61 | if (networkChange) 62 | { 63 | // update startup time and change count 64 | _serverGUID = guid; 65 | _serverChangeCount = changeCount; 66 | 67 | _context.lock()->newServerDetected(); 68 | 69 | return true; 70 | } 71 | else if (_serverChangeCount != changeCount) 72 | { 73 | // update change count 74 | _serverChangeCount = changeCount; 75 | 76 | // TODO be more specific (possible optimizations) 77 | _context.lock()->newServerDetected(); 78 | 79 | return true; 80 | } 81 | 82 | return false; 83 | } 84 | 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /documentation/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # http://www.sphinx-doc.org/en/master/config 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | # import os 14 | # import sys 15 | # sys.path.insert(0, os.path.abspath('.')) 16 | 17 | 18 | # -- Project information ----------------------------------------------------- 19 | 20 | project = 'EPICS Documentation' 21 | copyright = '2019, EPICS Controls.' 22 | author = 'EPICS' 23 | 24 | 25 | # -- General configuration --------------------------------------------------- 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be 28 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 29 | # ones. 30 | extensions = [ 31 | 'sphinx.ext.intersphinx', 32 | ] 33 | 34 | # Add any paths that contain templates here, relative to this directory. 35 | templates_path = ['_templates'] 36 | 37 | # List of patterns, relative to source directory, that match files and 38 | # directories to ignore when looking for source files. 39 | # This pattern also affects html_static_path and html_extra_path. 40 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 41 | 42 | # Intersphinx links to subprojects 43 | intersphinx_mapping = { 44 | 'how-tos': ('https://docs.epics-controls.org/projects/how-tos/en/latest', None), 45 | } 46 | 47 | 48 | # -- Options for HTML output ------------------------------------------------- 49 | 50 | # The theme to use for HTML and HTML Help pages. See the documentation for 51 | # a list of builtin themes. 52 | # 53 | html_theme = 'sphinx_rtd_theme' 54 | 55 | 56 | # Add any paths that contain custom static files (such as style sheets) here, 57 | # relative to this directory. They are copied after the builtin static files, 58 | # so a file named "default.css" will overwrite the builtin "default.css". 59 | html_static_path = ['_static'] 60 | 61 | html_css_files = [ 62 | 'css/custom.css', 63 | ] 64 | 65 | master_doc = 'index' 66 | 67 | html_theme_options = { 68 | 'logo_only': True, 69 | } 70 | html_logo = "images/EPICS_white_logo_v02.png" 71 | 72 | html_extra_path = ['../html'] 73 | 74 | 75 | # -- Run Doxygen ------------------------------------------------------------ 76 | 77 | import subprocess 78 | subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True) 79 | -------------------------------------------------------------------------------- /testApp/remote/testServerContext.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * testServerContext.cpp 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace { 12 | 13 | using namespace epics::pvAccess; 14 | using namespace epics::pvData; 15 | using namespace std; 16 | 17 | class TestChannelProvider : public ChannelProvider 18 | { 19 | public: 20 | 21 | std::string getProviderName() { 22 | return "local"; 23 | }; 24 | 25 | TestChannelProvider() {} 26 | 27 | ChannelFind::shared_pointer channelFind(std::string const & /*channelName*/, 28 | ChannelFindRequester::shared_pointer const & channelFindRequester) 29 | { 30 | ChannelFind::shared_pointer nullCF; 31 | channelFindRequester->channelFindResult(Status::Ok, nullCF, false); 32 | return nullCF; 33 | } 34 | 35 | ChannelFind::shared_pointer channelList(ChannelListRequester::shared_pointer const & channelListRequester) 36 | { 37 | ChannelFind::shared_pointer nullCF; 38 | PVStringArray::const_svector none; 39 | channelListRequester->channelListResult(Status::Ok, nullCF, none, false); 40 | return nullCF; 41 | } 42 | 43 | Channel::shared_pointer createChannel( 44 | std::string const & channelName, 45 | ChannelRequester::shared_pointer const & channelRequester, 46 | short priority = PRIORITY_DEFAULT) 47 | { 48 | return createChannel(channelName, channelRequester, priority, ""); 49 | } 50 | 51 | Channel::shared_pointer createChannel( 52 | std::string const & /*channelName*/, 53 | ChannelRequester::shared_pointer const & channelRequester, 54 | short /*priority*/, std::string const & /*address*/) 55 | { 56 | Channel::shared_pointer nullC; 57 | channelRequester->channelCreated(Status::Ok, nullC); 58 | return nullC; 59 | } 60 | 61 | void destroy() 62 | { 63 | } 64 | }; 65 | 66 | } // namespace 67 | 68 | MAIN(testServerContext) 69 | { 70 | testPlan(2); 71 | 72 | ChannelProvider::shared_pointer prov(new TestChannelProvider); 73 | ServerContext::shared_pointer ctx(ServerContext::create(ServerContext::Config() 74 | .provider(prov))); 75 | ServerContext::weak_pointer wctx(ctx); 76 | 77 | testOk(ctx.unique(), "# ServerContext::create() returned non-unique instance use_count=%u", (unsigned)ctx.use_count()); 78 | 79 | ctx->printInfo(); 80 | 81 | ctx->run(1); 82 | 83 | ctx.reset(); 84 | 85 | testOk(!wctx.lock(), "# ServerContext cleanup leaves use_count=%u", (unsigned)wctx.use_count()); 86 | 87 | return testDone(); 88 | } 89 | -------------------------------------------------------------------------------- /src/remote/pv/transportRegistry.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef TRANSPORTREGISTRY_H 8 | #define TRANSPORTREGISTRY_H 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #ifdef epicsExportSharedSymbols 16 | # define transportRegistryEpicsExportSharedSymbols 17 | # undef epicsExportSharedSymbols 18 | #endif 19 | 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef transportRegistryEpicsExportSharedSymbols 28 | # define epicsExportSharedSymbols 29 | # undef transportRegistryEpicsExportSharedSymbols 30 | #endif 31 | 32 | #include 33 | #include 34 | 35 | namespace epics { 36 | namespace pvAccess { 37 | 38 | class TransportRegistry { 39 | public: 40 | class Reservation; 41 | private: 42 | struct Key { 43 | osiSockAddr addr; 44 | epics::pvData::int16 prio; 45 | Key(const osiSockAddr& a, epics::pvData::int16 p) :addr(a), prio(p) {} 46 | bool operator<(const Key& o) const; 47 | }; 48 | 49 | typedef std::map transports_t; 50 | typedef std::map > locks_t; 51 | 52 | public: 53 | POINTER_DEFINITIONS(TransportRegistry); 54 | 55 | typedef std::vector transportVector_t; 56 | 57 | class Reservation { 58 | TransportRegistry* const owner; 59 | const Key key; 60 | std::tr1::shared_ptr mutex; 61 | public: 62 | 63 | // ctor blocks until no concurrent connect() in progress (success or failure) 64 | Reservation(TransportRegistry *owner, const osiSockAddr& address, epics::pvData::int16 prio); 65 | ~Reservation(); 66 | }; 67 | 68 | TransportRegistry() {} 69 | ~TransportRegistry(); 70 | 71 | Transport::shared_pointer get(const osiSockAddr& address, epics::pvData::int16 prio); 72 | void install(const Transport::shared_pointer& ptr); 73 | Transport::shared_pointer remove(Transport::shared_pointer const & transport); 74 | void clear(); 75 | size_t size(); 76 | 77 | // optimized to avoid reallocation, adds to array 78 | void toArray(transportVector_t & transportArray, const osiSockAddr *dest=0); 79 | 80 | private: 81 | transports_t transports; 82 | // per destination mutex to serialize concurrent connect() attempts 83 | locks_t locks; 84 | 85 | epics::pvData::Mutex _mutex; 86 | }; 87 | 88 | } 89 | } 90 | 91 | #endif /* INTROSPECTIONREGISTRY_H */ 92 | -------------------------------------------------------------------------------- /src/utils/pv/referenceCountingLock.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef REFERENCECOUNTINGLOCK_H 8 | #define REFERENCECOUNTINGLOCK_H 9 | 10 | #ifdef epicsExportSharedSymbols 11 | # define referenceCountingLockEpicsExportSharedSymbols 12 | # undef epicsExportSharedSymbols 13 | #endif 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #ifdef referenceCountingLockEpicsExportSharedSymbols 20 | # define epicsExportSharedSymbols 21 | # undef referenceCountingLockEpicsExportSharedSymbols 22 | #endif 23 | 24 | namespace epics { 25 | namespace pvAccess { 26 | 27 | /** 28 | * Reference counting mutex implementation w/ deadlock detection. 29 | * Synchronization helper class used (intended for use) for activation/deactivation synchronization. 30 | * This class enforces attempt method of acquiring the locks to prevent deadlocks. 31 | * Class also offers reference counting. 32 | * (NOTE: automatic lock counting was not implemented due to imperfect usage.) 33 | * 34 | */ 35 | class ReferenceCountingLock 36 | { 37 | public: 38 | POINTER_DEFINITIONS(ReferenceCountingLock); 39 | 40 | /** 41 | * Constructor of ReferenceCountingLock. 42 | * After construction lock is free and reference count equals 1. 43 | */ 44 | ReferenceCountingLock(); 45 | /** 46 | * Destructor of ReferenceCountingLock. 47 | */ 48 | virtual ~ReferenceCountingLock(); 49 | /** 50 | * Attempt to acquire lock. 51 | * 52 | * NOTE: Argument msecs is currently not supported due to 53 | * Darwin OS not supporting pthread_mutex_timedlock. May be changed in the future. 54 | * 55 | * @param msecs the number of milleseconds to wait. 56 | * An argument less than or equal to zero means not to wait at all. 57 | * 58 | * @return true if acquired, false otherwise. 59 | * NOTE: currently this routine always returns true. Look above for explanation. 60 | * 61 | */ 62 | bool acquire(epics::pvData::int64 msecs); 63 | /** 64 | * Release previously acquired lock. 65 | */ 66 | void release(); 67 | /** 68 | * Increment number of references. 69 | * 70 | * @return number of references. 71 | */ 72 | int increment(); 73 | /** 74 | * Decrement number of references. 75 | * 76 | * @return number of references. 77 | */ 78 | int decrement(); 79 | private: 80 | int _references; 81 | epics::pvData::Mutex _mutex; 82 | epics::pvData::Mutex _countMutex; 83 | }; 84 | 85 | } 86 | } 87 | 88 | #endif /* REFERENCECOUNTINGLOCK_H */ 89 | -------------------------------------------------------------------------------- /src/rpcService/pv/rpcService.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef RPCSERVICE_H 8 | #define RPCSERVICE_H 9 | 10 | #include 11 | 12 | #ifdef epicsExportSharedSymbols 13 | # define rpcServiceEpicsExportSharedSymbols 14 | # undef epicsExportSharedSymbols 15 | #endif 16 | 17 | #include 18 | #include 19 | 20 | #ifdef rpcServiceEpicsExportSharedSymbols 21 | # define epicsExportSharedSymbols 22 | # undef rpcServiceEpicsExportSharedSymbols 23 | #endif 24 | 25 | #include 26 | 27 | #include 28 | 29 | namespace epics { 30 | namespace pvAccess { 31 | 32 | class RPCRequestException : public std::runtime_error { 33 | public: 34 | 35 | explicit RPCRequestException(std::string const & message) : 36 | std::runtime_error(message), m_status(epics::pvData::Status::STATUSTYPE_ERROR) 37 | {} 38 | 39 | RPCRequestException(epics::pvData::Status::StatusType status, std::string const & message) : 40 | std::runtime_error(message), m_status(status) 41 | {} 42 | 43 | epics::pvData::Status::StatusType getStatus() const { 44 | return m_status; 45 | } 46 | 47 | epics::pvData::Status asStatus() const { 48 | return epics::pvData::Status(m_status, what()); 49 | } 50 | private: 51 | epics::pvData::Status::StatusType m_status; 52 | }; 53 | 54 | class epicsShareClass RPCResponseCallback 55 | { 56 | public: 57 | POINTER_DEFINITIONS(RPCResponseCallback); 58 | 59 | virtual ~RPCResponseCallback() {}; 60 | 61 | virtual void requestDone( 62 | epics::pvData::Status const & status, 63 | epics::pvData::PVStructure::shared_pointer const & result 64 | ) = 0; 65 | }; 66 | 67 | class epicsShareClass RPCServiceAsync 68 | { 69 | public: 70 | POINTER_DEFINITIONS(RPCServiceAsync); 71 | 72 | virtual ~RPCServiceAsync() {}; 73 | 74 | virtual void request( 75 | epics::pvData::PVStructure::shared_pointer const & args, 76 | RPCResponseCallback::shared_pointer const & callback 77 | ) = 0; 78 | }; 79 | 80 | class epicsShareClass RPCService : 81 | public RPCServiceAsync 82 | { 83 | public: 84 | POINTER_DEFINITIONS(RPCService); 85 | 86 | virtual ~RPCService() {}; 87 | 88 | virtual epics::pvData::PVStructure::shared_pointer request( 89 | epics::pvData::PVStructure::shared_pointer const & args 90 | ) = 0; 91 | 92 | private: 93 | virtual void request( 94 | epics::pvData::PVStructure::shared_pointer const & args, 95 | RPCResponseCallback::shared_pointer const & callback 96 | ) OVERRIDE FINAL; 97 | }; 98 | 99 | } 100 | } 101 | 102 | #endif /* RPCSERVICE_H */ 103 | -------------------------------------------------------------------------------- /testApp/remote/rpcServiceAsyncExample.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | using namespace epics::pvData; 11 | using namespace epics::pvAccess; 12 | 13 | static Structure::const_shared_pointer resultStructure = 14 | getFieldCreate()->createFieldBuilder()-> 15 | add("c", pvDouble)-> 16 | createStructure(); 17 | 18 | // s1 starts with s2 check 19 | static bool starts_with(const std::string& s1, const std::string& s2) { 20 | return s2.size() <= s1.size() && s1.compare(0, s2.size(), s2) == 0; 21 | } 22 | 23 | class SumServiceImpl : 24 | public RPCServiceAsync 25 | { 26 | void request(PVStructure::shared_pointer const & pvArguments, 27 | RPCResponseCallback::shared_pointer const & callback) 28 | { 29 | // NTURI support 30 | PVStructure::shared_pointer args( 31 | (starts_with(pvArguments->getStructure()->getID(), "epics:nt/NTURI:1.")) ? 32 | pvArguments->getSubField("query") : 33 | pvArguments 34 | ); 35 | 36 | // get fields and check their existence 37 | PVScalar::shared_pointer af = args->getSubField("a"); 38 | PVScalar::shared_pointer bf = args->getSubField("b"); 39 | if (!af || !bf) 40 | { 41 | callback->requestDone( 42 | Status( 43 | Status::STATUSTYPE_ERROR, 44 | "scalar 'a' and 'b' fields are required" 45 | ), 46 | PVStructure::shared_pointer()); 47 | return; 48 | } 49 | 50 | // get the numbers (and convert if neccessary) 51 | double a, b; 52 | try 53 | { 54 | a = af->getAs(); 55 | b = bf->getAs(); 56 | } 57 | catch (std::exception &e) 58 | { 59 | callback->requestDone( 60 | Status( 61 | Status::STATUSTYPE_ERROR, 62 | std::string("failed to convert arguments to double: ") + e.what() 63 | ), 64 | PVStructure::shared_pointer()); 65 | return; 66 | } 67 | 68 | // create return structure and set data 69 | PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); 70 | result->getSubField("c")->put(a+b); 71 | 72 | callback->requestDone(Status::Ok, result); 73 | } 74 | }; 75 | 76 | int main() 77 | { 78 | RPCServer server; 79 | 80 | server.registerService("sum", RPCServiceAsync::shared_pointer(new SumServiceImpl())); 81 | // you can register as many services as you want here ... 82 | 83 | server.printInfo(); 84 | server.run(); 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /src/utils/referenceCountingLock.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #define epicsExportSharedSymbols 8 | #include 9 | 10 | namespace epics { 11 | namespace pvAccess { 12 | 13 | using namespace epics::pvData; 14 | 15 | ReferenceCountingLock::ReferenceCountingLock(): _references(1) 16 | { 17 | /* pthread_mutexattr_t mutexAttribute; 18 | int32 retval = pthread_mutexattr_init(&mutexAttribute); 19 | if(retval != 0) 20 | { 21 | //string errMsg = "Error: pthread_mutexattr_init failed: " + string(strerror(retval)); 22 | assert(false); 23 | } 24 | retval = pthread_mutexattr_settype(&mutexAttribute, PTHREAD_MUTEX_RECURSIVE); 25 | if(retval == 0) 26 | { 27 | retval = pthread_mutex_init(_mutex, &mutexAttribute); 28 | if(retval != 0) 29 | { 30 | //string errMsg = "Error: pthread_mutex_init failed: " + string(strerror(retval)); 31 | assert(false); 32 | } 33 | } 34 | else 35 | { 36 | //string errMsg = "Error: pthread_mutexattr_settype failed: " + string(strerror(retval)); 37 | assert(false); 38 | } 39 | 40 | pthread_mutexattr_destroy(&mutexAttribute);*/ 41 | } 42 | 43 | ReferenceCountingLock::~ReferenceCountingLock() 44 | { 45 | // pthread_mutex_destroy(_mutex); 46 | } 47 | 48 | bool ReferenceCountingLock::acquire(int64 /*msecs*/) 49 | { 50 | _mutex.lock(); 51 | return true; 52 | /* struct timespec deltatime; 53 | if(msecs > 0) 54 | { 55 | deltatime.tv_sec = msecs / 1000; 56 | deltatime.tv_nsec = (msecs % 1000) * 1000; 57 | } 58 | else 59 | { 60 | deltatime.tv_sec = 0; 61 | deltatime.tv_nsec = 0; 62 | } 63 | 64 | int32 retval = pthread_mutex_timedlock(_mutex, &deltatime); 65 | if(retval == 0) 66 | { 67 | return true; 68 | } 69 | return false; 70 | */ 71 | } 72 | 73 | void ReferenceCountingLock::release() 74 | { 75 | _mutex.unlock(); 76 | /* int retval = pthread_mutex_unlock(_mutex); 77 | if(retval != 0) 78 | { 79 | //string errMsg = "Error: pthread_mutex_unlock failed: " + string(strerror(retval)); 80 | //TODO do something? 81 | }*/ 82 | } 83 | 84 | // TODO use atomic primitive impl. 85 | int ReferenceCountingLock::increment() 86 | { 87 | Lock guard(_countMutex); 88 | ++_references; 89 | return _references; 90 | } 91 | 92 | int ReferenceCountingLock::decrement() 93 | { 94 | Lock guard(_countMutex); 95 | --_references; 96 | return _references; 97 | } 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/ca/notifierConveyor.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include // Needed for 3.15 builds 14 | #include 15 | #include 16 | 17 | #define epicsExportSharedSymbols 18 | #include "notifierConveyor.h" 19 | 20 | namespace epics { 21 | namespace pvAccess { 22 | namespace ca { 23 | 24 | NotifierConveyor::~NotifierConveyor() 25 | { 26 | if (thread) { 27 | if (thread->isCurrentThread()) { 28 | cantProceed("NotifierConveyor: Can't delete me in notify()!\n"); 29 | } 30 | { 31 | epicsGuard G(mutex); 32 | halt = true; 33 | } 34 | workToDo.trigger(); 35 | thread->exitWait(); 36 | } 37 | } 38 | 39 | void NotifierConveyor::start() 40 | { 41 | if (thread) return; 42 | char name[40]; 43 | epicsSnprintf(name, sizeof(name), "pva::ca::conveyor %p", this); 44 | thread = std::tr1::shared_ptr(new epicsThread(*this, name, 45 | epicsThreadGetStackSize(epicsThreadStackBig), 46 | epicsThreadPriorityLow)); 47 | thread->start(); 48 | } 49 | 50 | void NotifierConveyor::notifyClient( 51 | NotificationPtr const ¬ificationPtr) 52 | { 53 | { 54 | epicsGuard G(mutex); 55 | if (halt || notificationPtr->queued) return; 56 | notificationPtr->queued = true; 57 | workQueue.push(notificationPtr); 58 | } 59 | workToDo.trigger(); 60 | } 61 | 62 | void NotifierConveyor::run() 63 | { 64 | bool stopping; 65 | do { 66 | workToDo.wait(); 67 | epicsGuard G(mutex); 68 | stopping = halt; 69 | while (!stopping && !workQueue.empty()) { 70 | NotificationWPtr notificationWPtr(workQueue.front()); 71 | workQueue.pop(); 72 | NotificationPtr notification(notificationWPtr.lock()); 73 | if (notification) { 74 | notification->queued = false; 75 | epicsGuardRelease U(G); 76 | NotifierClientPtr client(notification->client.lock()); 77 | if (client) { 78 | try { client->notifyClient(); } 79 | catch (std::exception &e) { 80 | std::cerr << "Exception from notifyClient(): " 81 | << e.what() << std::endl; 82 | } 83 | catch (...) { 84 | std::cerr << "Unknown exception from notifyClient()" 85 | << std::endl; 86 | } 87 | } 88 | } 89 | stopping = halt; 90 | } 91 | } while (!stopping); 92 | } 93 | 94 | }}} 95 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright and License Terms 2 | --------------------------- 3 | 4 | Copyright (c) 2006-2016 Martin R. Kraimer 5 | Copyright (c) 2006-2016 UChicago Argonne LLC, as Operator of Argonne 6 | National Laboratory. 7 | Copyright (c) 2006 Deutsches Elektronen-Synchrotron, 8 | Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. 9 | Copyright (c) 2007-2016 Control System Laboratory, 10 | (COSYLAB) Ljubljana Slovenia 11 | Copyright (c) 2010-2016 Brookhaven Science Associates, as Operator 12 | of Brookhaven National Laboratory 13 | Copyright (c) 2011-2016 Diamond Light Source Limited, 14 | (DLS) Didcot, United Kingdom 15 | 16 | Permission is hereby granted, free of charge, to any person 17 | obtaining a copy of this software and associated documentation 18 | files (the "Software"), to deal in the Software without 19 | restriction, including without limitation the rights to use, 20 | copy, modify, merge, publish, distribute, sublicense, and/or sell 21 | copies of the Software, and to permit persons to whom the 22 | Software is furnished to do so, subject to the following 23 | conditions: 24 | 25 | The above copyright notice and this permission notice shall be 26 | included in all copies or substantial portions of the Software. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 29 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 30 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 31 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 32 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 33 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 34 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 35 | OTHER DEALINGS IN THE SOFTWARE. 36 | 37 | ________________________________________________________________________ 38 | 39 | Additional Disclaimers 40 | ---------------------- 41 | 42 | This software is copyright in part by these institutions: 43 | 44 | * Brookhaven Science Associates, as Operator of Brookhaven 45 | National Laboratory, New York, USA 46 | * Control System Laboratory, Ljubljana, Slovenia 47 | * Deutsches Elektronen-Synchroton, Member of the Helmholtz 48 | Association, Hamburg, Germany 49 | * Diamond Light Source Limited, Didcot, United Kingdom 50 | * Helmholtz-Zentrum Berlin fuer Materialien und Energie m.b.H., 51 | Berlin, Germany. 52 | * UChicage Argonne LLC, as Operator of Argonne National Laboratory, 53 | Illinois, USA 54 | 55 | In no event shall these institutions be liable to any party for direct, 56 | indirect, special, incidental, or consequential damages arising out of 57 | the use of this software, its documentation, or any derivatives thereof, 58 | even if advised of the possibility of such damage. 59 | 60 | These institutions specifically disclaim any warranties, including, but 61 | not limited to, the implied warranties of merchantability, fitness for a 62 | particular purpose, and non-infringement. This software is provided on 63 | an "as is" basis, and these institutions have no obligation to provide 64 | maintenance, support, updates, enhancements, or modifications. 65 | 66 | -------------------------------------------------------------------------------- /documentation/client_ownership.dot: -------------------------------------------------------------------------------- 1 | digraph clientowner { 2 | ChannelProvider; 3 | Channel; 4 | ChannelRequester [shape=box]; 5 | External [shape=box]; 6 | 7 | Channel; 8 | ChannelRequester [shape=box]; 9 | ChannelGet; 10 | ChannelGetRequester [shape=box]; 11 | ChannelPut; 12 | ChannelPutRequester [shape=box]; 13 | Monitor; 14 | MonitorRequester [shape=box]; 15 | ChannelRPC; 16 | ChannelRPCRequester [shape=box]; 17 | ChannelProcess; 18 | ChannelProcessRequester [shape=box]; 19 | ChannelPutGet; 20 | ChannelPutGetRequester [shape=box]; 21 | ChannelArray; 22 | ChannelArrayRequester [shape=box]; 23 | 24 | Channel -> ChannelProvider [color=green, style=dashed]; 25 | ChannelProvider -> Channel [color=green, style=dashed]; 26 | 27 | # Operation -> Requester weak ref 28 | Channel -> ChannelRequester [color=green, style=dashed]; 29 | ChannelGet -> ChannelGetRequester [color=green, style=dashed]; 30 | ChannelPut -> ChannelPutRequester [color=green, style=dashed]; 31 | Monitor -> MonitorRequester [color=green, style=dashed]; 32 | ChannelRPC -> ChannelRPCRequester [color=green, style=dashed]; 33 | ChannelProcess -> ChannelProcessRequester [color=green, style=dashed]; 34 | ChannelPutGet -> ChannelPutGetRequester [color=green, style=dashed]; 35 | ChannelArray -> ChannelArrayRequester [color=green, style=dashed]; 36 | 37 | # Channel -> Operation weak ref 38 | Channel -> ChannelGet [color=green, style=dashed]; 39 | Channel -> ChannelPut [color=green, style=dashed]; 40 | Channel -> Monitor [color=green, style=dashed]; 41 | Channel -> ChannelRPC [color=green, style=dashed]; 42 | Channel -> ChannelProcess [color=green, style=dashed]; 43 | Channel -> ChannelPutGet [color=green, style=dashed]; 44 | Channel -> ChannelArray [color=green, style=dashed]; 45 | 46 | # Operation -> Channel strong ref 47 | ChannelGet -> Channel [color=red, style=dashed]; 48 | ChannelPut -> Channel [color=red, style=dashed]; 49 | Monitor -> Channel [color=red, style=dashed]; 50 | ChannelRPC -> Channel [color=red, style=dashed]; 51 | ChannelProcess -> Channel [color=red, style=dashed]; 52 | ChannelPutGet -> Channel [color=red, style=dashed]; 53 | ChannelArray -> Channel [color=red, style=dashed]; 54 | 55 | # user code ownership 56 | External -> ChannelProvider [color=red]; 57 | External -> ChannelRequester [color=red]; 58 | External -> ChannelGetRequester [color=red]; 59 | External -> ChannelPutRequester [color=red]; 60 | External -> MonitorRequester [color=red]; 61 | External -> ChannelRPCRequester [color=red]; 62 | External -> ChannelProcessRequester [color=red]; 63 | External -> ChannelPutGetRequester [color=red]; 64 | External -> ChannelArrayRequester [color=red]; 65 | 66 | ChannelRequester -> Channel [color=red]; 67 | ChannelGetRequester -> ChannelGet [color=red]; 68 | ChannelPutRequester -> ChannelPut [color=red]; 69 | MonitorRequester -> Monitor [color=red]; 70 | ChannelRPCRequester -> ChannelRPC [color=red]; 71 | ChannelProcessRequester -> ChannelProcess [color=red]; 72 | ChannelPutGetRequester -> ChannelPutGet [color=red]; 73 | ChannelArrayRequester -> ChannelArray [color=red]; 74 | } 75 | -------------------------------------------------------------------------------- /examples/minimonitor.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright information and license terms for this software can be 3 | * found in the file LICENSE that is included with the distribution 4 | */ 5 | // The simplest possible PVA monitor 6 | 7 | #include 8 | 9 | #if !defined(_WIN32) 10 | #include 11 | #define USE_SIGNAL 12 | #endif 13 | 14 | #include 15 | 16 | #include 17 | 18 | static volatile bool done; 19 | 20 | #ifdef USE_SIGNAL 21 | static pvac::MonitorSync * volatile subscription; 22 | static 23 | void handler(int num) 24 | { 25 | (void)num; 26 | done = true; 27 | pvac::MonitorSync *mon = subscription; 28 | if(mon) 29 | mon->wake(); 30 | } 31 | #endif 32 | 33 | int main(int argc, char *argv[]) 34 | { 35 | try { 36 | if(argc<=1) { 37 | std::cerr<<"Usage: "<\n"; 38 | return 1; 39 | } 40 | 41 | pvac::ClientProvider provider("pva"); 42 | 43 | pvac::ClientChannel channel(provider.connect(argv[1])); 44 | 45 | pvac::MonitorSync mon(channel.monitor()); 46 | 47 | #ifdef USE_SIGNAL 48 | subscription = &mon; 49 | signal(SIGINT, handler); 50 | signal(SIGTERM, handler); 51 | signal(SIGQUIT, handler); 52 | #endif 53 | 54 | int ret = 0; 55 | 56 | while(!done) { 57 | if(!mon.wait()) // updates mon.event 58 | continue; 59 | 60 | switch(mon.event.event) { 61 | // Subscription network/internal error 62 | case pvac::MonitorEvent::Fail: 63 | std::cerr<\n"; 70 | done = true; 71 | break; 72 | // Underlying channel becomes disconnected 73 | case pvac::MonitorEvent::Disconnect: 74 | std::cout<\n"; 75 | break; 76 | // Data queue becomes not-empty 77 | case pvac::MonitorEvent::Data: 78 | // We drain event FIFO completely 79 | while(mon.poll()) { 80 | std::cout<\n"; 86 | } 87 | break; 88 | } 89 | } 90 | 91 | #ifdef USE_SIGNAL 92 | signal(SIGINT, SIG_DFL); 93 | signal(SIGTERM, SIG_DFL); 94 | signal(SIGQUIT, SIG_DFL); 95 | subscription = 0; 96 | #endif 97 | 98 | return ret; 99 | }catch(std::exception& e){ 100 | std::cerr<<"Error: "< 11 | 12 | #ifdef epicsExportSharedSymbols 13 | # define pvaConstantsepicsExportSharedSymbols 14 | # undef epicsExportSharedSymbols 15 | #endif 16 | 17 | #include 18 | 19 | #ifdef pvaConstantsepicsExportSharedSymbols 20 | # define epicsExportSharedSymbols 21 | # undef pvaConstantsepicsExportSharedSymbols 22 | #endif 23 | #include 24 | 25 | namespace epics { 26 | namespace pvAccess { 27 | 28 | /** PVA protocol magic number */ 29 | const epics::pvData::int8 PVA_MAGIC = static_cast(0xCA); 30 | 31 | const epics::pvData::int8 PVA_SERVER_PROTOCOL_REVISION = 2; 32 | const epics::pvData::int8 PVA_CLIENT_PROTOCOL_REVISION = 2; 33 | 34 | /** PVA protocol revision (implemented by this library). */ 35 | const epics::pvData::int8 PVA_PROTOCOL_REVISION EPICS_DEPRECATED = 1; 36 | 37 | /** PVA version signature used to report this implementation version in header. */ 38 | const epics::pvData::int8 PVA_VERSION EPICS_DEPRECATED = 1; 39 | 40 | /** Default PVA server port. */ 41 | const epics::pvData::int32 PVA_SERVER_PORT = 5075; 42 | 43 | /** Default PVA beacon port. */ 44 | const epics::pvData::int32 PVA_BROADCAST_PORT = 5076; 45 | 46 | /** PVA protocol message header size. */ 47 | const epics::pvData::int16 PVA_MESSAGE_HEADER_SIZE = 8; 48 | 49 | /** 50 | * UDP maximum send message size. 51 | * MAX_UDP: 1500 (max of ethernet and 802.{2,3} MTU) - 20/40(IPv4/IPv6) 52 | * - 8(UDP) - some reserve (the MTU of Ethernet is currently independent 53 | * of its speed variant) 54 | */ 55 | const epics::pvData::int32 MAX_UDP_UNFRAGMENTED_SEND = 1440; 56 | 57 | /** 58 | * UDP maximum receive message size. 59 | * MAX_UDP: 65535 (max UDP packet size) - 20/40(IPv4/IPv6) - 8(UDP) 60 | */ 61 | const epics::pvData::int32 MAX_UDP_RECV = 65487; 62 | 63 | /** TCP maximum receive message size. */ 64 | const epics::pvData::int32 MAX_TCP_RECV = 1024*16; 65 | 66 | /** Maximum number of search requests in one search message. */ 67 | const epics::pvData::int32 MAX_SEARCH_BATCH_COUNT = 0x7FFF; // 32767 68 | 69 | /** Default priority (corresponds to POSIX SCHED_OTHER) */ 70 | const epics::pvData::int16 PVA_DEFAULT_PRIORITY = 0; 71 | 72 | /** Unreasonable channel name length. */ 73 | const epics::pvData::uint32 MAX_CHANNEL_NAME_LENGTH = 500; 74 | 75 | /** Invalid data type. */ 76 | const epics::pvData::int16 INVALID_DATA_TYPE = -1; 77 | 78 | /** Invalid IOID. */ 79 | const epics::pvData::int32 INVALID_IOID = 0; 80 | 81 | /** Default PVA provider name. */ 82 | epicsShareExtern const std::string PVACCESS_DEFAULT_PROVIDER; 83 | 84 | /** "All-providers registered" PVA provider name. */ 85 | epicsShareExtern const std::string PVACCESS_ALL_PROVIDERS; 86 | 87 | /** Name of the system env. variable to turn on debugging. */ 88 | epicsShareExtern const std::string PVACCESS_DEBUG; 89 | } 90 | } 91 | 92 | #endif /* PVACONSTANTS_H_ */ 93 | -------------------------------------------------------------------------------- /src/utils/hexDump.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include 14 | 15 | #define epicsExportSharedSymbols 16 | #include 17 | 18 | namespace epics { 19 | namespace pvAccess { 20 | 21 | HexDump::HexDump(const char* buf, size_t len) 22 | :buf(buf) 23 | ,buflen(len) 24 | ,_limit(1024u) 25 | ,_groupBy(4u) 26 | ,_perLine(16u) 27 | {} 28 | 29 | HexDump::HexDump(const pvData::ByteBuffer& bb, 30 | size_t size, size_t offset) 31 | :buf(bb.getBuffer() + bb.getPosition()) 32 | ,buflen(bb.getRemaining()) 33 | ,_limit((size_t)-1) 34 | ,_groupBy(4u) 35 | ,_perLine(16u) 36 | { 37 | if(offset > buflen) 38 | offset = buflen; 39 | buf += offset; 40 | buflen -= offset; 41 | if(buflen > size) 42 | buflen = size; 43 | } 44 | 45 | HexDump::~HexDump() {} 46 | 47 | static 48 | size_t ilog2(size_t val) 49 | { 50 | size_t ret = 0; 51 | while(val >>= 1) 52 | ret++; 53 | return ret; 54 | } 55 | 56 | static 57 | size_t bits2bytes(size_t val) 58 | { 59 | // round up to next multiple of 8 60 | val -= 1u; 61 | val |= 7u; 62 | val += 1u; 63 | // bits -> bytes 64 | val /= 8u; 65 | return val; 66 | } 67 | 68 | epicsShareFunc 69 | std::ostream& operator<<(std::ostream& strm, const HexDump& hex) 70 | { 71 | const size_t len = std::min(hex.buflen, hex._limit); 72 | // find address width in hex chars 73 | // find bit width, rounded up to 8 bits, divide down to bytes 74 | const size_t addrwidth = bits2bytes(ilog2(len))*2u; 75 | size_t nlines = len/hex._perLine; 76 | 77 | if(len%hex._perLine) 78 | nlines++; 79 | 80 | std::ios::fmtflags initialflags = strm.flags(); 81 | strm<=' ' && val<='~') { 110 | strm< 8 | #include 9 | 10 | using namespace epics::pvData; 11 | using namespace epics::pvAccess; 12 | 13 | static Structure::const_shared_pointer dataStructure = 14 | getFieldCreate()->createFieldBuilder()-> 15 | add("count", pvInt)-> 16 | createStructure(); 17 | 18 | class PipelineSessionImpl : 19 | public PipelineSession 20 | { 21 | public: 22 | 23 | PipelineSessionImpl( 24 | epics::pvData::PVStructure::shared_pointer const & pvRequest 25 | ) : 26 | m_counter(0), 27 | m_max(0) 28 | { 29 | PVStructure::shared_pointer pvOptions = pvRequest->getSubField("record._options"); 30 | if (pvOptions) { 31 | PVString::shared_pointer pvString = pvOptions->getSubField("limit"); 32 | if (pvString) 33 | { 34 | // note: this throws an exception if conversion fails 35 | m_max = pvString->getAs(); 36 | } 37 | } 38 | 39 | } 40 | 41 | size_t getMinQueueSize() const { 42 | return 16; //1024; 43 | } 44 | 45 | Structure::const_shared_pointer getStructure() const { 46 | return dataStructure; 47 | } 48 | 49 | virtual void request(PipelineControl::shared_pointer const & control, size_t elementCount) { 50 | // blocking in this call is not a good thing 51 | // but generating a simple counter data is fast 52 | // we will generate as much elements as we can 53 | size_t count = control->getFreeElementCount(); 54 | for (size_t i = 0; i < count; i++) { 55 | MonitorElement::shared_pointer element = control->getFreeElement(); 56 | element->pvStructurePtr->getSubField(1 /*"count"*/)->put(m_counter++); 57 | control->putElement(element); 58 | 59 | // we reached the limit, no more data 60 | if (m_max != 0 && m_counter == m_max) 61 | { 62 | control->done(); 63 | break; 64 | } 65 | } 66 | } 67 | 68 | virtual void cancel() { 69 | // noop, no need to clean any data-source resources 70 | } 71 | 72 | private: 73 | // NOTE: all the request calls will be made from the same thread, so we do not need sync m_counter 74 | int32 m_counter; 75 | int32 m_max; 76 | }; 77 | 78 | class PipelineServiceImpl : 79 | public PipelineService 80 | { 81 | PipelineSession::shared_pointer createPipeline( 82 | epics::pvData::PVStructure::shared_pointer const & pvRequest 83 | ) 84 | { 85 | return PipelineSession::shared_pointer(new PipelineSessionImpl(pvRequest)); 86 | } 87 | }; 88 | 89 | int main() 90 | { 91 | PipelineServer server; 92 | 93 | server.registerService("counterPipe", PipelineService::shared_pointer(new PipelineServiceImpl())); 94 | // you can register as many services as you want here ... 95 | 96 | server.printInfo(); 97 | server.run(); 98 | 99 | return 0; 100 | } 101 | -------------------------------------------------------------------------------- /src/pipelineService/pv/pipelineService.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef PIPELINESERVICE_H 8 | #define PIPELINESERVICE_H 9 | 10 | #include 11 | 12 | #ifdef epicsExportSharedSymbols 13 | # define pipelineServiceEpicsExportSharedSymbols 14 | # undef epicsExportSharedSymbols 15 | #endif 16 | 17 | #include 18 | #include 19 | 20 | #ifdef pipelineServiceEpicsExportSharedSymbols 21 | # define epicsExportSharedSymbols 22 | # undef pipelineServiceEpicsExportSharedSymbols 23 | #endif 24 | 25 | #include 26 | 27 | #include 28 | 29 | namespace epics { 30 | namespace pvAccess { 31 | 32 | class epicsShareClass PipelineControl 33 | { 34 | public: 35 | POINTER_DEFINITIONS(PipelineControl); 36 | 37 | virtual ~PipelineControl() {}; 38 | 39 | /// Number of free elements in the local queue. 40 | /// A service can (should) full up the entire queue. 41 | virtual size_t getFreeElementCount() = 0; 42 | 43 | /// Total count of requested elements. 44 | /// This is the minimum element count that a service should provide. 45 | virtual size_t getRequestedCount() = 0; 46 | 47 | /// Grab next free element. 48 | /// A service should take this element, populate it with the data 49 | /// and return it back by calling putElement(). 50 | virtual MonitorElement::shared_pointer getFreeElement() = 0; 51 | 52 | /// Put element on the local queue (an element to be sent to a client). 53 | virtual void putElement(MonitorElement::shared_pointer const & element) = 0; 54 | 55 | /// Call to notify that there is no more data to pipelined. 56 | /// This call destroyes corresponding pipeline session. 57 | virtual void done() = 0; 58 | 59 | }; 60 | 61 | 62 | class epicsShareClass PipelineSession 63 | { 64 | public: 65 | POINTER_DEFINITIONS(PipelineSession); 66 | 67 | virtual ~PipelineSession() {}; 68 | 69 | /// Returns (minimum) local queue size. 70 | /// Actual local queue size = max( getMinQueueSize(), client queue size ); 71 | virtual size_t getMinQueueSize() const = 0; 72 | 73 | /// Description of the structure used by this session. 74 | virtual epics::pvData::Structure::const_shared_pointer getStructure() const = 0; 75 | 76 | /// Request for additional (!) elementCount elements. 77 | /// The service should eventually call PipelineControl.getFreeElement() and PipelineControl.putElement() 78 | /// to provide [PipelineControl.getRequestedCount(), PipelineControl.getFreeElementCount()] elements. 79 | virtual void request(PipelineControl::shared_pointer const & control, size_t elementCount) = 0; 80 | 81 | /// Cancel the session (called by the client). 82 | virtual void cancel() = 0; 83 | }; 84 | 85 | 86 | class epicsShareClass PipelineService 87 | { 88 | public: 89 | POINTER_DEFINITIONS(PipelineService); 90 | 91 | virtual ~PipelineService() {}; 92 | 93 | virtual PipelineSession::shared_pointer createPipeline( 94 | epics::pvData::PVStructure::shared_pointer const & pvRequest 95 | ) = 0; 96 | 97 | }; 98 | 99 | 100 | } 101 | } 102 | 103 | #endif /* PIPELINESERVICE_H */ 104 | -------------------------------------------------------------------------------- /src/utils/pv/inetAddressUtil.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef INETADDRESSUTIL_H_ 8 | #define INETADDRESSUTIL_H_ 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | 15 | #include 16 | #include 17 | 18 | namespace epics { 19 | namespace pvAccess { 20 | 21 | typedef std::vector InetAddrVector; 22 | 23 | struct ifaceNode { 24 | osiSockAddr addr, //!< Our address 25 | peer, //!< point to point peer 26 | bcast,//!< sub-net broadcast address 27 | mask; //!< Net mask 28 | bool loopback, 29 | validP2P, //!< true if peer has been set. 30 | validBcast; //!< true if bcast and mask have been set 31 | ifaceNode(); 32 | }; 33 | typedef std::vector IfaceNodeVector; 34 | epicsShareFunc int discoverInterfaces(IfaceNodeVector &list, SOCKET socket, const osiSockAddr *pMatchAddr = 0); 35 | 36 | /** 37 | * Encode IPv4 address as IPv6 address. 38 | * @param buffer byte-buffer where to put encoded data. 39 | * @param address address to encode. 40 | */ 41 | epicsShareFunc void encodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, const osiSockAddr* address); 42 | 43 | /** 44 | * Decode IPv6 address (as IPv4 address). 45 | * @param buffer byte-buffer where to get encoded data. 46 | * @param address address where to decode. 47 | * @return success status (true on success). 48 | */ 49 | epicsShareFunc bool decodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, osiSockAddr* address); 50 | 51 | /** 52 | * Check if an IPv4 address is a multicast address. 53 | * @param address IPv4 address to check. 54 | * @return true if the adress is a multicast address. 55 | */ 56 | epicsShareFunc bool isMulticastAddress(const osiSockAddr* address); 57 | 58 | /** 59 | * Parse space delimited addresss[:port] string and populate array of InetSocketAddress. 60 | * @param ret results stored hre 61 | * @param list space delimited addresss[:port] string. 62 | * @param defaultPort port take if not specified. 63 | * @param appendList list to be appended. 64 | * @return array of InetSocketAddress. 65 | */ 66 | epicsShareFunc void getSocketAddressList(InetAddrVector& ret, const std::string & list, int defaultPort, 67 | const InetAddrVector* appendList = NULL); 68 | 69 | epicsShareFunc std::string inetAddressToString(const osiSockAddr &addr, 70 | bool displayPort = true, bool displayHex = false); 71 | 72 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 73 | 74 | // comparators for osiSockAddr 75 | 76 | struct comp_osiSock_lt { 77 | bool operator()(const osiSockAddr& a, const osiSockAddr& b) const { 78 | if(a.sa.sa_family 6 | #if !defined(_WIN32) 7 | #include 8 | #define USE_SIGNAL 9 | #endif 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | 23 | #include "pvutils.h" 24 | 25 | double timeout = 5.0; 26 | bool debugFlag = false; 27 | 28 | pvd::PVStructure::Formatter::format_t outmode = pvd::PVStructure::Formatter::NT; 29 | int verbosity; 30 | 31 | std::string request(""); 32 | std::string defaultProvider("pva"); 33 | 34 | epicsMutex Tracker::doneLock; 35 | epicsEvent Tracker::doneEvt; 36 | Tracker::inprog_t Tracker::inprog; 37 | bool Tracker::abort = false; 38 | 39 | #ifdef USE_SIGNAL 40 | static 41 | void alldone(int num) 42 | { 43 | (void)num; 44 | Tracker::abort = true; 45 | Tracker::doneEvt.signal(); 46 | } 47 | #endif 48 | 49 | void Tracker::prepare() 50 | { 51 | #ifdef USE_SIGNAL 52 | signal(SIGINT, alldone); 53 | signal(SIGTERM, alldone); 54 | signal(SIGQUIT, alldone); 55 | #endif 56 | } 57 | 58 | static 59 | void early(const char *inp, unsigned pos) 60 | { 61 | fprintf(stderr, "Unexpected end of input: %s\n", inp); 62 | throw std::runtime_error("Unexpected end of input"); 63 | } 64 | 65 | // rudimentory parser for json array 66 | // needed as long as Base < 3.15 is supported. 67 | // for consistency, used with all version 68 | void jarray(pvd::shared_vector& out, const char *inp) 69 | { 70 | assert(inp[0]=='['); 71 | const char * const orig = inp; 72 | inp++; 73 | 74 | while(true) { 75 | // starting a new token 76 | 77 | for(; *inp==' '; inp++) {} // skip leading whitespace 78 | 79 | if(*inp=='\0') early(inp, inp-orig); 80 | 81 | if(isalnum(*inp) || *inp=='+' || *inp=='-') { 82 | // number 83 | 84 | const char *start = inp; 85 | 86 | while(isalnum(*inp) || *inp=='.' || *inp=='+' || *inp=='-') 87 | inp++; 88 | 89 | if(*inp=='\0') early(inp, inp-orig); 90 | 91 | // inp points to first char after token 92 | 93 | out.push_back(std::string(start, inp-start)); 94 | 95 | } else if(*inp=='"') { 96 | // quoted string 97 | 98 | const char *start = ++inp; // skip quote 99 | 100 | while(*inp!='\0' && *inp!='"') 101 | inp++; 102 | 103 | if(*inp=='\0') early(inp, inp-orig); 104 | 105 | // inp points to trailing " 106 | 107 | out.push_back(std::string(start, inp-start)); 108 | 109 | inp++; // skip trailing " 110 | 111 | } else if(*inp==']') { 112 | // no-op 113 | } else { 114 | fprintf(stderr, "Unknown token '%c' in \"%s\"", *inp, inp); 115 | throw std::runtime_error("Unknown token"); 116 | } 117 | 118 | for(; *inp==' '; inp++) {} // skip trailing whitespace 119 | 120 | if(*inp==',') inp++; 121 | else if(*inp==']') break; 122 | else { 123 | fprintf(stderr, "Unknown token '%c' in \"%s\"", *inp, inp); 124 | throw std::runtime_error("Unknown token"); 125 | } 126 | } 127 | 128 | } 129 | -------------------------------------------------------------------------------- /src/ca/caProviderPvt.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | /** 8 | * @author msekoranja, mrk 9 | * @date 2018.07 10 | */ 11 | 12 | #ifndef CAPROVIDERPVT_H 13 | #define CAPROVIDERPVT_H 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | 22 | #include 23 | #include "caContext.h" 24 | #include "notifierConveyor.h" 25 | 26 | 27 | namespace epics { 28 | namespace pvAccess { 29 | namespace ca { 30 | 31 | #define EXCEPTION_GUARD(code) try { code; } \ 32 | catch (std::exception &e) { \ 33 | LOG(logLevelError, "Unhandled exception from client code at %s:%d: %s", \ 34 | __FILE__, __LINE__, e.what()); \ 35 | } \ 36 | catch (...) { \ 37 | LOG(logLevelError, "Unhandled exception from client code at %s:%d.", \ 38 | __FILE__, __LINE__); \ 39 | } 40 | 41 | class CAChannel; 42 | typedef std::tr1::shared_ptr CAChannelPtr; 43 | typedef std::tr1::weak_ptr CAChannelWPtr; 44 | 45 | class CAChannelProvider; 46 | typedef std::tr1::shared_ptr CAChannelProviderPtr; 47 | typedef std::tr1::weak_ptr CAChannelProviderWPtr; 48 | 49 | class CAChannelProvider : 50 | public ChannelProvider, 51 | public std::tr1::enable_shared_from_this 52 | { 53 | public: 54 | POINTER_DEFINITIONS(CAChannelProvider); 55 | CAChannelProvider(const std::tr1::shared_ptr&); 56 | virtual ~CAChannelProvider(); 57 | 58 | /* --------------- epics::pvAccess::ChannelProvider --------------- */ 59 | 60 | virtual std::string getProviderName(); 61 | 62 | virtual ChannelFind::shared_pointer channelFind( 63 | std::string const & channelName, 64 | ChannelFindRequester::shared_pointer const & channelFindRequester); 65 | 66 | virtual ChannelFind::shared_pointer channelList( 67 | ChannelListRequester::shared_pointer const & channelListRequester); 68 | 69 | virtual Channel::shared_pointer createChannel( 70 | std::string const & channelName, 71 | ChannelRequester::shared_pointer const & channelRequester, 72 | short priority); 73 | 74 | virtual Channel::shared_pointer createChannel( 75 | std::string const & channelName, 76 | ChannelRequester::shared_pointer const & channelRequester, 77 | short priority, 78 | std::string const & address); 79 | 80 | virtual void configure(epics::pvData::PVStructure::shared_pointer configuration); 81 | virtual void flush(); 82 | virtual void poll(); 83 | 84 | void addChannel(CAChannel &channel); 85 | void delChannel(CAChannel &channel); 86 | 87 | CAContextPtr caContext() { 88 | return ca_context; 89 | } 90 | void notifyConnection(NotificationPtr const ¬ificationPtr) { 91 | connectNotifier.notifyClient(notificationPtr); 92 | } 93 | void notifyResult(NotificationPtr const ¬ificationPtr) { 94 | resultNotifier.notifyClient(notificationPtr); 95 | } 96 | private: 97 | CAContextPtr ca_context; 98 | epicsMutex channelListMutex; 99 | tsDLList caChannelList; 100 | 101 | NotifierConveyor connectNotifier; 102 | NotifierConveyor resultNotifier; 103 | }; 104 | 105 | }}} 106 | 107 | #endif /* CAPROVIDERPVT_H */ 108 | -------------------------------------------------------------------------------- /src/remote/pv/beaconHandler.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef BEACONHANDLER_H 8 | #define BEACONHANDLER_H 9 | 10 | #ifdef epicsExportSharedSymbols 11 | # define beaconHandlerEpicsExportSharedSymbols 12 | # undef epicsExportSharedSymbols 13 | #endif 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #ifdef beaconHandlerEpicsExportSharedSymbols 21 | # define epicsExportSharedSymbols 22 | # undef beaconHandlerEpicsExportSharedSymbols 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | namespace 30 | { 31 | class InternalClientContextImpl; 32 | } 33 | 34 | namespace epics { 35 | namespace pvAccess { 36 | namespace detail { 37 | class BeaconCleanupHandler; 38 | } 39 | 40 | /** 41 | * BeaconHandler 42 | */ 43 | class BeaconHandler 44 | { 45 | public: 46 | POINTER_DEFINITIONS(BeaconHandler); 47 | 48 | /** 49 | * Constructor. 50 | */ 51 | BeaconHandler(Context::shared_pointer const & context, 52 | const osiSockAddr* responseFrom); 53 | 54 | virtual ~BeaconHandler(); 55 | 56 | /** 57 | * Update beacon period and do analitical checks (server restared, routing problems, etc.) 58 | * @param from who is notifying. 59 | * @param remoteTransportRevision encoded (major, minor) revision. 60 | * @param guid server GUID. 61 | * @param sequentalID sequential ID. 62 | * @param changeCount change count. 63 | * @param data server status data, can be NULL. 64 | */ 65 | void beaconNotify(osiSockAddr* from, 66 | epics::pvData::int8 remoteTransportRevision, 67 | epics::pvData::TimeStamp* timestamp, 68 | ServerGUID const &guid, 69 | epics::pvData::int16 sequentalID, 70 | epics::pvData::int16 changeCount, 71 | const epics::pvData::PVFieldPtr& data); 72 | private: 73 | /** 74 | * Context instance. 75 | */ 76 | Context::weak_pointer _context; 77 | /** 78 | * Remote address. 79 | */ 80 | /** 81 | * Mutex 82 | */ 83 | epics::pvData::Mutex _mutex; 84 | /** 85 | * Server GUID. 86 | */ 87 | ServerGUID _serverGUID; 88 | /** 89 | * Server startup timestamp. 90 | */ 91 | epics::pvData::int16 _serverChangeCount; 92 | /** 93 | * First beacon flag. 94 | */ 95 | bool _first; 96 | /** 97 | * Callback for cleaning up the beacon 98 | */ 99 | std::tr1::shared_ptr _callback; 100 | 101 | /** 102 | * Update beacon. 103 | * @param remoteTransportRevision encoded (major, minor) revision. 104 | * @param timestamp time when beacon was received. 105 | * @param guid server GUID. 106 | * @param sequentalID sequential ID. 107 | * @param changeCount change count. 108 | * @return network change (server restarted) detected. 109 | */ 110 | bool updateBeacon(epics::pvData::int8 remoteTransportRevision, 111 | epics::pvData::TimeStamp* timestamp, 112 | ServerGUID const &guid, 113 | epics::pvData::int16 sequentalID, 114 | epics::pvData::int16 changeCount); 115 | 116 | friend class ::InternalClientContextImpl; 117 | }; 118 | 119 | } 120 | } 121 | 122 | #endif /* INTROSPECTIONREGISTRY_H */ 123 | -------------------------------------------------------------------------------- /src/remote/serializationHelper.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define epicsExportSharedSymbols 16 | #include 17 | #include 18 | 19 | using namespace epics::pvData; 20 | 21 | namespace epics { 22 | namespace pvAccess { 23 | 24 | PVDataCreatePtr SerializationHelper::_pvDataCreate(getPVDataCreate()); 25 | 26 | PVStructure::shared_pointer SerializationHelper::deserializePVRequest(ByteBuffer* buffer, DeserializableControl* control) 27 | { 28 | // for now ordinary structure, later can be changed 29 | return deserializeStructureFull(buffer, control); 30 | } 31 | 32 | PVStructure::shared_pointer SerializationHelper::deserializeStructureAndCreatePVStructure(ByteBuffer* buffer, DeserializableControl* control, PVStructure::shared_pointer const & existingStructure) 33 | { 34 | FieldConstPtr field = control->cachedDeserialize(buffer); 35 | if (!field) 36 | return PVStructure::shared_pointer(); 37 | 38 | if (existingStructure && *field == *existingStructure->getField()) 39 | return existingStructure; 40 | else if(field->getType()==structure) 41 | return _pvDataCreate->createPVStructure(std::tr1::static_pointer_cast(field)); 42 | else 43 | throw std::runtime_error("deserializeStructureAndCreatePVStructure expects a Structure"); 44 | } 45 | 46 | PVStructure::shared_pointer SerializationHelper::deserializeStructureFull(ByteBuffer* buffer, DeserializableControl* control) 47 | { 48 | PVField::shared_pointer ret(deserializeFull(buffer, control)); 49 | if(!ret) return PVStructure::shared_pointer(); 50 | else if(ret->getField()->getType()!=structure) 51 | throw std::runtime_error("deserializeStructureFull expects a Structure"); 52 | return std::tr1::static_pointer_cast(ret); 53 | } 54 | 55 | PVField::shared_pointer SerializationHelper::deserializeFull(ByteBuffer* buffer, DeserializableControl* control) 56 | { 57 | PVField::shared_pointer pvField; 58 | FieldConstPtr field = control->cachedDeserialize(buffer); 59 | if (field) 60 | { 61 | pvField = _pvDataCreate->createPVField(field); 62 | pvField->deserialize(buffer, control); 63 | } 64 | return pvField; 65 | } 66 | 67 | void SerializationHelper::serializeNullField(ByteBuffer* buffer, SerializableControl* control) 68 | { 69 | control->ensureBuffer(1); 70 | buffer->putByte(IntrospectionRegistry::NULL_TYPE_CODE); 71 | } 72 | 73 | void SerializationHelper::serializePVRequest(ByteBuffer* buffer, SerializableControl* control, PVStructure::shared_pointer const & pvRequest) 74 | { 75 | // for now ordinary structure, later can be changed 76 | serializeStructureFull(buffer, control, pvRequest); 77 | } 78 | 79 | void SerializationHelper::serializeStructureFull(ByteBuffer* buffer, SerializableControl* control, PVStructure::shared_pointer const & pvStructure) 80 | { 81 | serializeFull(buffer, control, pvStructure); 82 | } 83 | 84 | void SerializationHelper::serializeFull(ByteBuffer* buffer, SerializableControl* control, PVField::const_shared_pointer const & pvField) 85 | { 86 | if (!pvField) 87 | { 88 | serializeNullField(buffer, control); 89 | } 90 | else 91 | { 92 | control->cachedSerialize(pvField->getField(), buffer); 93 | pvField->serialize(buffer, control); 94 | } 95 | } 96 | 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/remote/blockingUDPConnector.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #include 10 | 11 | #define epicsExportSharedSymbols 12 | #include 13 | #include 14 | #include 15 | 16 | using namespace std; 17 | using namespace epics::pvData; 18 | 19 | namespace { 20 | struct closer { 21 | epics::pvAccess::BlockingUDPTransport::shared_pointer P; 22 | closer(const epics::pvAccess::BlockingUDPTransport::shared_pointer& P) :P(P) {} 23 | void operator()(epics::pvAccess::BlockingUDPTransport*) { 24 | try{ 25 | P->close(); 26 | }catch(...){ 27 | P.reset(); 28 | throw; 29 | } 30 | P.reset(); 31 | } 32 | }; 33 | } 34 | 35 | namespace epics { 36 | namespace pvAccess { 37 | 38 | BlockingUDPTransport::shared_pointer BlockingUDPConnector::connect(ResponseHandler::shared_pointer const & responseHandler, 39 | osiSockAddr& bindAddress, 40 | int8 transportRevision) 41 | { 42 | SOCKET socket = epicsSocketCreate(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 43 | if(socket==INVALID_SOCKET) { 44 | char errStr[64]; 45 | epicsSocketConvertErrnoToString(errStr, sizeof(errStr)); 46 | LOG(logLevelError, "Error creating socket: %s.", errStr); 47 | return BlockingUDPTransport::shared_pointer(); 48 | } 49 | 50 | int optval = 1; 51 | int retval = ::setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&optval, sizeof(optval)); 52 | if(retval<0) 53 | { 54 | char errStr[64]; 55 | epicsSocketConvertErrnoToString(errStr, sizeof(errStr)); 56 | LOG(logLevelError, "Error setting SO_BROADCAST: %s.", errStr); 57 | epicsSocketDestroy (socket); 58 | return BlockingUDPTransport::shared_pointer(); 59 | } 60 | 61 | /* 62 | IPv4 multicast addresses are defined by the leading address bits of 1110, 63 | originating from the classful network design of the early Internet when this 64 | group of addresses was designated as Class D. The Classless Inter-Domain Routing (CIDR) 65 | prefix of this group is 224.0.0.0/4. 66 | The group includes the addresses from 224.0.0.0 to 239.255.255.255. 67 | Address assignments from within this range are specified in RFC 5771, 68 | an Internet Engineering Task Force (IETF) Best Current Practice document (BCP 51).*/ 69 | 70 | 71 | // set SO_REUSEADDR or SO_REUSEPORT, OS dependant 72 | epicsSocketEnableAddressUseForDatagramFanout(socket); 73 | 74 | retval = ::bind(socket, (sockaddr*)&(bindAddress.sa), sizeof(sockaddr)); 75 | if(retval<0) { 76 | char ip[24]; 77 | sockAddrToDottedIP((sockaddr*)&(bindAddress.sa), ip, sizeof(ip)); 78 | char errStr[64]; 79 | epicsSocketConvertErrnoToString(errStr, sizeof(errStr)); 80 | LOG(logLevelError, "Error binding socket %s: %s.", ip, errStr); 81 | epicsSocketDestroy (socket); 82 | return BlockingUDPTransport::shared_pointer(); 83 | } 84 | 85 | // sockets are blocking by default 86 | BlockingUDPTransport::shared_pointer transport(new BlockingUDPTransport(_serverFlag, responseHandler, 87 | socket, bindAddress, transportRevision)); 88 | transport->internal_this = transport; 89 | 90 | // the worker thread holds a strong ref, which is released by transport->close() 91 | BlockingUDPTransport::shared_pointer ret(transport.get(), closer(transport)); 92 | 93 | return ret; 94 | } 95 | 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /notes.md.txt: -------------------------------------------------------------------------------- 1 | changes 2 | 3 | must keep ChannelProvider refs 4 | Channel doesn't have strong ref to provider. 5 | All channels closed when provider destory'd 6 | 7 | default ChannelProviderFactory uses weak_ptr for sharedInstance() 8 | copy+paste from eget.cpp very inefficient... 9 | 10 | TODO 11 | 12 | 13 | ca provider changes 14 | channel has weak_ref to provider 15 | create operations on disconnected channel 16 | monitor queue 17 | 18 | untangle responseHandlers.cpp 19 | ref. loops galore 20 | destroy which queued to send??? 21 | 22 | maps which grow w/o bound 23 | 24 | named lock pattern 25 | m_beaconHandlers 26 | 27 | 28 | 29 | 30 | 31 | locking 32 | 33 | 34 | 35 | no internal locks held when calling *Requester methods, including dtor 36 | 37 | any external locks may be held when channel/operation methods called 38 | 39 | 40 | provider->createChannel() 41 | 42 | * returns unique() reference. 43 | * Provider must maintain a cache of existing Channels are prefer this to creating new Channels 44 | 45 | calls to channel->createChannel* 46 | 47 | * returns unique() reference 48 | * Channel retains internal references to Operation until destroy() is called (or all external references released) 49 | * request on dis-connected channel queues until connected 50 | 51 | Add channelStateChanged() to all operation Requesters 52 | 53 | * called only with DISCONNECTED (channel connected -> disconnected) or DESTROYED (channel->destroy() called). 54 | * Any in-progress action is implicitly cancel()'d 55 | 56 | 57 | 58 | After some considerable thought, I like to re-define some of the semantics of ChannelProvider, Channel, and operations (eg. ChannelGet). 59 | 60 | 1. User/caller code takes ownership of returned Channel or operation. 61 | 62 | For a Channel to remain open, or an operation to remain active, the caller must hold a reference. This will prevent accumulation of channels and operations which user code isn't accounting for. 63 | 64 | The suggested way to accomplish this is for a ChannelProvider to return a shared_ptr<> with a custom cleanup function which calls destroy(). 65 | 66 | 1.1 returned shared_ptr must not include an internal references. That is, the first time a Channel is returned it is unique(). Subsequent calls to createChannel() with the same arguments may return unique()==false provided that this count includes only external references. 67 | 68 | 1.2 returned operation shared_ptr<> must be unique(). 69 | 70 | 2. User/caller code need not cache Channel instances. 71 | 72 | Every non-trivial client worries about minimizing the number of Channels. 73 | 74 | 2.1 ChannelProvider is required to maintain a cache of in-use Channels and prefer to return a cached entry before creating a new Channel. 75 | 76 | 3 Notify operations about Channel state changes 77 | 78 | channelStateChanged() by itself isn't so useful. Clients always proxy this through to some action of each in-progress operation. So have the Channel do this. 79 | 80 | 3.1 Add a new method channelStateChanged() to all operation Requester classes. Default implementation is a no-op. Only DISCONNECTED and DESTROYED shall be used (CONNECT is delivered as a separate callback *Connect() ). 81 | 82 | 3.2 When DISCONNECTED is delivered the operation remains "valid" and its *Connect() will be called (again) if/when the Channel again becomes connected 83 | 84 | 3.3 When DESTROYED is delivered, the underlying Channel has been forcibly closed. 85 | 86 | 3.3 Delivery of DISCONNECTED or DESTROYED implicitly cancels any in-progress action. 87 | 88 | 4 Operation life-time 89 | 90 | 4.1 Channel must support starting operations while in disconnected state 91 | 92 | 4.2 Operations persist when a Channel becomes DISCONNECTED. On re-connect, the operation *Connect() method is called again, potentially with new Structure definition. 93 | -------------------------------------------------------------------------------- /src/client/clientInfo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright information and license terms for this software can be 3 | * found in the file LICENSE that is included with the distribution 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define epicsExportSharedSymbols 17 | #include "pv/logger.h" 18 | #include "clientpvt.h" 19 | #include "pv/pvAccess.h" 20 | 21 | namespace { 22 | using pvac::detail::CallbackGuard; 23 | using pvac::detail::CallbackUse; 24 | 25 | struct Infoer : public pvac::detail::CallbackStorage, 26 | public pva::GetFieldRequester, 27 | public pvac::Operation::Impl, 28 | public pvac::detail::wrapped_shared_from_this 29 | { 30 | pvac::ClientChannel::InfoCallback *cb; 31 | const pva::Channel::shared_pointer channel; 32 | 33 | static size_t num_instances; 34 | 35 | explicit Infoer(pvac::ClientChannel::InfoCallback *cb, const pva::Channel::shared_pointer& channel) 36 | :cb(cb), channel(channel) 37 | {REFTRACE_INCREMENT(num_instances);} 38 | virtual ~Infoer() { 39 | CallbackGuard G(*this); 40 | cb = 0; 41 | G.wait(); // paranoia 42 | REFTRACE_DECREMENT(num_instances); 43 | } 44 | 45 | 46 | virtual std::string getRequesterName() OVERRIDE FINAL 47 | { 48 | Guard G(mutex); 49 | return channel->getChannelName(); 50 | } 51 | 52 | virtual void getDone( 53 | const pvd::Status& status, 54 | pvd::FieldConstPtr const & field) OVERRIDE FINAL 55 | { 56 | CallbackGuard G(*this); 57 | pvac::ClientChannel::InfoCallback *C(cb); 58 | cb = 0; 59 | if(C) { 60 | pvac::InfoEvent evt; 61 | evt.event = status.isSuccess() ? pvac::InfoEvent::Success : pvac::InfoEvent::Fail; 62 | evt.message = status.getMessage(); 63 | evt.type = field; 64 | CallbackUse U(G); 65 | C->infoDone(evt); 66 | } 67 | pvac::InfoEvent evt; 68 | } 69 | 70 | virtual std::string name() const OVERRIDE FINAL { return channel->getChannelName(); } 71 | 72 | virtual void cancel() OVERRIDE FINAL { 73 | CallbackGuard G(*this); 74 | // we can't actually cancel a getField 75 | pvac::ClientChannel::InfoCallback *C(cb); 76 | cb = 0; 77 | if(C) { 78 | pvac::InfoEvent evt; 79 | evt.event = pvac::InfoEvent::Cancel; 80 | CallbackUse U(G); 81 | C->infoDone(evt); 82 | } 83 | G.wait(); 84 | } 85 | 86 | virtual void show(std::ostream& strm) const OVERRIDE FINAL { 87 | strm << "Operation(Info" 88 | "\"" << name() <<"\"" 89 | ")"; 90 | } 91 | }; 92 | 93 | size_t Infoer::num_instances; 94 | 95 | } // namespace 96 | 97 | namespace pvac { 98 | 99 | Operation ClientChannel::info(InfoCallback *cb, const std::string& subfld) 100 | { 101 | if(!impl) throw std::logic_error("Dead Channel"); 102 | 103 | std::tr1::shared_ptr ret(Infoer::build(cb, getChannel())); 104 | 105 | { 106 | Guard G(ret->mutex); 107 | getChannel()->getField(ret, subfld); 108 | // getField is an oddity as it doesn't have an associated Operation class, 109 | // and is thus largely out of our control. (eg. can't cancel) 110 | } 111 | 112 | return Operation(ret); 113 | } 114 | 115 | namespace detail { 116 | 117 | void registerRefTrackInfo() 118 | { 119 | epics::registerRefCounter("pvac::Infoer", &Infoer::num_instances); 120 | } 121 | 122 | } 123 | 124 | } // namespace pvac 125 | -------------------------------------------------------------------------------- /.appveyor.yml: -------------------------------------------------------------------------------- 1 | # .appveyor.yml for use with EPICS Base ci-scripts 2 | # (see: https://github.com/epics-base/ci-scripts) 3 | 4 | # This is YAML - indentation levels are crucial 5 | 6 | #---------------------------------# 7 | # build cache # 8 | #---------------------------------# 9 | # The AppVeyor cache allowance is way too small (1GB per account across all 10 | # projects, branches and jobs) to be used for the dependency builds. 11 | 12 | cache: 13 | - C:\Users\appveyor\.tools 14 | 15 | #---------------------------------# 16 | # repository cloning # 17 | #---------------------------------# 18 | 19 | init: 20 | # Set autocrlf to make batch files work 21 | - git config --global core.autocrlf true 22 | 23 | clone_depth: 5 24 | 25 | #---------------------------------# 26 | # build matrix configuration # 27 | #---------------------------------# 28 | 29 | # Build Configurations: dll/static, regular/debug 30 | configuration: 31 | - dynamic 32 | - static 33 | - dynamic-debug 34 | - static-debug 35 | 36 | # Environment variables: compiler toolchain, base version, setup file, ... 37 | environment: 38 | # common / default variables for all jobs 39 | SETUP_PATH: .ci-local 40 | EPICS_TEST_IMPRECISE_TIMING: YES 41 | BASE: 7.0 42 | 43 | matrix: 44 | - CMP: vs2019 45 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 46 | - CMP: vs2019 47 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 48 | BASE: 3.15 49 | - CMP: vs2017 50 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 51 | - CMP: vs2015 52 | - CMP: gcc 53 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 54 | # TODO: static linking w/ readline isn't working. Bypass auto-detect 55 | COMMANDLINE_LIBRARY: EPICS 56 | 57 | # Platform: processor architecture 58 | platform: x64 59 | 60 | # Matrix configuration: exclude sets of jobs 61 | matrix: 62 | exclude: 63 | # MinGW debug builds use the same libraries, unlike VS 64 | - configuration: dynamic-debug 65 | CMP: gcc 66 | - configuration: static-debug 67 | CMP: gcc 68 | 69 | #---------------------------------# 70 | # building & testing # 71 | #---------------------------------# 72 | 73 | install: 74 | - cmd: git submodule update --init --recursive 75 | - cmd: pip install git+https://github.com/mdavidsaver/ci-core-dumper#egg=ci-core-dumper 76 | - cmd: python .ci/cue.py prepare 77 | 78 | build_script: 79 | - cmd: python .ci/cue.py build 80 | 81 | test_script: 82 | - cmd: python -m ci_core_dumper install 83 | - cmd: python .ci/cue.py -T 20M test 84 | 85 | on_finish: 86 | - ps: Get-ChildItem *.tap -Recurse -Force | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name } 87 | - cmd: python .ci/cue.py -T 5M test-results 88 | 89 | on_failure: 90 | - cmd: python -m ci_core_dumper report 91 | 92 | #---------------------------------# 93 | # debugging # 94 | #---------------------------------# 95 | 96 | ## To connect by remote desktop to a failing build, uncomment the lines below. 97 | ## You must connect within the usual build timeout limit (60 minutes), 98 | ## so adjust the build matrix above to just build the config of interest. 99 | 100 | #on_failure: 101 | # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) 102 | # - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) 103 | 104 | #---------------------------------# 105 | # notifications # 106 | #---------------------------------# 107 | 108 | notifications: 109 | - provider: Email 110 | to: 111 | - core-talk@aps.anl.gov 112 | on_build_success: false 113 | - provider: GitHubPullRequest 114 | -------------------------------------------------------------------------------- /src/remote/pv/serializationHelper.h: -------------------------------------------------------------------------------- 1 | /* 2 | * serializationHelper.h 3 | * 4 | * Created on: Jul 24, 2012 5 | * Author: msekoranja 6 | */ 7 | 8 | #ifndef SERIALIZATIONHELPER_H_ 9 | #define SERIALIZATIONHELPER_H_ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | namespace epics { 21 | namespace pvAccess { 22 | 23 | class epicsShareClass SerializationHelper { 24 | EPICS_NOT_COPYABLE(SerializationHelper) 25 | public: 26 | 27 | static epics::pvData::PVDataCreatePtr _pvDataCreate; 28 | 29 | /** 30 | * Deserialize PVRequest. 31 | * @param payloadBuffer data buffer. 32 | * @return deserialized PVRequest, can be null. 33 | */ 34 | static epics::pvData::PVStructure::shared_pointer deserializePVRequest(epics::pvData::ByteBuffer* payloadBuffer, epics::pvData::DeserializableControl* control); 35 | 36 | /** 37 | * Deserialize Structure and create PVStructure instance, if necessary. 38 | * @param payloadBuffer data buffer. 39 | * @param control deserialization control. 40 | * @param existingStructure if deserialized Field matches existingStrcuture Field, then 41 | * existingStructure instance is returned. null value is allowed. 42 | * @return PVStructure instance, can be null. 43 | */ 44 | static epics::pvData::PVStructure::shared_pointer deserializeStructureAndCreatePVStructure(epics::pvData::ByteBuffer* payloadBuffer, 45 | epics::pvData::DeserializableControl* control, 46 | epics::pvData::PVStructure::shared_pointer const & existingStructure = epics::pvData::PVStructure::shared_pointer()); 47 | 48 | /** 49 | * Deserialize optional PVStructrue. 50 | * @param payloadBuffer data buffer. 51 | * @return deserialized PVStructure, can be null. 52 | */ 53 | static epics::pvData::PVStructure::shared_pointer deserializeStructureFull(epics::pvData::ByteBuffer* payloadBuffer, epics::pvData::DeserializableControl* control); 54 | 55 | /** 56 | * Deserialize optional PVField. 57 | * @param payloadBuffer data buffer. 58 | * @return deserialized PVField, can be null. 59 | */ 60 | static epics::pvData::PVField::shared_pointer deserializeFull(epics::pvData::ByteBuffer* payloadBuffer, epics::pvData::DeserializableControl* control); 61 | 62 | /** 63 | * Serialize null PVField. 64 | * @param buffer 65 | * @param control 66 | */ 67 | static void serializeNullField(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control); 68 | 69 | /** 70 | * Serialize PVRequest. 71 | * @param buffer data buffer. 72 | */ 73 | static void serializePVRequest(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control, epics::pvData::PVStructure::shared_pointer const & pvRequest); 74 | 75 | /** 76 | * Serialize optional PVStructrue. 77 | * @param buffer data buffer. 78 | */ 79 | static void serializeStructureFull(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control, epics::pvData::PVStructure::shared_pointer const & pvStructure); 80 | 81 | /** 82 | * Serialize optional PVField. 83 | * @param buffer data buffer. 84 | */ 85 | static void serializeFull(epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control, const epics::pvData::PVField::const_shared_pointer &pvField); 86 | 87 | }; 88 | 89 | } 90 | } 91 | 92 | #endif /* SERIALIZATIONHELPER_H_ */ 93 | -------------------------------------------------------------------------------- /src/utils/pv/introspectionRegistry.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef INTROSPECTIONREGISTRY_H 8 | #define INTROSPECTIONREGISTRY_H 9 | 10 | #include 11 | #include 12 | 13 | #ifdef epicsExportSharedSymbols 14 | # define introspectionRegistryEpicsExportSharedSymbols 15 | # undef epicsExportSharedSymbols 16 | #endif 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef introspectionRegistryEpicsExportSharedSymbols 28 | # define epicsExportSharedSymbols 29 | # undef introspectionRegistryEpicsExportSharedSymbols 30 | #endif 31 | 32 | // TODO check for memory leaks 33 | 34 | namespace epics { 35 | namespace pvAccess { 36 | 37 | typedef std::map registryMap_t; 38 | 39 | 40 | /** 41 | * PVData Structure registry. 42 | * Registry is used to cache introspection interfaces to minimize network traffic. 43 | * @author gjansa 44 | */ 45 | class IntrospectionRegistry { 46 | EPICS_NOT_COPYABLE(IntrospectionRegistry) 47 | public: 48 | IntrospectionRegistry(); 49 | virtual ~IntrospectionRegistry(); 50 | 51 | /** 52 | * Resets registry, i.e. must be done when transport is changed (server restarted). 53 | */ 54 | void reset(); 55 | 56 | private: 57 | /** 58 | * Registers introspection interface and get it's ID. Always OUTGOING. 59 | * If it is already registered only preassigned ID is returned. 60 | * 61 | * TODO !!!!!!this can get very slow in large maps. We need to change this !!!!!! 62 | * 63 | * @param field introspection interface to register 64 | * 65 | * @return id of given introspection interface 66 | */ 67 | epics::pvData::int16 registerIntrospectionInterface(epics::pvData::FieldConstPtr const & field, bool& existing); 68 | public: 69 | /** 70 | * Serializes introspection interface 71 | * 72 | * @param field 73 | * @param buffer 74 | * @param control 75 | */ 76 | void serialize(epics::pvData::FieldConstPtr const & field, epics::pvData::ByteBuffer* buffer, epics::pvData::SerializableControl* control); 77 | 78 | /** 79 | * Deserializes introspection interface 80 | * 81 | * TODO 82 | * 83 | * @param buffer 84 | * @param control 85 | * 86 | * @return Field deserialized from the buffer. 87 | */ 88 | epics::pvData::FieldConstPtr deserialize(epics::pvData::ByteBuffer* buffer, epics::pvData::DeserializableControl* control); 89 | 90 | /** 91 | * Null type. 92 | */ 93 | const static epics::pvData::int8 NULL_TYPE_CODE; 94 | 95 | /** 96 | * Serialization contains only an ID (that was assigned by one of the previous FULL_WITH_ID descriptions). 97 | */ 98 | const static epics::pvData::int8 ONLY_ID_TYPE_CODE; 99 | 100 | /** 101 | * Serialization contains an ID (that can be used later, if cached) and full interface description. 102 | */ 103 | const static epics::pvData::int8 FULL_WITH_ID_TYPE_CODE; 104 | 105 | private: 106 | registryMap_t _registry; 107 | epics::pvData::int16 _pointer; 108 | 109 | /** 110 | * Field factory. 111 | */ 112 | static epics::pvData::FieldCreatePtr _fieldCreate; 113 | 114 | bool registryContainsValue(epics::pvData::FieldConstPtr const & field, epics::pvData::int16& key); 115 | }; 116 | 117 | } 118 | } 119 | 120 | #endif /* INTROSPECTIONREGISTRY_H */ 121 | -------------------------------------------------------------------------------- /examples/mailbox.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #include 8 | 9 | #if !defined(_WIN32) 10 | #include 11 | #define USE_SIGNAL 12 | #endif 13 | 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | namespace pvd = epics::pvData; 22 | namespace pva = epics::pvAccess; 23 | 24 | namespace { 25 | 26 | epicsEvent done; 27 | 28 | #ifdef USE_SIGNAL 29 | void alldone(int num) 30 | { 31 | (void)num; 32 | done.signal(); 33 | } 34 | #endif 35 | 36 | static pvd::StructureConstPtr string_type(pvd::getFieldCreate()->createFieldBuilder() 37 | ->add("value", pvd::pvString) 38 | ->createStructure()); 39 | 40 | static pvd::StructureConstPtr int_type(pvd::getFieldCreate()->createFieldBuilder() 41 | ->add("value", pvd::pvInt) 42 | ->createStructure()); 43 | 44 | static pvd::StructureConstPtr real_type(pvd::getFieldCreate()->createFieldBuilder() 45 | ->add("value", pvd::pvDouble) 46 | ->createStructure()); 47 | 48 | }//namespace 49 | 50 | int main(int argc, char *argv[]) 51 | { 52 | try { 53 | if(argc<=1) { 54 | fprintf(stderr, "Usage: %s ...\n type: string, int, real", argv[0]); 55 | return 1; 56 | } 57 | 58 | // container for PVs 59 | pvas::StaticProvider provider("mailbox"); // provider name "mailbox" is arbitrary 60 | 61 | for(int i=1; iopen(string_type); 80 | } else if(type=="int") { 81 | pv->open(int_type); 82 | } else if(type=="real") { 83 | pv->open(real_type); 84 | } else { 85 | fprintf(stderr, "Unknown type '%s'\n", type.c_str()); 86 | return 1; 87 | } 88 | 89 | // add to container 90 | provider.add(argv[1], pv); 91 | } 92 | 93 | // create and run network server 94 | pva::ServerContext::shared_pointer server(pva::ServerContext::create( 95 | pva::ServerContext::Config() 96 | // use default config from environment 97 | .provider(provider.provider()) 98 | )); 99 | 100 | #ifdef USE_SIGNAL 101 | signal(SIGINT, alldone); 102 | signal(SIGTERM, alldone); 103 | signal(SIGQUIT, alldone); 104 | #endif 105 | server->printInfo(); 106 | 107 | printf("Running with mailbox '%s'\n", argv[1]); 108 | 109 | done.wait(); 110 | 111 | } catch(std::exception& e){ 112 | std::cerr<<"Error: "< 8 | 9 | #define epicsExportSharedSymbols 10 | #include 11 | 12 | using namespace epics::pvData; 13 | 14 | namespace epics { 15 | namespace pvAccess { 16 | 17 | size_t ServerChannel::num_instances; 18 | 19 | ServerChannel::ServerChannel(Channel::shared_pointer const & channel, 20 | const ChannelRequester::shared_pointer &requester, 21 | pvAccessID cid, pvAccessID sid): 22 | _channel(channel), 23 | _requester(requester), 24 | _cid(cid), 25 | _sid(sid), 26 | _destroyed(false) 27 | { 28 | REFTRACE_INCREMENT(num_instances); 29 | if (!channel.get()) 30 | { 31 | THROW_BASE_EXCEPTION("non-null channel required"); 32 | } 33 | } 34 | 35 | void ServerChannel::registerRequest(const pvAccessID id, const std::tr1::shared_ptr & request) 36 | { 37 | Lock guard(_mutex); 38 | if(_destroyed) throw std::logic_error("Can't registerRequest() for destory'd server channel"); 39 | _requests[id] = request; 40 | } 41 | 42 | void ServerChannel::unregisterRequest(const pvAccessID id) 43 | { 44 | Lock guard(_mutex); 45 | _requests_t::iterator iter = _requests.find(id); 46 | if(iter != _requests.end()) 47 | { 48 | _requests.erase(iter); 49 | } 50 | } 51 | 52 | std::tr1::shared_ptr ServerChannel::getRequest(const pvAccessID id) 53 | { 54 | Lock guard(_mutex); 55 | _requests_t::iterator iter = _requests.find(id); 56 | if(iter != _requests.end()) 57 | { 58 | return iter->second; 59 | } 60 | return BaseChannelRequester::shared_pointer(); 61 | } 62 | 63 | void ServerChannel::destroy() 64 | { 65 | _requests_t reqs; 66 | { 67 | Lock guard(_mutex); 68 | 69 | if (_destroyed) return; 70 | _destroyed = true; 71 | 72 | // destroy all requests 73 | // take ownership of _requests locally to prevent 74 | // removal via unregisterRequest() during iteration 75 | _requests.swap(reqs); 76 | 77 | // ... and the channel 78 | // TODO try catch 79 | _channel->destroy(); 80 | } 81 | // unlock our before destroy. 82 | // our mutex is subordinate to operation mutex 83 | 84 | for(_requests_t::const_iterator it=reqs.begin(), end=reqs.end(); it!=end; ++it) 85 | { 86 | const _requests_t::mapped_type& req = it->second; 87 | // will call unregisterRequest() which is now a no-op 88 | req->destroy(); 89 | // May still be in the send queue 90 | } 91 | } 92 | 93 | ServerChannel::~ServerChannel() 94 | { 95 | destroy(); 96 | REFTRACE_DECREMENT(num_instances); 97 | } 98 | 99 | void ServerChannel::printInfo() const 100 | { 101 | printInfo(stdout); 102 | } 103 | 104 | void ServerChannel::printInfo(FILE *fd) const 105 | { 106 | fprintf(fd,"CLASS : %s\n", typeid(*this).name()); 107 | fprintf(fd,"CHANNEL : %s\n", typeid(*_channel).name()); 108 | } 109 | 110 | void ServerChannel::installGetField(const GetFieldRequester::shared_pointer& gf) 111 | { 112 | GetFieldRequester::shared_pointer prev; 113 | { 114 | epicsGuard G(_mutex); 115 | prev.swap(_active_requester); 116 | _active_requester = gf; 117 | } 118 | if(prev) { 119 | prev->getDone(Status::error("Aborted"), FieldConstPtr()); 120 | } 121 | } 122 | 123 | void ServerChannel::completeGetField(GetFieldRequester *req) 124 | { 125 | GetFieldRequester::shared_pointer prev; 126 | { 127 | epicsGuard G(_mutex); 128 | if(_active_requester.get()==req) 129 | prev.swap(_active_requester); 130 | } 131 | } 132 | 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/server/pv/baseChannelRequester.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef BASECHANNELREQUESTER_H_ 8 | #define BASECHANNELREQUESTER_H_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | namespace epics { 16 | namespace pvAccess { 17 | 18 | class ServerChannel; 19 | class ChannelRequest; 20 | 21 | class BaseChannelRequester : 22 | virtual public epics::pvData::Requester, 23 | public TransportSender, 24 | public NetStats, 25 | public Destroyable 26 | { 27 | public: 28 | POINTER_DEFINITIONS(BaseChannelRequester); 29 | BaseChannelRequester(ServerContextImpl::shared_pointer const & context, std::tr1::shared_ptr const & channel, 30 | const pvAccessID ioid, Transport::shared_pointer const & transport); 31 | virtual ~BaseChannelRequester() {}; 32 | 33 | bool startRequest(epics::pvData::int32 qos); 34 | void stopRequest(); 35 | epics::pvData::int32 getPendingRequest(); 36 | //! The Operation associated with this Requester, except for GetField and Monitor (which are special snowflakes...) 37 | virtual std::tr1::shared_ptr getOperation() =0; 38 | virtual std::string getRequesterName() OVERRIDE FINAL; 39 | virtual void message(std::string const & message, epics::pvData::MessageType messageType) OVERRIDE FINAL; 40 | static void message(Transport::shared_pointer const & transport, const pvAccessID ioid, const std::string message, const epics::pvData::MessageType messageType); 41 | static void sendFailureMessage(const epics::pvData::int8 command, Transport::shared_pointer const & transport, const pvAccessID ioid, const epics::pvData::int8 qos, const epics::pvData::Status status); 42 | 43 | virtual void stats(Stats &s) const OVERRIDE FINAL; 44 | 45 | static const epics::pvData::Status okStatus; 46 | static const epics::pvData::Status badCIDStatus; 47 | static const epics::pvData::Status badIOIDStatus; 48 | static const epics::pvData::Status noReadACLStatus; 49 | static const epics::pvData::Status noWriteACLStatus; 50 | static const epics::pvData::Status noProcessACLStatus; 51 | static const epics::pvData::Status otherRequestPendingStatus; 52 | static const epics::pvData::Status notAChannelRequestStatus; 53 | protected: 54 | const pvAccessID _ioid; 55 | const Transport::shared_pointer _transport; 56 | const std::tr1::shared_ptr _channel; 57 | epics::pvData::Mutex _mutex; 58 | private: 59 | ServerContextImpl::shared_pointer _context; 60 | static const epics::pvData::int32 NULL_REQUEST; 61 | epics::pvData::int32 _pendingRequest; 62 | }; 63 | 64 | class BaseChannelRequesterMessageTransportSender : public TransportSender 65 | { 66 | public: 67 | BaseChannelRequesterMessageTransportSender(const pvAccessID _ioid, const std::string message,const epics::pvData::MessageType messageType); 68 | virtual void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) OVERRIDE FINAL; 69 | private: 70 | const pvAccessID _ioid; 71 | const std::string _message; 72 | const epics::pvData::MessageType _messageType; 73 | }; 74 | 75 | class BaseChannelRequesterFailureMessageTransportSender : public TransportSender 76 | { 77 | public: 78 | BaseChannelRequesterFailureMessageTransportSender(const epics::pvData::int8 command, Transport::shared_pointer const & transport, const pvAccessID ioid, const epics::pvData::int8 qos, const epics::pvData::Status& status); 79 | virtual void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) OVERRIDE FINAL; 80 | 81 | private: 82 | const epics::pvData::int8 _command; 83 | const pvAccessID _ioid; 84 | const epics::pvData::int8 _qos; 85 | const epics::pvData::Status _status; 86 | Transport::shared_pointer _transport; 87 | }; 88 | 89 | } 90 | } 91 | 92 | 93 | #endif /* BASECHANNELREQUESTER_H_ */ 94 | -------------------------------------------------------------------------------- /src/server/pv/beaconEmitter.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef BEACONEMITTER_H 8 | #define BEACONEMITTER_H 9 | 10 | #ifdef epicsExportSharedSymbols 11 | # define beaconEmitterEpicsExportSharedSymbols 12 | # undef epicsExportSharedSymbols 13 | #endif 14 | 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #ifdef beaconEmitterEpicsExportSharedSymbols 22 | # define epicsExportSharedSymbols 23 | # undef beaconEmitterEpicsExportSharedSymbols 24 | #endif 25 | 26 | #include 27 | #include 28 | //#include 29 | 30 | namespace epics { 31 | namespace pvAccess { 32 | 33 | class ServerContextImpl; 34 | 35 | /** 36 | * BeaconEmitter 37 | * 38 | * @author gjansa 39 | */ 40 | class BeaconEmitter: 41 | public TransportSender, 42 | public epics::pvData::TimerCallback, 43 | public std::tr1::enable_shared_from_this 44 | { 45 | public: 46 | typedef std::tr1::shared_ptr shared_pointer; 47 | typedef std::tr1::shared_ptr const_shared_pointer; 48 | 49 | /** 50 | * Constructor. 51 | * @param protocol a protocol (transport) name to report. 52 | * @param transport transport to be used to send beacons. 53 | * @param context PVA context. 54 | */ 55 | // BeaconEmitter(std::sting const & protocol, 56 | // Transport::shared_pointer const & transport, ServerContextImpl::shared_pointer const & context); 57 | BeaconEmitter(std::string const & protocol, 58 | Transport::shared_pointer const & transport, std::tr1::shared_ptr& context); 59 | 60 | virtual ~BeaconEmitter(); 61 | 62 | void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control); 63 | 64 | void timerStopped(); 65 | 66 | /** 67 | * Start emitting. 68 | */ 69 | void start(); 70 | 71 | /** 72 | * Reschedule timer. 73 | */ 74 | void reschedule(); 75 | 76 | /** 77 | * Timer callback. 78 | */ 79 | void callback(); 80 | 81 | void destroy(); 82 | 83 | private: 84 | 85 | /** 86 | * Minimal (initial) PVA beacon period (in seconds). 87 | */ 88 | static const float EPICS_PVA_MIN_BEACON_PERIOD; 89 | 90 | /** 91 | * Minimal PVA beacon count limit. 92 | */ 93 | static const float EPICS_PVA_MIN_BEACON_COUNT_LIMIT; 94 | 95 | /** 96 | * Protocol. 97 | */ 98 | const std::string _protocol; 99 | 100 | /** 101 | * Transport. 102 | */ 103 | Transport::shared_pointer _transport; 104 | 105 | /** 106 | * Beacon sequence ID. 107 | */ 108 | epics::pvData::int8 _beaconSequenceID; 109 | 110 | /** 111 | * Server GUID. 112 | */ 113 | const ServerGUID _guid; 114 | 115 | /** 116 | * Fast (at startup) beacon period (in sec). 117 | */ 118 | const double _fastBeaconPeriod; 119 | 120 | /** 121 | * Slow (after beaconCountLimit is reached) beacon period (in sec). 122 | */ 123 | const double _slowBeaconPeriod; 124 | 125 | /** 126 | * Limit on number of beacons issued. 127 | */ 128 | const epics::pvData::int16 _beaconCountLimit; 129 | 130 | /** 131 | * Server address. 132 | */ 133 | const osiSockAddr _serverAddress; 134 | 135 | /** 136 | * Server port. 137 | */ 138 | const epics::pvData::int32 _serverPort; 139 | 140 | /** 141 | * Server status provider implementation (optional). 142 | */ 143 | BeaconServerStatusProvider::shared_pointer _serverStatusProvider; 144 | 145 | /** Timer is referenced by server context, which also references us. 146 | * We will also be queuing ourselves, and be referenced by Timer. 147 | * So keep only a weak ref to Timer to avoid possible ref. loop. 148 | */ 149 | epics::pvData::Timer::weak_pointer _timer; 150 | }; 151 | 152 | } 153 | } 154 | 155 | #endif /* BEACONEMITTER_H */ 156 | -------------------------------------------------------------------------------- /testApp/remote/testRAII.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | namespace pva = epics::pvAccess; 7 | 8 | class ChannelGetRequesterImpl : public pva::ChannelGetRequester 9 | { 10 | public: 11 | virtual ~ChannelGetRequesterImpl() { 12 | std::cout << "~ChannelGetRequesterImpl" << std::endl; 13 | } 14 | 15 | virtual std::string getRequesterName() { 16 | return "ChannelGetRequesterImpl"; 17 | } 18 | 19 | virtual void message(std::string const & message, epics::pvData::MessageType messageType) { 20 | std::cout << message << std::endl; 21 | } 22 | 23 | virtual void channelGetConnect( 24 | const epics::pvData::Status& status, 25 | pva::ChannelGet::shared_pointer const & channelGet, 26 | epics::pvData::Structure::const_shared_pointer const & structure) 27 | { 28 | if (status.isSuccess()) 29 | { 30 | std::cout << "issuing channel get" << std::endl; 31 | channelGet->get(); 32 | } 33 | else 34 | std::cout << "failed to create channel get: " << status << std::endl; 35 | } 36 | 37 | virtual void getDone( 38 | const epics::pvData::Status& status, 39 | pva::ChannelGet::shared_pointer const & channelGet, 40 | epics::pvData::PVStructure::shared_pointer const & pvStructure, 41 | epics::pvData::BitSet::shared_pointer const & bitSet) 42 | { 43 | if (status.isSuccess()) 44 | { 45 | std::cout << *pvStructure << std::endl; 46 | } 47 | else 48 | std::cout << "failed to get: " << status << std::endl; 49 | 50 | } 51 | }; 52 | 53 | class ChannelRequesterImpl : public pva::ChannelRequester 54 | { 55 | public: 56 | virtual ~ChannelRequesterImpl() { 57 | std::cout << "~ChannelRequesterImpl" << std::endl; 58 | } 59 | 60 | virtual std::string getRequesterName() { 61 | return "ChannelRequesterImpl"; 62 | } 63 | 64 | virtual void message(std::string const & message, epics::pvData::MessageType messageType) { 65 | std::cout << message << std::endl; 66 | } 67 | 68 | virtual void channelCreated(const epics::pvData::Status& status, 69 | pva::Channel::shared_pointer const & channel) 70 | { 71 | if (status.isSuccess()) 72 | { 73 | 74 | } 75 | else 76 | std::cout << "failed to create channel: " << status << std::endl; 77 | } 78 | 79 | /** 80 | * A channel connection state change has occurred. 81 | * @param c The channel. 82 | * @param connectionState The new connection state. 83 | */ 84 | virtual void channelStateChange(pva::Channel::shared_pointer const & channel, pva::Channel::ConnectionState connectionState) 85 | { 86 | std::cerr << "[" << channel->getChannelName() << "] channel state change: " 87 | << pva::Channel::ConnectionStateNames[connectionState] << std::endl; 88 | } 89 | }; 90 | 91 | int main() 92 | { 93 | pva::ClientFactory::start(); 94 | 95 | pva::ChannelProvider::shared_pointer provider = 96 | pva::ChannelProviderRegistry::clients()->getProvider("pva"); 97 | 98 | 99 | { 100 | pva::ChannelRequester::shared_pointer channelRequester(new ChannelRequesterImpl()); 101 | pva::Channel::shared_pointer channel = provider->createChannel("testChannel", channelRequester); 102 | 103 | { 104 | pva::ChannelGetRequester::shared_pointer channelGetRequester(new ChannelGetRequesterImpl()); 105 | pva::ChannelGet::shared_pointer channelGet = 106 | channel->createChannelGet(channelGetRequester, 107 | epics::pvData::CreateRequest::create()->createRequest("")); 108 | 109 | epicsThreadSleep(3.0); 110 | std::cout << "leaving channelGet scope, channelGet should be destroyed" << std::endl; 111 | } 112 | 113 | epicsThreadSleep(3.0); 114 | std::cout << "leaving channel scope, channel should be destroyed" << std::endl; 115 | } 116 | 117 | epicsThreadSleep(3.0); 118 | std::cout << "exiting" << std::endl; 119 | return 0; 120 | } 121 | -------------------------------------------------------------------------------- /src/pva/pv/pvaVersion.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | 7 | #ifndef VERSION_H_ 8 | #define VERSION_H_ 9 | 10 | #ifdef epicsExportSharedSymbols 11 | # define pvaVersionEpicsExportSharedSymbols 12 | # undef epicsExportSharedSymbols 13 | #endif 14 | 15 | #include 16 | #include 17 | 18 | #ifdef pvaVersionEpicsExportSharedSymbols 19 | # define epicsExportSharedSymbols 20 | # undef pvaVersionEpicsExportSharedSymbols 21 | #endif 22 | 23 | #include 24 | 25 | #include "pv/pvaVersionNum.h" 26 | 27 | #ifndef VERSION_INT 28 | # define VERSION_INT(V,R,M,P) ( ((V)<<24) | ((R)<<16) | ((M)<<8) | (P)) 29 | #endif 30 | 31 | #define PVACCESS_VERSION_INT VERSION_INT(EPICS_PVA_MAJOR_VERSION, EPICS_PVA_MINOR_VERSION, EPICS_PVA_MAINTENANCE_VERSION, 0) 32 | 33 | namespace epics { 34 | namespace pvAccess { 35 | 36 | class epicsShareClass Version { 37 | EPICS_NOT_COPYABLE(Version) 38 | public: 39 | /** 40 | * Default constructor. 41 | * @param productName product name. 42 | * @param implementationLangugage implementation language. 43 | * @param majorVersion major version. 44 | * @param minorVersion minor version. 45 | * @param maintenanceVersion maintenance version. 46 | * @param developmentFlag development indicator flag. 47 | */ 48 | Version(std::string const & productName, 49 | std::string const & implementationLangugage, 50 | int majorVersion, int minorVersion, 51 | int maintenanceVersion, bool developmentFlag); 52 | 53 | /** The name of the product */ 54 | const std::string getProductName() const; 55 | 56 | /** Implementation Language: C++ 57 | */ 58 | const std::string getImplementationLanguage() const; 59 | 60 | /** 61 | * Major version number. This changes only when there is a 62 | * significant, externally apparent enhancement from the previous release. 63 | * 'n' represents the n'th version. 64 | * 65 | * Clients should carefully consider the implications of new versions as 66 | * external interfaces and behaviour may have changed. 67 | */ 68 | int getMajorVersion() const; 69 | 70 | /** 71 | * Minor version number. This changes when: 72 | *
    73 | *
  • a new set of functionality is to be added
  • 74 | *
  • API or behaviour change
  • 75 | *
  • its designated as a reference release
  • 76 | *
77 | */ 78 | int getMinorVersion() const; 79 | 80 | /** 81 | * Maintenance version number. Optional identifier used to designate 82 | * maintenance drop applied to a specific release and contains fixes for 83 | * defects reported. It maintains compatibility with the release and 84 | * contains no API changes. When missing, it designates the final and 85 | * complete development drop for a release. 86 | */ 87 | int getMaintenanceVersion() const; 88 | 89 | /** 90 | * Development flag. 91 | * 92 | * Development drops are works in progress towards a completed, final 93 | * release. A specific development drop may not completely implement all 94 | * aspects of a new feature, which may take several development drops to 95 | * complete. At the point of the final drop for the release, the -SNAPSHOT suffix 96 | * will be omitted. 97 | */ 98 | bool isDevelopmentVersion() const; 99 | 100 | /** 101 | * Get the long version string. 102 | * @return std::string denoting current version 103 | */ 104 | const std::string getLongVersionString() const; 105 | 106 | /** 107 | * Get the basic version string. 108 | * @return std::string denoting current version 109 | */ 110 | const std::string getVersionString() const; 111 | 112 | private: 113 | std::string _productName; 114 | std::string _implementationLanguage; 115 | int _majorVersion; 116 | int _minorVersion; 117 | int _maintenanceVersion; 118 | bool _developmentFlag; 119 | }; 120 | 121 | epicsShareFunc std::ostream& operator<<(std::ostream& o, const Version& v); 122 | } 123 | } 124 | 125 | #endif /* VERSION_H_ */ 126 | -------------------------------------------------------------------------------- /src/ca/dbdToPv.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright - See the COPYRIGHT that is included with this distribution. 3 | * pvAccessCPP is distributed subject to a Software License Agreement found 4 | * in file LICENSE that is included with this distribution. 5 | */ 6 | /** 7 | * @author mrk 8 | * @date 2018.03 9 | */ 10 | #ifndef DbdToPv_H 11 | #define DbdToPv_H 12 | 13 | #include 14 | #include 15 | #include 16 | #include "caChannel.h" 17 | 18 | namespace epics { 19 | namespace pvAccess { 20 | namespace ca { 21 | 22 | enum IOType {getIO,putIO,monitorIO}; 23 | 24 | class AlarmDbd; 25 | typedef std::tr1::shared_ptr AlarmDbdPtr; 26 | class TimeStampDbd; 27 | typedef std::tr1::shared_ptr TimeStampDbdPtr; 28 | class DisplayDbd; 29 | typedef std::tr1::shared_ptr DisplayDbdPtr; 30 | class ControlDbd; 31 | typedef std::tr1::shared_ptr ControlDbdPtr; 32 | class ValueAlarmDbd; 33 | typedef std::tr1::shared_ptr ValueAlarmDbdPtr; 34 | 35 | struct CaAlarm 36 | { 37 | dbr_short_t status; 38 | dbr_short_t severity; 39 | CaAlarm() : status(0), severity(0) {} 40 | }; 41 | 42 | struct CaDisplay 43 | { 44 | double lower_disp_limit; 45 | double upper_disp_limit; 46 | std::string units; 47 | std::string format; 48 | CaDisplay() : lower_disp_limit(0),upper_disp_limit(0) {} 49 | }; 50 | 51 | struct CaControl 52 | { 53 | double upper_ctrl_limit; 54 | double lower_ctrl_limit; 55 | CaControl() : upper_ctrl_limit(0),lower_ctrl_limit(0) {} 56 | }; 57 | 58 | struct CaValueAlarm 59 | { 60 | double upper_alarm_limit; 61 | double upper_warning_limit; 62 | double lower_warning_limit; 63 | double lower_alarm_limit; 64 | CaValueAlarm() : 65 | upper_alarm_limit(0), 66 | upper_warning_limit(0), 67 | lower_warning_limit(0), 68 | lower_alarm_limit(0) 69 | {} 70 | }; 71 | 72 | class DbdToPv; 73 | typedef std::tr1::shared_ptr DbdToPvPtr; 74 | 75 | typedef void ( caCallbackFunc ) (struct event_handler_args); 76 | 77 | /** 78 | * @brief DbdToPv converts between DBD data and pvData. 79 | * 80 | * 81 | */ 82 | class DbdToPv 83 | { 84 | public: 85 | POINTER_DEFINITIONS(DbdToPv); 86 | static DbdToPvPtr create( 87 | CAChannelPtr const & caChannel, 88 | epics::pvData::PVStructurePtr const & pvRequest, 89 | IOType ioType 90 | ); 91 | epics::pvData::Structure::const_shared_pointer getStructure(); 92 | void getChoices(CAChannelPtr const & caChannel); 93 | epics::pvData::PVStructurePtr createPVStructure(); 94 | chtype getRequestType(); 95 | epics::pvData::Status getFromDBD( 96 | epics::pvData::PVStructurePtr const & pvStructure, 97 | epics::pvData::BitSet::shared_pointer const & bitSet, 98 | struct event_handler_args &args 99 | ); 100 | epics::pvData::Status putToDBD( 101 | CAChannelPtr const & caChannel, 102 | epics::pvData::PVStructurePtr const & pvStructure, 103 | bool block, 104 | caCallbackFunc putHandler, 105 | void *userArg 106 | ); 107 | void getChoicesDone(struct event_handler_args &args); 108 | private: 109 | DbdToPv(IOType ioType); 110 | void activate( 111 | CAChannelPtr const & caChannel, 112 | epics::pvData::PVStructurePtr const & pvRequest 113 | ); 114 | IOType ioType; 115 | bool dbfIsUCHAR; 116 | bool dbfIsUSHORT; 117 | bool dbfIsULONG; 118 | bool dbfIsINT64; 119 | bool dbfIsUINT64; 120 | bool valueRequested; 121 | bool alarmRequested; 122 | bool timeStampRequested; 123 | bool displayRequested; 124 | bool controlRequested; 125 | bool valueAlarmRequested; 126 | bool isArray; 127 | bool charArrayIsString; 128 | bool firstTime; 129 | chtype caValueType; 130 | chtype caRequestType; 131 | unsigned long maxElements; 132 | epicsEvent choicesEvent; 133 | epicsTimeStamp caTimeStamp; 134 | CaAlarm caAlarm; 135 | CaDisplay caDisplay; 136 | CaControl caControl; 137 | CaValueAlarm caValueAlarm; 138 | epics::pvData::Structure::const_shared_pointer structure; 139 | std::vector choices; 140 | epics::pvData::PVDoubleArrayPtr pvDoubleArray; //for dbfIsINT64 and dbfIsUINT64 141 | }; 142 | 143 | } 144 | } 145 | } 146 | 147 | #endif /* DbdToPv_H */ 148 | --------------------------------------------------------------------------------