From 102174913c572f6b83cee1b84286cb7dbef7c1fb Mon Sep 17 00:00:00 2001
From: mrkraimer
Date: Thu, 21 Jan 2016 14:39:23 -0500
Subject: [PATCH 1/3] remove examples (moved to exampleCPP) ; test is now a
regresion test (make runtests)
---
Doxyfile | 2 +-
Makefile | 25 +-
README.md | 16 +-
RELEASE_NOTES.md | 11 +
arrayPerformance/Makefile | 11 -
arrayPerformance/configure/CONFIG | 29 -
arrayPerformance/configure/CONFIG_SITE | 39 -
.../configure/ExampleRELEASE.local | 8 -
arrayPerformance/configure/Makefile | 8 -
arrayPerformance/configure/RELEASE | 40 -
arrayPerformance/configure/RULES | 6 -
arrayPerformance/configure/RULES.ioc | 2 -
arrayPerformance/configure/RULES_DIRS | 2 -
arrayPerformance/configure/RULES_TOP | 2 -
arrayPerformance/src/Makefile | 45 -
arrayPerformance/src/arrayPerformance.cpp | 206 --
arrayPerformance/src/arrayPerformance.h | 92 -
arrayPerformance/src/arrayPerformanceMain.cpp | 119 -
arrayPerformance/src/longArrayGet.cpp | 543 -----
arrayPerformance/src/longArrayGet.h | 81 -
arrayPerformance/src/longArrayGetMain.cpp | 87 -
arrayPerformance/src/longArrayMonitor.cpp | 319 ---
arrayPerformance/src/longArrayMonitor.h | 85 -
arrayPerformance/src/longArrayMonitorMain.cpp | 76 -
arrayPerformance/src/longArrayPut.cpp | 383 ---
arrayPerformance/src/longArrayPut.h | 84 -
arrayPerformance/src/longArrayPutMain.cpp | 93 -
.../src/vectorPerformanceMain.cpp | 189 --
configure/ExampleRELEASE.local | 12 +-
documentation/pvDatabaseCPP.html | 1171 +--------
documentation/pvDatabaseCPP_20121127.html | 714 ------
documentation/pvDatabaseCPP_20121211.html | 874 -------
documentation/pvDatabaseCPP_20130417.html | 870 -------
documentation/pvDatabaseCPP_20130516.html | 876 -------
documentation/pvDatabaseCPP_20130523.html | 1001 --------
documentation/pvDatabaseCPP_20130627.html | 1155 ---------
documentation/pvDatabaseCPP_20130725.html | 1244 ----------
documentation/pvDatabaseCPP_20130828.html | 1732 --------------
documentation/pvDatabaseCPP_20130904.html | 1809 --------------
documentation/pvDatabaseCPP_20131112.html | 1831 --------------
documentation/pvDatabaseCPP_20131113.html | 1803 --------------
documentation/pvDatabaseCPP_20131120.html | 1936 ---------------
documentation/pvDatabaseCPP_20131121.html | 1936 ---------------
documentation/pvDatabaseCPP_20140207.html | 2040 ----------------
documentation/pvDatabaseCPP_20140219.html | 2043 ----------------
documentation/pvDatabaseCPP_20140710.html | 1940 ---------------
documentation/pvDatabaseCPP_20140811.html | 2111 -----------------
documentation/pvDatabaseCPP_20151002.html | 2052 ----------------
documentation/pvDatabaseCPP_20151023.html | 2004 ----------------
exampleDatabase/Makefile | 19 -
exampleDatabase/configure/CONFIG | 29 -
exampleDatabase/configure/CONFIG_SITE | 27 -
.../configure/ExampleRELEASE.local | 9 -
exampleDatabase/configure/Makefile | 8 -
exampleDatabase/configure/RELEASE | 43 -
exampleDatabase/configure/RULES | 6 -
exampleDatabase/configure/RULES.ioc | 2 -
exampleDatabase/configure/RULES_DIRS | 2 -
exampleDatabase/configure/RULES_TOP | 3 -
exampleDatabase/ioc/Db/Makefile | 29 -
exampleDatabase/ioc/Db/dbArray.db | 9 -
exampleDatabase/ioc/Db/dbCounter.db | 20 -
exampleDatabase/ioc/Db/dbDouble.db | 3 -
exampleDatabase/ioc/Db/dbEnum.db | 14 -
exampleDatabase/ioc/Db/dbInteger.db | 16 -
exampleDatabase/ioc/Db/dbScalar.db | 17 -
exampleDatabase/ioc/Db/dbString.db | 3 -
exampleDatabase/ioc/Db/dbStringArray.db | 5 -
exampleDatabase/ioc/Makefile | 8 -
exampleDatabase/ioc/src/Makefile | 43 -
.../ioc/src/exampleDatabaseInclude.dbd | 6 -
.../ioc/src/exampleDatabaseMain.cpp | 33 -
exampleDatabase/iocBoot/Makefile | 7 -
.../iocBoot/exampleDatabase/Makefile | 5 -
.../iocBoot/exampleDatabase/st.cmd | 29 -
exampleDatabase/src/Makefile | 35 -
exampleDatabase/src/exampleDatabase.cpp | 159 --
exampleDatabase/src/exampleDatabase.h | 38 -
.../src/exampleDatabaseInclude.dbd | 1 -
exampleDatabase/src/exampleDatabaseMain.cpp | 36 -
.../src/exampleDatabaseRegister.cpp | 63 -
exampleLink/Makefile | 16 -
exampleLink/configure/CONFIG | 29 -
exampleLink/configure/CONFIG_SITE | 39 -
exampleLink/configure/ExampleRELEASE.local | 8 -
exampleLink/configure/Makefile | 8 -
exampleLink/configure/RELEASE | 40 -
exampleLink/configure/RULES | 6 -
exampleLink/configure/RULES.ioc | 2 -
exampleLink/configure/RULES_DIRS | 2 -
exampleLink/configure/RULES_TOP | 3 -
exampleLink/ioc/Db/Makefile | 21 -
exampleLink/ioc/Db/ai.db | 13 -
exampleLink/ioc/Makefile | 8 -
exampleLink/ioc/src/Makefile | 43 -
exampleLink/ioc/src/exampleLinkInclude.dbd | 5 -
exampleLink/ioc/src/exampleLinkMain.cpp | 31 -
exampleLink/iocBoot/Makefile | 7 -
exampleLink/iocBoot/exampleLink/Makefile | 5 -
exampleLink/iocBoot/exampleLink/st.local | 16 -
exampleLink/iocBoot/exampleLink/st.remote | 16 -
exampleLink/src/Makefile | 30 -
exampleLink/src/exampleLink.cpp | 164 --
exampleLink/src/exampleLink.h | 102 -
exampleLink/src/exampleLinkInclude.dbd | 1 -
exampleLink/src/exampleLinkRegister.cpp | 89 -
exampleLink/src/exampleLinkRegister.dbd | 1 -
examplePowerSupply/Makefile | 19 -
examplePowerSupply/configure/CONFIG | 29 -
examplePowerSupply/configure/CONFIG_SITE | 39 -
.../configure/ExampleRELEASE.local | 9 -
examplePowerSupply/configure/Makefile | 8 -
examplePowerSupply/configure/RELEASE | 42 -
examplePowerSupply/configure/RULES | 6 -
examplePowerSupply/configure/RULES.ioc | 2 -
examplePowerSupply/configure/RULES_DIRS | 2 -
examplePowerSupply/configure/RULES_TOP | 3 -
examplePowerSupply/ioc/Db/Makefile | 28 -
examplePowerSupply/ioc/Db/dbArray.db | 9 -
examplePowerSupply/ioc/Db/dbCounter.db | 20 -
examplePowerSupply/ioc/Db/dbEnum.db | 14 -
examplePowerSupply/ioc/Db/dbInteger.db | 16 -
examplePowerSupply/ioc/Db/dbScalar.db | 17 -
examplePowerSupply/ioc/Db/dbString.db | 3 -
examplePowerSupply/ioc/Db/dbStringArray.db | 5 -
examplePowerSupply/ioc/Makefile | 8 -
examplePowerSupply/ioc/src/Makefile | 41 -
.../ioc/src/powerSupplyInclude.dbd | 5 -
.../ioc/src/powerSupplyMain.cpp | 31 -
examplePowerSupply/iocBoot/Makefile | 7 -
.../iocBoot/powerSupply/Makefile | 5 -
examplePowerSupply/iocBoot/powerSupply/st.cmd | 23 -
examplePowerSupply/src/Makefile | 27 -
examplePowerSupply/src/powerSupplyMain.cpp | 50 -
.../src/powerSupplyRegisterInclude.dbd | 1 -
exampleRPC/Makefile | 16 -
exampleRPC/configure/CONFIG | 29 -
exampleRPC/configure/CONFIG_SITE | 39 -
exampleRPC/configure/ExampleRELEASE.local | 8 -
exampleRPC/configure/Makefile | 8 -
exampleRPC/configure/RELEASE | 40 -
exampleRPC/configure/RULES | 6 -
exampleRPC/configure/RULES.ioc | 2 -
exampleRPC/configure/RULES_DIRS | 2 -
exampleRPC/configure/RULES_TOP | 3 -
exampleRPC/ioc/Db/Makefile | 28 -
exampleRPC/ioc/Db/dbArray.db | 9 -
exampleRPC/ioc/Db/dbCounter.db | 20 -
exampleRPC/ioc/Db/dbEnum.db | 14 -
exampleRPC/ioc/Db/dbInteger.db | 16 -
exampleRPC/ioc/Db/dbScalar.db | 17 -
exampleRPC/ioc/Db/dbString.db | 3 -
exampleRPC/ioc/Db/dbStringArray.db | 5 -
exampleRPC/ioc/Makefile | 8 -
exampleRPC/ioc/src/Makefile | 41 -
exampleRPC/ioc/src/exampleRPCInclude.dbd | 6 -
exampleRPC/ioc/src/exampleRPCMain.cpp | 31 -
exampleRPC/iocBoot/Makefile | 7 -
exampleRPC/iocBoot/exampleRPC/Makefile | 5 -
exampleRPC/iocBoot/exampleRPC/st.cmd | 23 -
exampleRPC/src/Makefile | 43 -
exampleRPC/src/exampleRPC.cpp | 227 --
exampleRPC/src/exampleRPC.h | 126 -
exampleRPC/src/exampleRPCInclude.dbd | 1 -
exampleRPC/src/exampleRPCMain.cpp | 48 -
exampleRPC/src/exampleRPCRegister.cpp | 71 -
exampleRPC/src/exampleRPCRegister.dbd | 1 -
exampleRPC/src/positionClient.cpp | 135 --
exampleServer/Makefile | 16 -
exampleServer/configure/CONFIG | 29 -
exampleServer/configure/CONFIG_SITE | 39 -
exampleServer/configure/ExampleRELEASE.local | 8 -
exampleServer/configure/Makefile | 8 -
exampleServer/configure/RELEASE | 40 -
exampleServer/configure/RULES | 6 -
exampleServer/configure/RULES.ioc | 2 -
exampleServer/configure/RULES_DIRS | 2 -
exampleServer/configure/RULES_TOP | 3 -
exampleServer/ioc/Db/Makefile | 28 -
exampleServer/ioc/Db/dbArray.db | 9 -
exampleServer/ioc/Db/dbCounter.db | 20 -
exampleServer/ioc/Db/dbEnum.db | 14 -
exampleServer/ioc/Db/dbInteger.db | 16 -
exampleServer/ioc/Db/dbScalar.db | 17 -
exampleServer/ioc/Db/dbString.db | 3 -
exampleServer/ioc/Db/dbStringArray.db | 5 -
exampleServer/ioc/Makefile | 8 -
exampleServer/ioc/src/Makefile | 41 -
.../ioc/src/exampleServerInclude.dbd | 6 -
exampleServer/ioc/src/exampleServerMain.cpp | 31 -
exampleServer/iocBoot/Makefile | 7 -
exampleServer/iocBoot/exampleServer/Makefile | 5 -
exampleServer/iocBoot/exampleServer/st.cmd | 23 -
exampleServer/src/Makefile | 39 -
exampleServer/src/exampleServer.cpp | 84 -
exampleServer/src/exampleServer.h | 61 -
exampleServer/src/exampleServerInclude.dbd | 1 -
exampleServer/src/exampleServerMain.cpp | 55 -
exampleServer/src/exampleServerRegister.cpp | 71 -
exampleServer/src/exampleServerRegister.dbd | 1 -
jenkins/cloudbees_build | 4 +-
src/Makefile | 8 +-
src/database/Makefile | 2 -
src/{pvAccess => pv}/channelProviderLocal.h | 0
src/{database => pv}/pvDatabase.h | 2 +-
src/{special => pv}/traceRecord.h | 0
src/pvAccess/Makefile | 2 -
src/special/Makefile | 2 -
test/Makefile | 29 +-
test/configure/CONFIG | 29 -
test/configure/CONFIG_SITE | 39 -
test/configure/Makefile | 8 -
test/configure/RELEASE | 40 -
test/configure/RULES | 6 -
test/configure/RULES.ioc | 2 -
test/configure/RULES_DIRS | 2 -
test/configure/RULES_TOP | 3 -
test/src/Makefile | 38 +-
test/src/powerSupply.cpp | 162 --
test/src/powerSupply.h | 138 +-
test/src/powerSupplyRegister.cpp | 72 -
test/src/powerSupplyRegister.dbd | 1 -
test/src/testExampleRecord.cpp | 55 +-
test/src/testPVCopy.cpp | 215 +-
test/src/testPVRecord.cpp | 25 +-
225 files changed, 425 insertions(+), 37853 deletions(-)
delete mode 100644 arrayPerformance/Makefile
delete mode 100644 arrayPerformance/configure/CONFIG
delete mode 100644 arrayPerformance/configure/CONFIG_SITE
delete mode 100644 arrayPerformance/configure/ExampleRELEASE.local
delete mode 100644 arrayPerformance/configure/Makefile
delete mode 100644 arrayPerformance/configure/RELEASE
delete mode 100644 arrayPerformance/configure/RULES
delete mode 100644 arrayPerformance/configure/RULES.ioc
delete mode 100644 arrayPerformance/configure/RULES_DIRS
delete mode 100644 arrayPerformance/configure/RULES_TOP
delete mode 100644 arrayPerformance/src/Makefile
delete mode 100644 arrayPerformance/src/arrayPerformance.cpp
delete mode 100644 arrayPerformance/src/arrayPerformance.h
delete mode 100644 arrayPerformance/src/arrayPerformanceMain.cpp
delete mode 100644 arrayPerformance/src/longArrayGet.cpp
delete mode 100644 arrayPerformance/src/longArrayGet.h
delete mode 100644 arrayPerformance/src/longArrayGetMain.cpp
delete mode 100644 arrayPerformance/src/longArrayMonitor.cpp
delete mode 100644 arrayPerformance/src/longArrayMonitor.h
delete mode 100644 arrayPerformance/src/longArrayMonitorMain.cpp
delete mode 100644 arrayPerformance/src/longArrayPut.cpp
delete mode 100644 arrayPerformance/src/longArrayPut.h
delete mode 100644 arrayPerformance/src/longArrayPutMain.cpp
delete mode 100644 arrayPerformance/src/vectorPerformanceMain.cpp
delete mode 100644 documentation/pvDatabaseCPP_20121127.html
delete mode 100644 documentation/pvDatabaseCPP_20121211.html
delete mode 100644 documentation/pvDatabaseCPP_20130417.html
delete mode 100644 documentation/pvDatabaseCPP_20130516.html
delete mode 100644 documentation/pvDatabaseCPP_20130523.html
delete mode 100644 documentation/pvDatabaseCPP_20130627.html
delete mode 100644 documentation/pvDatabaseCPP_20130725.html
delete mode 100644 documentation/pvDatabaseCPP_20130828.html
delete mode 100644 documentation/pvDatabaseCPP_20130904.html
delete mode 100644 documentation/pvDatabaseCPP_20131112.html
delete mode 100644 documentation/pvDatabaseCPP_20131113.html
delete mode 100644 documentation/pvDatabaseCPP_20131120.html
delete mode 100644 documentation/pvDatabaseCPP_20131121.html
delete mode 100644 documentation/pvDatabaseCPP_20140207.html
delete mode 100644 documentation/pvDatabaseCPP_20140219.html
delete mode 100644 documentation/pvDatabaseCPP_20140710.html
delete mode 100644 documentation/pvDatabaseCPP_20140811.html
delete mode 100644 documentation/pvDatabaseCPP_20151002.html
delete mode 100644 documentation/pvDatabaseCPP_20151023.html
delete mode 100644 exampleDatabase/Makefile
delete mode 100644 exampleDatabase/configure/CONFIG
delete mode 100644 exampleDatabase/configure/CONFIG_SITE
delete mode 100644 exampleDatabase/configure/ExampleRELEASE.local
delete mode 100644 exampleDatabase/configure/Makefile
delete mode 100644 exampleDatabase/configure/RELEASE
delete mode 100644 exampleDatabase/configure/RULES
delete mode 100644 exampleDatabase/configure/RULES.ioc
delete mode 100644 exampleDatabase/configure/RULES_DIRS
delete mode 100644 exampleDatabase/configure/RULES_TOP
delete mode 100644 exampleDatabase/ioc/Db/Makefile
delete mode 100644 exampleDatabase/ioc/Db/dbArray.db
delete mode 100644 exampleDatabase/ioc/Db/dbCounter.db
delete mode 100644 exampleDatabase/ioc/Db/dbDouble.db
delete mode 100644 exampleDatabase/ioc/Db/dbEnum.db
delete mode 100644 exampleDatabase/ioc/Db/dbInteger.db
delete mode 100644 exampleDatabase/ioc/Db/dbScalar.db
delete mode 100644 exampleDatabase/ioc/Db/dbString.db
delete mode 100644 exampleDatabase/ioc/Db/dbStringArray.db
delete mode 100644 exampleDatabase/ioc/Makefile
delete mode 100644 exampleDatabase/ioc/src/Makefile
delete mode 100644 exampleDatabase/ioc/src/exampleDatabaseInclude.dbd
delete mode 100644 exampleDatabase/ioc/src/exampleDatabaseMain.cpp
delete mode 100644 exampleDatabase/iocBoot/Makefile
delete mode 100644 exampleDatabase/iocBoot/exampleDatabase/Makefile
delete mode 100644 exampleDatabase/iocBoot/exampleDatabase/st.cmd
delete mode 100644 exampleDatabase/src/Makefile
delete mode 100644 exampleDatabase/src/exampleDatabase.cpp
delete mode 100644 exampleDatabase/src/exampleDatabase.h
delete mode 100644 exampleDatabase/src/exampleDatabaseInclude.dbd
delete mode 100644 exampleDatabase/src/exampleDatabaseMain.cpp
delete mode 100644 exampleDatabase/src/exampleDatabaseRegister.cpp
delete mode 100644 exampleLink/Makefile
delete mode 100644 exampleLink/configure/CONFIG
delete mode 100644 exampleLink/configure/CONFIG_SITE
delete mode 100644 exampleLink/configure/ExampleRELEASE.local
delete mode 100644 exampleLink/configure/Makefile
delete mode 100644 exampleLink/configure/RELEASE
delete mode 100644 exampleLink/configure/RULES
delete mode 100644 exampleLink/configure/RULES.ioc
delete mode 100644 exampleLink/configure/RULES_DIRS
delete mode 100644 exampleLink/configure/RULES_TOP
delete mode 100644 exampleLink/ioc/Db/Makefile
delete mode 100644 exampleLink/ioc/Db/ai.db
delete mode 100644 exampleLink/ioc/Makefile
delete mode 100644 exampleLink/ioc/src/Makefile
delete mode 100644 exampleLink/ioc/src/exampleLinkInclude.dbd
delete mode 100644 exampleLink/ioc/src/exampleLinkMain.cpp
delete mode 100644 exampleLink/iocBoot/Makefile
delete mode 100644 exampleLink/iocBoot/exampleLink/Makefile
delete mode 100644 exampleLink/iocBoot/exampleLink/st.local
delete mode 100644 exampleLink/iocBoot/exampleLink/st.remote
delete mode 100644 exampleLink/src/Makefile
delete mode 100644 exampleLink/src/exampleLink.cpp
delete mode 100644 exampleLink/src/exampleLink.h
delete mode 100644 exampleLink/src/exampleLinkInclude.dbd
delete mode 100644 exampleLink/src/exampleLinkRegister.cpp
delete mode 100644 exampleLink/src/exampleLinkRegister.dbd
delete mode 100644 examplePowerSupply/Makefile
delete mode 100644 examplePowerSupply/configure/CONFIG
delete mode 100644 examplePowerSupply/configure/CONFIG_SITE
delete mode 100644 examplePowerSupply/configure/ExampleRELEASE.local
delete mode 100644 examplePowerSupply/configure/Makefile
delete mode 100644 examplePowerSupply/configure/RELEASE
delete mode 100644 examplePowerSupply/configure/RULES
delete mode 100644 examplePowerSupply/configure/RULES.ioc
delete mode 100644 examplePowerSupply/configure/RULES_DIRS
delete mode 100644 examplePowerSupply/configure/RULES_TOP
delete mode 100644 examplePowerSupply/ioc/Db/Makefile
delete mode 100644 examplePowerSupply/ioc/Db/dbArray.db
delete mode 100644 examplePowerSupply/ioc/Db/dbCounter.db
delete mode 100644 examplePowerSupply/ioc/Db/dbEnum.db
delete mode 100644 examplePowerSupply/ioc/Db/dbInteger.db
delete mode 100644 examplePowerSupply/ioc/Db/dbScalar.db
delete mode 100644 examplePowerSupply/ioc/Db/dbString.db
delete mode 100644 examplePowerSupply/ioc/Db/dbStringArray.db
delete mode 100644 examplePowerSupply/ioc/Makefile
delete mode 100644 examplePowerSupply/ioc/src/Makefile
delete mode 100644 examplePowerSupply/ioc/src/powerSupplyInclude.dbd
delete mode 100644 examplePowerSupply/ioc/src/powerSupplyMain.cpp
delete mode 100644 examplePowerSupply/iocBoot/Makefile
delete mode 100644 examplePowerSupply/iocBoot/powerSupply/Makefile
delete mode 100644 examplePowerSupply/iocBoot/powerSupply/st.cmd
delete mode 100644 examplePowerSupply/src/Makefile
delete mode 100644 examplePowerSupply/src/powerSupplyMain.cpp
delete mode 100644 examplePowerSupply/src/powerSupplyRegisterInclude.dbd
delete mode 100644 exampleRPC/Makefile
delete mode 100644 exampleRPC/configure/CONFIG
delete mode 100644 exampleRPC/configure/CONFIG_SITE
delete mode 100644 exampleRPC/configure/ExampleRELEASE.local
delete mode 100644 exampleRPC/configure/Makefile
delete mode 100644 exampleRPC/configure/RELEASE
delete mode 100644 exampleRPC/configure/RULES
delete mode 100644 exampleRPC/configure/RULES.ioc
delete mode 100644 exampleRPC/configure/RULES_DIRS
delete mode 100644 exampleRPC/configure/RULES_TOP
delete mode 100644 exampleRPC/ioc/Db/Makefile
delete mode 100644 exampleRPC/ioc/Db/dbArray.db
delete mode 100644 exampleRPC/ioc/Db/dbCounter.db
delete mode 100644 exampleRPC/ioc/Db/dbEnum.db
delete mode 100644 exampleRPC/ioc/Db/dbInteger.db
delete mode 100644 exampleRPC/ioc/Db/dbScalar.db
delete mode 100644 exampleRPC/ioc/Db/dbString.db
delete mode 100644 exampleRPC/ioc/Db/dbStringArray.db
delete mode 100644 exampleRPC/ioc/Makefile
delete mode 100644 exampleRPC/ioc/src/Makefile
delete mode 100644 exampleRPC/ioc/src/exampleRPCInclude.dbd
delete mode 100644 exampleRPC/ioc/src/exampleRPCMain.cpp
delete mode 100644 exampleRPC/iocBoot/Makefile
delete mode 100644 exampleRPC/iocBoot/exampleRPC/Makefile
delete mode 100644 exampleRPC/iocBoot/exampleRPC/st.cmd
delete mode 100644 exampleRPC/src/Makefile
delete mode 100644 exampleRPC/src/exampleRPC.cpp
delete mode 100644 exampleRPC/src/exampleRPC.h
delete mode 100644 exampleRPC/src/exampleRPCInclude.dbd
delete mode 100644 exampleRPC/src/exampleRPCMain.cpp
delete mode 100644 exampleRPC/src/exampleRPCRegister.cpp
delete mode 100644 exampleRPC/src/exampleRPCRegister.dbd
delete mode 100644 exampleRPC/src/positionClient.cpp
delete mode 100644 exampleServer/Makefile
delete mode 100644 exampleServer/configure/CONFIG
delete mode 100644 exampleServer/configure/CONFIG_SITE
delete mode 100644 exampleServer/configure/ExampleRELEASE.local
delete mode 100644 exampleServer/configure/Makefile
delete mode 100644 exampleServer/configure/RELEASE
delete mode 100644 exampleServer/configure/RULES
delete mode 100644 exampleServer/configure/RULES.ioc
delete mode 100644 exampleServer/configure/RULES_DIRS
delete mode 100644 exampleServer/configure/RULES_TOP
delete mode 100644 exampleServer/ioc/Db/Makefile
delete mode 100644 exampleServer/ioc/Db/dbArray.db
delete mode 100644 exampleServer/ioc/Db/dbCounter.db
delete mode 100644 exampleServer/ioc/Db/dbEnum.db
delete mode 100644 exampleServer/ioc/Db/dbInteger.db
delete mode 100644 exampleServer/ioc/Db/dbScalar.db
delete mode 100644 exampleServer/ioc/Db/dbString.db
delete mode 100644 exampleServer/ioc/Db/dbStringArray.db
delete mode 100644 exampleServer/ioc/Makefile
delete mode 100644 exampleServer/ioc/src/Makefile
delete mode 100644 exampleServer/ioc/src/exampleServerInclude.dbd
delete mode 100644 exampleServer/ioc/src/exampleServerMain.cpp
delete mode 100644 exampleServer/iocBoot/Makefile
delete mode 100644 exampleServer/iocBoot/exampleServer/Makefile
delete mode 100644 exampleServer/iocBoot/exampleServer/st.cmd
delete mode 100644 exampleServer/src/Makefile
delete mode 100644 exampleServer/src/exampleServer.cpp
delete mode 100644 exampleServer/src/exampleServer.h
delete mode 100644 exampleServer/src/exampleServerInclude.dbd
delete mode 100644 exampleServer/src/exampleServerMain.cpp
delete mode 100644 exampleServer/src/exampleServerRegister.cpp
delete mode 100644 exampleServer/src/exampleServerRegister.dbd
rename src/{pvAccess => pv}/channelProviderLocal.h (100%)
rename src/{database => pv}/pvDatabase.h (99%)
rename src/{special => pv}/traceRecord.h (100%)
delete mode 100644 test/configure/CONFIG
delete mode 100644 test/configure/CONFIG_SITE
delete mode 100644 test/configure/Makefile
delete mode 100644 test/configure/RELEASE
delete mode 100644 test/configure/RULES
delete mode 100644 test/configure/RULES.ioc
delete mode 100644 test/configure/RULES_DIRS
delete mode 100644 test/configure/RULES_TOP
delete mode 100644 test/src/powerSupply.cpp
delete mode 100644 test/src/powerSupplyRegister.cpp
delete mode 100644 test/src/powerSupplyRegister.dbd
diff --git a/Doxyfile b/Doxyfile
index 24768b1..3caa0af 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -1078,7 +1078,7 @@ HTML_EXTRA_STYLESHEET =
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
-HTML_EXTRA_FILES = documentation/pvDatabaseCPP.html
+HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the stylesheet and background images according to
diff --git a/Makefile b/Makefile
index 70d34e5..c7236b5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,27 +1,12 @@
#Makefile at top of application tree
TOP = .
include $(TOP)/configure/CONFIG
-DIRS := $(DIRS) $(filter-out $(DIRS), configure)
-DIRS := $(DIRS) $(filter-out $(DIRS), src)
-DIRS := $(DIRS) $(filter-out $(DIRS), test)
-DIRS := $(DIRS) $(filter-out $(DIRS), arrayPerformance)
-DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard example*))
+DIRS += configure
-EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), test)
-EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), arrayPerformance)
-EMBEDDED_TOPS := $(EMBEDDED_TOPS) $(filter-out $(EMBEDDED_TOPS), $(wildcard example*))
+DIRS += src
+src_DEPEND_DIRS = configure
-define DIR_template
- $(1)_DEPEND_DIRS = configure
-endef
-$(foreach dir, $(filter-out configure,$(DIRS)),$(eval $(call DIR_template,$(dir))))
-
-define EMB_template
- $(1)_DEPEND_DIRS = src
-endef
-$(foreach dir, $(EMBEDDED_TOPS),$(eval $(call EMB_template,$(dir))))
-
-#exampleDatabase_DEPEND_DIRS += test
-#examplePowerSupply_DEPEND_DIRS += test
+DIRS += test
+test_DEPEND_DIRS = src
include $(TOP)/configure/RULES_TOP
diff --git a/README.md b/README.md
index b8ac347..ee6a6c5 100644
--- a/README.md
+++ b/README.md
@@ -17,18 +17,18 @@ then just type:
make
-If RELEASE.local does not exist then look at configure/RELEASE
-for directions for how to build.
+It can also be built by:
+
+ cp configure/ExampleRELEASE.local configure/RELEASE.local
+ edit configure/RELEASE.local
+ make
+
+
Examples
------------
-The examples require the database in pvaDatabaseTestCPP.
-For example:
-
- mrk> pwd
- /home/epicsv4/pvaDatabaseTestCPP/database/iocBoot/exampleDatabase
- mrk> ../../bin/linux-x86_64/exampleDatabase st.cmd
+Examples are available in exampleCPP.
Status
------
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 78f1bf3..1efca70 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,3 +1,14 @@
+
+EPICS V4 release 4.6
+====================
+
+The examples are moved to exampleCPP
+
+The test is now a regression test the can be ran via
+
+ make runtests
+
+
EPICS V4 release 4.5
====================
diff --git a/arrayPerformance/Makefile b/arrayPerformance/Makefile
deleted file mode 100644
index 999631d..0000000
--- a/arrayPerformance/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-#Makefile at top of application tree
-TOP = .
-include $(TOP)/configure/CONFIG
-DIRS += configure
-
-DIRS += src
-src_DEPEND_DIRS = configure
-
-include $(TOP)/configure/RULES_TOP
-
-
diff --git a/arrayPerformance/configure/CONFIG b/arrayPerformance/configure/CONFIG
deleted file mode 100644
index c1a4703..0000000
--- a/arrayPerformance/configure/CONFIG
+++ /dev/null
@@ -1,29 +0,0 @@
-# CONFIG - Load build configuration data
-#
-# Do not make changes to this file!
-
-# Allow user to override where the build rules come from
-RULES = $(EPICS_BASE)
-
-# RELEASE files point to other application tops
-include $(TOP)/configure/RELEASE
--include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).Common
-ifdef T_A
--include $(TOP)/configure/RELEASE.Common.$(T_A)
--include $(TOP)/configure/RELEASE.$(EPICS_HOST_ARCH).$(T_A)
-endif
-
-CONFIG = $(RULES)/configure
-include $(CONFIG)/CONFIG
-
-# Override the Base definition:
-INSTALL_LOCATION = $(TOP)
-
-# CONFIG_SITE files contain other build configuration settings
-include $(TOP)/configure/CONFIG_SITE
--include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).Common
-ifdef T_A
- -include $(TOP)/configure/CONFIG_SITE.Common.$(T_A)
- -include $(TOP)/configure/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
-endif
-
diff --git a/arrayPerformance/configure/CONFIG_SITE b/arrayPerformance/configure/CONFIG_SITE
deleted file mode 100644
index 0165b88..0000000
--- a/arrayPerformance/configure/CONFIG_SITE
+++ /dev/null
@@ -1,39 +0,0 @@
-# CONFIG_SITE
-
-# Make any application-specific changes to the EPICS build
-# configuration variables in this file.
-#
-# Host/target specific settings can be specified in files named
-# CONFIG_SITE.$(EPICS_HOST_ARCH).Common
-# CONFIG_SITE.Common.$(T_A)
-# CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
-
-# CHECK_RELEASE controls the consistency checking of the support
-# applications pointed to by the RELEASE* files.
-# Normally CHECK_RELEASE should be set to YES.
-# Set CHECK_RELEASE to NO to disable checking completely.
-# Set CHECK_RELEASE to WARN to perform consistency checking but
-# continue building anyway if conflicts are found.
-#CHECK_RELEASE = YES
-
-# Set this when you only want to compile this application
-# for a subset of the cross-compiled target architectures
-# that Base is built for.
-#CROSS_COMPILER_TARGET_ARCHS = vxWorks-68040
-
-# To install files into a location other than $(TOP) define
-# INSTALL_LOCATION here.
-#INSTALL_LOCATION=
-
-# Set this when your IOC and the host use different paths
-# to access the application. This will be needed to boot
-# from a Microsoft FTP server or with some NFS mounts.
-# You must rebuild in the iocBoot directory for this to
-# take effect.
-#IOCS_APPL_TOP =
-
-INSTALL_INCLUDE = $(INSTALL_LOCATION)/include/pv
-USR_INCLUDES += -I $(INSTALL_LOCATION)/include
-
--include $(TOP)/../../CONFIG_SITE.local
--include $(TOP)/../configure/CONFIG_SITE.local
diff --git a/arrayPerformance/configure/ExampleRELEASE.local b/arrayPerformance/configure/ExampleRELEASE.local
deleted file mode 100644
index 95e3783..0000000
--- a/arrayPerformance/configure/ExampleRELEASE.local
+++ /dev/null
@@ -1,8 +0,0 @@
-EPICS_BASE=/home/install/epics/base
-TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
-EPICSV4HOME=/home/hg
-PVCOMMON=${EPICSV4HOME}/pvCommonCPP
-PVDATA=${EPICSV4HOME}/pvDataCPP
-PVACCESS=${EPICSV4HOME}/pvAccessCPP
-PVDATABASE=${EPICSV4HOME}/pvDatabaseCPP
-PVASRV=${EPICSV4HOME}/pvaSrv
diff --git a/arrayPerformance/configure/Makefile b/arrayPerformance/configure/Makefile
deleted file mode 100644
index 9254309..0000000
--- a/arrayPerformance/configure/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-TOP=..
-
-include $(TOP)/configure/CONFIG
-
-TARGETS = $(CONFIG_TARGETS)
-CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
-
-include $(TOP)/configure/RULES
diff --git a/arrayPerformance/configure/RELEASE b/arrayPerformance/configure/RELEASE
deleted file mode 100644
index eca1885..0000000
--- a/arrayPerformance/configure/RELEASE
+++ /dev/null
@@ -1,40 +0,0 @@
-# pvDatabaseCPP/arrayPerformance RELEASE - Location of external support modules
-#
-# IF YOU CHANGE this file or any file it includes you must
-# subsequently do a "gnumake rebuild" in the application's
-# top level directory.
-#
-# The build process does not check dependencies against files
-# that are outside this application, thus you should also do a
-# "gnumake rebuild" in the top level directory after EPICS_BASE
-# or any other external module pointed to below is rebuilt.
-#
-# Host- or target-specific settings can be given in files named
-# RELEASE.$(EPICS_HOST_ARCH).Common
-# RELEASE.Common.$(T_A)
-# RELEASE.$(EPICS_HOST_ARCH).$(T_A)
-
-# EPICS V4 Developers: Do not edit the locations in this file!
-#
-# Create a file RELEASE.local pointing to your places
-# for the dependencies, e.g.
-# PVACCESS = /path/to/epics/pvAccessCPP
-# PVDATA = /path/to/epics/pvDataCPP
-# PVCOMMON = /path/to/epics/pvCommonCPP
-# EPICS_BASE = /path/to/epics/base
-
-# If this example is built in a directory under pvDatabaseCPP,
-# use the following definitions:
-
-PVDATABASE = $(TOP)/..
--include $(TOP)/../../RELEASE.local
--include $(TOP)/../configure/RELEASE.local
-
-# If you copied this example from pvDatabaseCPP to be built as a
-# standalone TOP, define
-# PVDATABASE = /path/to/epics/pvDatabaseCPP
-# in the appropriate RELEASE[.local],
-# and use the following definitions instead:
-
-#-include $(TOP)/../RELEASE.local
-#-include $(TOP)/configure/RELEASE.local
diff --git a/arrayPerformance/configure/RULES b/arrayPerformance/configure/RULES
deleted file mode 100644
index 6d56e14..0000000
--- a/arrayPerformance/configure/RULES
+++ /dev/null
@@ -1,6 +0,0 @@
-# RULES
-
-include $(CONFIG)/RULES
-
-# Library should be rebuilt because LIBOBJS may have changed.
-$(LIBNAME): ../Makefile
diff --git a/arrayPerformance/configure/RULES.ioc b/arrayPerformance/configure/RULES.ioc
deleted file mode 100644
index 901987c..0000000
--- a/arrayPerformance/configure/RULES.ioc
+++ /dev/null
@@ -1,2 +0,0 @@
-#RULES.ioc
-include $(CONFIG)/RULES.ioc
diff --git a/arrayPerformance/configure/RULES_DIRS b/arrayPerformance/configure/RULES_DIRS
deleted file mode 100644
index 3ba269d..0000000
--- a/arrayPerformance/configure/RULES_DIRS
+++ /dev/null
@@ -1,2 +0,0 @@
-#RULES_DIRS
-include $(CONFIG)/RULES_DIRS
diff --git a/arrayPerformance/configure/RULES_TOP b/arrayPerformance/configure/RULES_TOP
deleted file mode 100644
index 2b8cbc6..0000000
--- a/arrayPerformance/configure/RULES_TOP
+++ /dev/null
@@ -1,2 +0,0 @@
-#RULES_TOP
-include $(CONFIG)/RULES_TOP
diff --git a/arrayPerformance/src/Makefile b/arrayPerformance/src/Makefile
deleted file mode 100644
index 362d0c6..0000000
--- a/arrayPerformance/src/Makefile
+++ /dev/null
@@ -1,45 +0,0 @@
-TOP = ..
-include $(TOP)/configure/CONFIG
-
-LIBRARY_IOC += pvDatabaseExample
-pvDatabaseExample_LIBS += pvDatabase pvAccess pvData Com
-pvDatabaseExample_LIBS += $(EPICS_BASE_IOC_LIBS)
-
-
-INC+= arrayPerformance.h
-LIBSRCS += arrayPerformance.cpp
-INC+= longArrayMonitor.h
-LIBSRCS += longArrayMonitor.cpp
-INC+= longArrayGet.h
-LIBSRCS += longArrayGet.cpp
-INC+= longArrayPut.h
-LIBSRCS += longArrayPut.cpp
-
-PROD_HOST += arrayPerformanceMain
-arrayPerformanceMain_SRCS += arrayPerformanceMain.cpp
-arrayPerformanceMain_LIBS += pvDatabase pvAccess pvData Com
-arrayPerformanceMain_LIBS += pvDatabaseExample
-
-PROD_HOST += longArrayMonitorMain
-longArrayMonitorMain_SRCS += longArrayMonitorMain.cpp
-longArrayMonitorMain_LIBS += pvDatabase pvAccess pvData Com
-longArrayMonitorMain_LIBS += pvDatabaseExample
-
-PROD_HOST += longArrayGetMain
-longArrayGetMain_SRCS += longArrayGetMain.cpp
-longArrayGetMain_LIBS += pvDatabase pvAccess pvData Com
-longArrayGetMain_LIBS += pvDatabaseExample
-
-PROD_HOST += longArrayPutMain
-longArrayPutMain_SRCS += longArrayPutMain.cpp
-longArrayPutMain_LIBS += pvDatabase pvAccess pvData Com
-longArrayPutMain_LIBS += pvDatabaseExample
-
-PROD_HOST += vectorPerformanceMain
-vectorPerformanceMain_SRCS += vectorPerformanceMain.cpp
-vectorPerformanceMain_LIBS += pvDatabase pvAccess pvData Com
-vectorPerformanceMain_LIBS += pvDatabaseExample
-
-
-include $(TOP)/configure/RULES
-
diff --git a/arrayPerformance/src/arrayPerformance.cpp b/arrayPerformance/src/arrayPerformance.cpp
deleted file mode 100644
index efe2e3f..0000000
--- a/arrayPerformance/src/arrayPerformance.cpp
+++ /dev/null
@@ -1,206 +0,0 @@
-/* arrayPerformance.cpp */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.08
- */
-
-#include
-
-#define epicsExportSharedSymbols
-#include
-
-
-
-namespace epics { namespace pvDatabase {
-
-using namespace epics::pvData;
-using std::tr1::static_pointer_cast;
-using std::tr1::dynamic_pointer_cast;
-using std::cout;
-using std::endl;
-using std::ostringstream;
-
-ArrayPerformancePtr ArrayPerformance::create(
- std::string const & recordName,
- size_t size,
- double delay)
-{
- epics::pvData::PVStructurePtr pvStructure =
- epics::pvData::getStandardPVField()->scalarArray(epics::pvData::pvLong,"timeStamp,alarm");
- ArrayPerformancePtr pvRecord(
- new ArrayPerformance(recordName,pvStructure,size,delay));
- if(!pvRecord->init()) pvRecord.reset();
- return pvRecord;
-}
-
-ArrayPerformance::ArrayPerformance(
- std::string const & recordName,
- epics::pvData::PVStructurePtr const & pvStructure,
- size_t size,
- double delay)
-: PVRecord(recordName,pvStructure),
- size(size),
- delay(delay),
- isDestroyed(false)
-{
- pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
-}
-
-ArrayPerformance::~ArrayPerformance()
-{
-}
-
-bool ArrayPerformance::init()
-{
-
- initPVRecord();
- PVLongArrayPtr pvLongArray = getPVStructure()->getSubField("value");
- if(!pvLongArray) return false;
- pvValue = pvLongArray;
- ArrayPerformancePtr xxx = dynamic_pointer_cast(getPtrSelf());
- arrayPerformanceThread = ArrayPerformanceThreadPtr(new ArrayPerformanceThread(xxx));
- arrayPerformanceThread->init();
- return true;
-}
-
-void ArrayPerformance::start()
-{
- arrayPerformanceThread->start();
-}
-
-void ArrayPerformance::process()
-{
- timeStamp.getCurrent();
- pvTimeStamp.set(timeStamp);
-}
-
-void ArrayPerformance::destroy()
-{
- if(isDestroyed) return;
- isDestroyed = true;
- arrayPerformanceThread->destroy();
- arrayPerformanceThread.reset();
- PVRecord::destroy();
-}
-
-ArrayPerformanceThread::ArrayPerformanceThread(ArrayPerformancePtr const & arrayPerformance)
-:
- arrayPerformance(arrayPerformance),
- isDestroyed(false),
- runReturned(false),
- threadName("arrayPerformance"),
- value(0)
-{}
-
-void ArrayPerformanceThread::init()
-{
- thread = std::auto_ptr(new epicsThread(
- *this,
- threadName.c_str(),
- epicsThreadGetStackSize(epicsThreadStackSmall),
- epicsThreadPriorityHigh));
-}
-
-void ArrayPerformanceThread::start()
-{
- thread->start();
-}
-
-void ArrayPerformanceThread::destroy()
-{
- Lock lock(mutex);
- if(isDestroyed) return;
- isDestroyed = true;
- while(true) {
- if(runReturned) break;
- lock.unlock();
- epicsThreadSleep(.01);
- lock.lock();
- }
- thread->exitWait();
- thread.reset();
- arrayPerformance.reset();
-}
-
-void ArrayPerformanceThread::run()
-{
- TimeStamp timeStamp;
- TimeStamp timeStampLast;
- timeStampLast.getCurrent();
- int nSinceLastReport = 0;
- while(true) {
- if(arrayPerformance->delay>0.0) epicsThreadSleep(arrayPerformance->delay);
- {
- Lock lock(mutex);
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- }
- timeStamp.getCurrent();
- double diff = TimeStamp::diff(timeStamp,timeStampLast);
- if(diff>=1.0) {
- ostringstream out;
- out << "arrayPerformance value " << value;
- out << " time " << diff ;
- double iterations = nSinceLastReport;
- iterations /= diff;
- if(iterations>10.0e9) {
- iterations /= 1e9;
- out << " gigaIterations/sec " << iterations;
- } else if(iterations>10.0e6) {
- iterations /= 1e6;
- out << " megaIterations/sec " << iterations;
- } else if(iterations>10.0e3) {
- iterations /= 1e3;
- out << " kiloIterations/sec " << iterations;
- } else {
- out << " Iterations/sec " << iterations;
- }
- double elementSize = arrayPerformance->size;
- double elementsPerSecond = elementSize*nSinceLastReport;
- elementsPerSecond /= diff;
- if(elementsPerSecond>10.0e9) {
- elementsPerSecond /= 1e9;
- out << " gigaElements/sec " << elementsPerSecond;
- } else if(elementsPerSecond>10.0e6) {
- elementsPerSecond /= 1e6;
- out << " megaElements/sec " << elementsPerSecond;
- } else if(elementsPerSecond>10.0e3) {
- elementsPerSecond /= 1e3;
- out << " kiloElements/sec " << elementsPerSecond;
- } else {
- out << " Elements/sec " << elementsPerSecond;
- }
- cout << out.str() << endl;
- timeStampLast = timeStamp;
- nSinceLastReport = 0;
- }
- ++nSinceLastReport;
- arrayPerformance->lock();
- try {
- if(arrayPerformance->getTraceLevel()>1) {
- cout << "arrayPerformance size " << arrayPerformance->size;
- cout << " value " << value +1 << endl;
- }
- shared_vector xxx(arrayPerformance->size,value++);
- shared_vector data(freeze(xxx));
- arrayPerformance->beginGroupPut();
- arrayPerformance->pvValue->replace(data);
- arrayPerformance->process();
- arrayPerformance->endGroupPut();
- } catch(...) {
- arrayPerformance->unlock();
- throw;
- }
- arrayPerformance->unlock();
- }
-}
-
-}}
-
diff --git a/arrayPerformance/src/arrayPerformance.h b/arrayPerformance/src/arrayPerformance.h
deleted file mode 100644
index 60e8210..0000000
--- a/arrayPerformance/src/arrayPerformance.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/* arrayPerformance.h */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.08
- */
-#ifndef ARRAYPERFORMANCE_H
-#define ARRAYPERFORMANCE_H
-
-
-#ifdef epicsExportSharedSymbols
-# define arrayperformanceEpicsExportSharedSymbols
-# undef epicsExportSharedSymbols
-#endif
-
-#include
-#include
-#include
-#include
-#include
-
-#ifdef arrayperformanceEpicsExportSharedSymbols
-# define epicsExportSharedSymbols
-# undef arrayperformanceEpicsExportSharedSymbols
-# include
-#endif
-
-namespace epics { namespace pvDatabase {
-
-class ArrayPerformance;
-typedef std::tr1::shared_ptr ArrayPerformancePtr;
-
-class ArrayPerformanceThread;
-typedef std::tr1::shared_ptr ArrayPerformanceThreadPtr;
-
-class epicsShareClass ArrayPerformance :
- public PVRecord
-{
-public:
- POINTER_DEFINITIONS(ArrayPerformance);
- static ArrayPerformancePtr create(
- std::string const & recordName,
- size_t size,
- double delay);
- virtual ~ArrayPerformance();
- virtual bool init();
- virtual void start();
- virtual void process();
- virtual void destroy();
-private:
- ArrayPerformance(std::string const & recordName,
- epics::pvData::PVStructurePtr const & pvStructure,
- size_t size,
- double delay);
- size_t size;
- double delay;
- bool isDestroyed;
- epics::pvData::PVLongArrayPtr pvValue;
- epics::pvData::PVTimeStamp pvTimeStamp;
- epics::pvData::TimeStamp timeStamp;
- ArrayPerformanceThreadPtr arrayPerformanceThread;
- friend class ArrayPerformanceThread;
-};
-
-class epicsShareClass ArrayPerformanceThread :
- public epicsThreadRunable
-{
-public:
- ArrayPerformanceThread(ArrayPerformancePtr const & arrayPerformance);
- virtual ~ArrayPerformanceThread(){};
- void init();
- void start();
- virtual void run();
- void destroy();
-private:
- ArrayPerformancePtr arrayPerformance;
- bool isDestroyed;
- bool runReturned;
- std::string threadName;
- epics::pvData::Mutex mutex;
- epics::pvData::int64 value;
- std::auto_ptr thread;
-};
-
-
-}}
-
-#endif /* ARRAYPERFORMANCE_H */
diff --git a/arrayPerformance/src/arrayPerformanceMain.cpp b/arrayPerformance/src/arrayPerformanceMain.cpp
deleted file mode 100644
index 9540a26..0000000
--- a/arrayPerformance/src/arrayPerformanceMain.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*arrayPerformanceMain.cpp */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.08
- */
-
-/* Author: Marty Kraimer */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-using namespace std;
-using std::tr1::static_pointer_cast;
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using namespace epics::pvDatabase;
-
-int main(int argc,char *argv[])
-{
- bool result(false);
- string recordName;
- recordName = "arrayPerformance";
- size_t size = 10000000;
- double delay = .0001;
- string providerName("local");
- size_t nMonitor = 1;
- int queueSize = 2;
- double waitTime = 0.0;
- if(argc==2 && string(argv[1])==string("-help")) {
- cout << "arrayPerformanceMain recordName size";
- cout << " delay providerName nMonitor queueSize waitTime" << endl;
- cout << "default" << endl;
- cout << "arrayPerformance ";
- cout << recordName << " ";
- cout << size << " ";
- cout << delay << " ";
- cout << providerName << " ";
- cout << nMonitor << " ";
- cout << queueSize << " ";
- cout << "0.0" << endl;
- return 0;
- }
- if(argc>1) recordName = argv[1];
- if(argc>2) size = strtoul(argv[2],0,0);
- if(argc>3) delay = atof(argv[3]);
- if(argc>4) providerName = argv[4];
- if(argc>5) nMonitor = strtoul(argv[5],0,0);
- if(argc>6) queueSize = strtol(argv[6],0,0);
- if(argc>7) waitTime = atof(argv[7]);
- cout << "arrayPerformance ";
- cout << recordName << " ";
- cout << size << " ";
- cout << delay << " ";
- cout << providerName << " ";
- cout << nMonitor << " ";
- cout << queueSize << " ";
- cout << waitTime << endl;
- ClientFactory::start();
- PVDatabasePtr master = PVDatabase::getMaster();
- ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
- PVRecordPtr pvRecord;
- pvRecord = ArrayPerformance::create(recordName,size,delay);
- result = master->addRecord(pvRecord);
- PVRecordPtr arrayPreformance = pvRecord;
- arrayPreformance->setTraceLevel(0);
- pvRecord = TraceRecord::create("traceRecordPGRPC");
- result = master->addRecord(pvRecord);
- if(!result) cout<< "record " << recordName << " not added" << endl;
- pvRecord.reset();
- ServerContext::shared_pointer pvaServer =
- startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
- std::vector longArrayMonitor(nMonitor);
- for(size_t i=0; istart();
- cout << "arrayPerformance\n";
- string str;
- while(true) {
- cout << "Type exit to stop: \n";
- getline(cin,str);
- if(str.compare("exit")==0) break;
-
- }
- arrayPreformance.reset();
- for(size_t i=0; istop();
- for(size_t i=0; idestroy();
- pvaServer->shutdown();
- epicsThreadSleep(1.0);
- pvaServer->destroy();
- ClientFactory::stop();
- epicsThreadSleep(1.0);
- channelProvider->destroy();
- return 0;
-}
-
diff --git a/arrayPerformance/src/longArrayGet.cpp b/arrayPerformance/src/longArrayGet.cpp
deleted file mode 100644
index 778af61..0000000
--- a/arrayPerformance/src/longArrayGet.cpp
+++ /dev/null
@@ -1,543 +0,0 @@
-/* longArrayGet.cpp */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.09
- */
-
-#include
-#include
-
-#define epicsExportSharedSymbols
-#include
-
-namespace epics { namespace pvDatabase {
-
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using std::tr1::static_pointer_cast;
-using std::tr1::dynamic_pointer_cast;
-using std::cout;
-using std::endl;
-using std::ostringstream;
-using std::string;
-
-static string requesterName("longArrayGet");
-static string request("value,timeStamp,alarm");
-static epics::pvData::Mutex printMutex;
-
-class LongArrayChannelRequester;
-typedef std::tr1::shared_ptr LongArrayChannelRequesterPtr;
-class LongArrayChannelGetRequester;
-typedef std::tr1::shared_ptr LongArrayChannelGetRequesterPtr;
-
-class LongArrayChannelRequester :
- virtual public ChannelRequester,
- public std::tr1::enable_shared_from_this
-{
-public:
- LongArrayChannelRequester(
- LongArrayChannelGetPtr const & longArrayChannelGet)
- : longArrayChannelGet(longArrayChannelGet),
- isDestroyed(false)
- {}
- virtual ~LongArrayChannelRequester(){}
- virtual void destroy()
- {
- Lock guard(mutex);
- if(isDestroyed) return;
- isDestroyed = true;
- longArrayChannelGet.reset();
- }
- virtual string getRequesterName() { return requesterName;}
- virtual void message(string const & message, MessageType messageType)
- {
- Lock guard(printMutex);
- cout << requesterName << " message " << message << endl;
- }
- virtual void channelCreated(
- const Status& status,
- Channel::shared_pointer const & channel);
- virtual void channelStateChange(
- Channel::shared_pointer const & channel,
- Channel::ConnectionState connectionState);
-private:
- LongArrayChannelRequesterPtr getPtrSelf()
- {
- return shared_from_this();
- }
- LongArrayChannelGetPtr longArrayChannelGet;
- bool isDestroyed;
- Mutex mutex;
-};
-
-
-class LongArrayChannelGetRequester :
- virtual public ChannelGetRequester,
- public std::tr1::enable_shared_from_this
-{
-public:
- LongArrayChannelGetRequester(
- LongArrayChannelGetPtr const & longArrayChannelGet)
- : longArrayChannelGet(longArrayChannelGet),
- isDestroyed(false)
- {}
- virtual ~LongArrayChannelGetRequester(){}
- virtual void destroy()
- {
- Lock guard(mutex);
- if(isDestroyed) return;
- isDestroyed = true;
- longArrayChannelGet.reset();
- }
- virtual string getRequesterName() { return requesterName;}
- virtual void message(string const & message, MessageType messageType)
- {
- Lock guard(printMutex);
- cout << requesterName << " message " << message << endl;
- }
- virtual void channelGetConnect(
- Status const & status,
- ChannelGet::shared_pointer const & channelGet,
- StructureConstPtr const &structure);
- virtual void getDone(
- Status const & status,
- ChannelGet::shared_pointer const & channelGet,
- PVStructurePtr const &pvStructure,
- BitSetPtr const & bitSet);
-private:
- LongArrayChannelGetRequesterPtr getPtrSelf()
- {
- return shared_from_this();
- }
- LongArrayChannelGetPtr longArrayChannelGet;
- bool isDestroyed;
- Mutex mutex;
-};
-
-
-
-class LongArrayChannelGet :
- public std::tr1::enable_shared_from_this,
- public epicsThreadRunable
-{
-public:
- LongArrayChannelGet(
- string providerName,
- string channelName,
- int iterBetweenCreateChannel,
- int iterBetweenCreateChannelGet,
- double delayTime)
- : providerName(providerName),
- channelName(channelName),
- iterBetweenCreateChannel(iterBetweenCreateChannel),
- iterBetweenCreateChannelGet(iterBetweenCreateChannelGet),
- delayTime(delayTime),
- isDestroyed(false),
- runReturned(false),
- threadName("longArrayGet")
- {}
- virtual ~LongArrayChannelGet(){}
- bool init();
- virtual void destroy();
- virtual void run();
- void message(string const & message, MessageType messageType)
- {
- Lock guard(printMutex);
- cout << requesterName << " message " << message << endl;
- }
- virtual void channelCreated(
- const Status& status,
- Channel::shared_pointer const & channel);
- virtual void channelStateChange(
- Channel::shared_pointer const & channel,
- Channel::ConnectionState connectionState);
- virtual void channelGetConnect(
- Status const & status,
- ChannelGet::shared_pointer const & channelGet,
- StructureConstPtr const &structure);
- virtual void getDone(
- Status const & status,
- ChannelGet::shared_pointer channelGet,
- PVStructurePtr const &pvStructure,
- BitSetPtr const & bitSet);
-private:
- LongArrayChannelGetPtr getPtrSelf()
- {
- return shared_from_this();
- }
- size_t checkResult();
- string providerName;
- string channelName;
- int iterBetweenCreateChannel;
- int iterBetweenCreateChannelGet;
- double delayTime;
- bool isDestroyed;
- bool runReturned;
- std::string threadName;
- Status status;
- Event event;
- Mutex mutex;
- std::auto_ptr thread;
- Channel::shared_pointer channel;
- ChannelGet::shared_pointer channelGet;
- PVStructurePtr pvStructure;
- BitSetPtr bitSet;
- LongArrayChannelRequesterPtr longArrayChannelRequester;
- LongArrayChannelGetRequesterPtr longArrayChannelGetRequester;
-};
-
-void LongArrayChannelRequester::channelCreated(
- const Status& status,
- Channel::shared_pointer const & channel)
-{
- Lock guard(mutex);
- if(isDestroyed) return;
- longArrayChannelGet->channelCreated(status,channel);
-}
-
-void LongArrayChannelRequester::channelStateChange(
- Channel::shared_pointer const & channel,
- Channel::ConnectionState connectionState)
-{
- string mess(Channel::ConnectionStateNames[connectionState]);
- message(mess,infoMessage);
- Lock guard(mutex);
- if(isDestroyed) return;
- longArrayChannelGet->channelStateChange(channel,connectionState);
-}
-
-void LongArrayChannelGetRequester::channelGetConnect(
- Status const & status,
- ChannelGet::shared_pointer const & channelGet,
- StructureConstPtr const &structure)
-{
- Lock guard(mutex);
- if(isDestroyed) return;
- longArrayChannelGet->channelGetConnect(
- status,channelGet,structure);
-}
-
-void LongArrayChannelGetRequester::getDone(
- Status const & status,
- ChannelGet::shared_pointer const & channelGet,
- PVStructurePtr const &pvStructure,
- BitSetPtr const & bitSet)
-{
- Lock guard(mutex);
- if(isDestroyed) return;
- longArrayChannelGet->getDone(status,channelGet,pvStructure,bitSet);
-}
-
-void LongArrayChannelGet::channelCreated(
- const Status& status,
- Channel::shared_pointer const & channel)
-{
- if(!status.isOK()) message(status.getMessage(),errorMessage);
- this->status = status;
- this->channel = channel;
- event.signal();
-}
-
-void LongArrayChannelGet::channelStateChange(
- Channel::shared_pointer const & channel,
- Channel::ConnectionState connectionState)
-{
- MessageType messageType =
- (connectionState==Channel::CONNECTED ? infoMessage : errorMessage);
- message("channelStateChange",messageType);
-}
-void LongArrayChannelGet::channelGetConnect(
- Status const & status,
- ChannelGet::shared_pointer const & channelGet,
- StructureConstPtr const &structure)
-{
- this->status = status;
- if(!status.isOK()) {
- message(status.getMessage(),errorMessage);
- event.signal();
- return;
- }
- this->channelGet = channelGet;
- bool structureOK(true);
- PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(structure);
- PVFieldPtr pvField = pvStructure->getSubField("timeStamp");
- if(!pvField) structureOK = false;
- pvField = pvStructure->getSubField("value");
- if(!pvField) {
- structureOK = false;
- } else {
- FieldConstPtr field = pvField->getField();
- if(field->getType()!=scalarArray) {
- structureOK = false;
- } else {
- ScalarArrayConstPtr scalarArray = dynamic_pointer_cast(field);
- if(scalarArray->getElementType()!=pvLong) structureOK = false;
- }
- }
- if(!structureOK) {
- string mess("channelGetConnect: illegal structure");
- message(mess,errorMessage);
- this->status = Status(Status::STATUSTYPE_ERROR,mess);
- }
- event.signal();
-}
-
-
-bool LongArrayChannelGet::init()
-{
- ChannelProvider::shared_pointer channelProvider =
- getChannelProviderRegistry()->getProvider(providerName);
- if(!channelProvider) {
- cout << "provider " << providerName << " not found" << endl;
- return false;
- }
- longArrayChannelRequester.reset(new LongArrayChannelRequester(getPtrSelf()));
- channel = channelProvider->createChannel(
- channelName,
- longArrayChannelRequester);
- event.wait();
- channelProvider.reset();
- if(!status.isOK()) return false;
- CreateRequest::shared_pointer createRequest = CreateRequest::create();
- PVStructurePtr pvRequest = createRequest->createRequest(request);
- if(!pvRequest) {
- cout << "request logic error " << createRequest->getMessage() << endl;
- return false;
- }
- longArrayChannelGetRequester.reset(new LongArrayChannelGetRequester(getPtrSelf()));
- channelGet = channel->createChannelGet(
- longArrayChannelGetRequester,
- pvRequest);
- event.wait();
- if(!status.isOK()) return false;
- thread = std::auto_ptr(new epicsThread(
- *this,
- threadName.c_str(),
- epicsThreadGetStackSize(epicsThreadStackSmall),
- epicsThreadPriorityLow));
- thread->start();
- event.signal();
- return true;
-}
-
-void LongArrayChannelGet::destroy()
-{
- if(isDestroyed) return;
- isDestroyed = true;
- event.signal();
- while(true) {
- if(runReturned) break;
- epicsThreadSleep(.01);
- }
- if(longArrayChannelRequester) {
- longArrayChannelRequester->destroy();
- }
- if(longArrayChannelGetRequester) {
- longArrayChannelGetRequester->destroy();
- }
- thread->exitWait();
- channel->destroy();
- channelGet.reset();
- channel.reset();
-}
-
-
-void LongArrayChannelGet::run()
-{
- while(true) {
- event.wait();
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- TimeStamp timeStamp;
- TimeStamp timeStampLast;
- timeStampLast.getCurrent();
- int numChannelGet = 0;
- int numChannelCreate = 0;
- size_t nElements = 0;
- while(true) {
- channelGet->get();
- event.wait();
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- size_t latestSize = checkResult();
- nElements += latestSize;
- timeStamp.getCurrent();
- double diff = TimeStamp::diff(timeStamp,timeStampLast);
- if(diff>=1.0) {
- ostringstream out;
- out << "get";
- double elementsPerSec = nElements;
- elementsPerSec /= diff;
- if(elementsPerSec>10.0e9) {
- elementsPerSec /= 1e9;
- out << " gigaElements/sec " << elementsPerSec;
- } else if(elementsPerSec>10.0e6) {
- elementsPerSec /= 1e6;
- out << " megaElements/sec " << elementsPerSec;
- } else if(elementsPerSec>10.0e3) {
- elementsPerSec /= 1e3;
- out << " kiloElements/sec " << elementsPerSec;
- } else {
- out << " Elements/sec " << elementsPerSec;
- }
- cout << out.str() << endl;
- timeStampLast = timeStamp;
- nElements = 0;
- }
- if(delayTime>0.0) epicsThreadSleep(delayTime);
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- ++numChannelCreate;
- bool createGet = false;
- if(iterBetweenCreateChannel!=0) {
- if(numChannelCreate>=iterBetweenCreateChannel) {
- longArrayChannelRequester->destroy();
- channel->destroy();
- ChannelProvider::shared_pointer channelProvider =
- getChannelProviderRegistry()->getProvider(providerName);
- longArrayChannelRequester.reset(new LongArrayChannelRequester(getPtrSelf()));
- channel = channelProvider->createChannel(
- channelName,
- longArrayChannelRequester);
- event.wait();
- channelProvider.reset();
- if(!status.isOK()) {
- message(status.getMessage(),errorMessage);
- return;
- }
- cout<< "createChannel success" << endl;
- createGet = true;
- numChannelCreate = 0;
- }
- }
- ++numChannelGet;
- if(iterBetweenCreateChannelGet!=0) {
- if(numChannelGet>=iterBetweenCreateChannelGet) createGet = true;
- }
- if(createGet) {
- numChannelGet = 0;
- longArrayChannelGetRequester->destroy();
- channelGet->destroy();
- CreateRequest::shared_pointer createRequest =
- CreateRequest::create();
- PVStructurePtr pvRequest =
- createRequest->createRequest(request);
- if(!pvRequest) {
- cout << "request logic error " << createRequest->getMessage() << endl;
- return ;
- }
- longArrayChannelGetRequester.reset(new LongArrayChannelGetRequester(getPtrSelf()));
- channelGet = channel->createChannelGet(
- longArrayChannelGetRequester,
- pvRequest);
- event.wait();
- if(!status.isOK()) {
- message(status.getMessage(),errorMessage);
- return;
- }
- cout<< "createChannelGet success" << endl;
- }
- }
- }
-}
-
-void LongArrayChannelGet::getDone(
- Status const & status,
- ChannelGet::shared_pointer channelGet,
- PVStructurePtr const &pvStructure,
- BitSetPtr const & bitSet)
-{
- this->pvStructure = pvStructure;
- this->bitSet = bitSet;
- event.signal();
-}
-
-size_t LongArrayChannelGet::checkResult()
-{
- PVLongArrayPtr pvValue;
- if(!status.isOK()) {
- message(status.getMessage(),errorMessage);
- return 0;
- }
- pvValue = dynamic_pointer_cast(pvStructure->getSubField("value"));
- if(!bitSet->get(pvValue->getFieldOffset())) {
- return 0;
- }
- bitSet->clear();
- shared_vector data = pvValue->view();
- if(data.size()>0) {
- int64 first = data[0];
- int64 last = data[data.size()-1];
- if(first!=last) {
- cout << "error first=" << first << " last=" << last << endl;
- }
- }
- return data.size();
-}
-
-
-LongArrayGetPtr LongArrayGet::create(
- string const &providerName,
- string const & channelName,
- int iterBetweenCreateChannel,
- int iterBetweenCreateChannelGet,
- double delayTime)
-{
- LongArrayGetPtr longArrayGet(
- new LongArrayGet(
- providerName,
- channelName,
- iterBetweenCreateChannel,
- iterBetweenCreateChannelGet,
- delayTime));
- if(!longArrayGet->init()) longArrayGet.reset();
- return longArrayGet;
-}
-
-LongArrayGet::LongArrayGet(
- string const &providerName,
- string const & channelName,
- int iterBetweenCreateChannel,
- int iterBetweenCreateChannelGet,
- double delayTime)
-: providerName(providerName),
- channelName(channelName),
- iterBetweenCreateChannel(iterBetweenCreateChannel),
- iterBetweenCreateChannelGet(iterBetweenCreateChannelGet),
- delayTime(delayTime)
-{}
-
-
-LongArrayGet::~LongArrayGet() {}
-
-bool LongArrayGet::init()
-{
- longArrayChannelGet = LongArrayChannelGetPtr(new LongArrayChannelGet(
- providerName,
- channelName,
- iterBetweenCreateChannel,
- iterBetweenCreateChannelGet,
- delayTime));
- return longArrayChannelGet->init();
-}
-
-void LongArrayGet::destroy()
-{
- longArrayChannelGet->destroy();
- longArrayChannelGet.reset();
-}
-
-}}
-
-
diff --git a/arrayPerformance/src/longArrayGet.h b/arrayPerformance/src/longArrayGet.h
deleted file mode 100644
index 85b00be..0000000
--- a/arrayPerformance/src/longArrayGet.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* longArrayGet.h */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.09
- */
-#ifndef LONGARRAYGET_H
-#define LONGARRAYGET_H
-
-
-#ifdef epicsExportSharedSymbols
-# define longarraygetEpicsExportSharedSymbols
-# undef epicsExportSharedSymbols
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#ifdef longarraygetEpicsExportSharedSymbols
-# define epicsExportSharedSymbols
-# undef longarraygetEpicsExportSharedSymbols
-# include
-#endif
-
-namespace epics { namespace pvDatabase {
-
-
-class LongArrayGet;
-typedef std::tr1::shared_ptr LongArrayGetPtr;
-
-
-class LongArrayChannelGet;
-typedef std::tr1::shared_ptr LongArrayChannelGetPtr;
-
-class epicsShareClass LongArrayGet :
- public std::tr1::enable_shared_from_this
-{
-public:
- POINTER_DEFINITIONS(LongArrayGet);
- static LongArrayGetPtr create(
- std::string const & providerName,
- std::string const & channelName,
- int iterBetweenCreateChannel = 0,
- int iterBetweenCreateChannelGet = 0,
- double delayTime = 0.0);
- ~LongArrayGet();
- void destroy();
-private:
- LongArrayGetPtr getPtrSelf()
- {
- return shared_from_this();
- }
- LongArrayGet(
- std::string const & providerName,
- std::string const & channelName,
- int iterBetweenCreateChannel = 0,
- int iterBetweenCreateChannelGet = 0,
- double delayTime = 0.0);
- bool init();
-
- std::string providerName;
- std::string channelName;
- int iterBetweenCreateChannel;
- int iterBetweenCreateChannelGet;
- double delayTime;
- LongArrayChannelGetPtr longArrayChannelGet;
-};
-
-
-}}
-
-#endif /* LONGARRAYGET_H */
diff --git a/arrayPerformance/src/longArrayGetMain.cpp b/arrayPerformance/src/longArrayGetMain.cpp
deleted file mode 100644
index 39b41bb..0000000
--- a/arrayPerformance/src/longArrayGetMain.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*longArrayGetMain.cpp */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.10
- */
-
-/* Author: Marty Kraimer */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-using namespace std;
-using std::tr1::static_pointer_cast;
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using namespace epics::pvDatabase;
-
-int main(int argc,char *argv[])
-{
- string channelName("arrayPerformance");
- int iterBetweenCreateChannel = 0;
- int iterBetweenCreateChannelGet = 0;
- double delayTime = 1.0;
- if(argc==2 && string(argv[1])==string("-help")) {
- cout << "longArrayGetMain channelName ";
- cout << "iterBetweenCreateChannel iterBetweenCreateChannelGet delayTime" << endl;
- cout << "default" << endl;
- cout << "longArrayGetMain " << channelName << " ";
- cout << iterBetweenCreateChannel << " ";
- cout << iterBetweenCreateChannelGet << " ";
- cout << delayTime << endl;
- return 0;
- }
- ClientFactory::start();
- if(argc>1) channelName = argv[1];
- if(argc>2) iterBetweenCreateChannel = strtol(argv[2],0,0);
- if(argc>3) iterBetweenCreateChannelGet = strtol(argv[3],0,0);
- if(argc>4) delayTime = atof(argv[4]);
- cout << "longArrayGetMain " << channelName << " ";
- cout << iterBetweenCreateChannel << " ";
- cout << iterBetweenCreateChannelGet << " ";
- cout << delayTime << endl;
- LongArrayGetPtr longArrayGet
- = LongArrayGet::create(
- "pvAccess",
- channelName,
- iterBetweenCreateChannel,
- iterBetweenCreateChannelGet,
- delayTime);
- cout << "longArrayGet\n";
- string str;
- while(true) {
- cout << "Type exit to stop: \n";
- getline(cin,str);
- if(str.compare("exit")==0) break;
-
- }
- longArrayGet->destroy();
- longArrayGet.reset();
- double xxx = 1.0;
- if(xxx
-#include
-
-#define epicsExportSharedSymbols
-#include
-
-
-namespace epics { namespace pvDatabase {
-
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using std::tr1::static_pointer_cast;
-using std::tr1::dynamic_pointer_cast;
-using std::cout;
-using std::endl;
-using std::string;
-using std::ostringstream;
-
-static string requesterName("longArrayMonitor");
-
-static void messagePvt(string const & message, MessageType messageType)
-{
- cout << requesterName << " message " << message << endl;
-}
-
-class LAMChannelRequester :
- public ChannelRequester
-{
-public:
- LAMChannelRequester(LongArrayMonitorPtr const &longArrayMonitor)
- : longArrayMonitor(longArrayMonitor)
- {}
- virtual ~LAMChannelRequester(){}
- virtual void destroy(){longArrayMonitor.reset();}
- virtual string getRequesterName() { return requesterName;}
- virtual void message(string const & message, MessageType messageType)
- { messagePvt(message,messageType);}
- virtual void channelCreated(const Status& status, Channel::shared_pointer const & channel);
- virtual void channelStateChange(Channel::shared_pointer const & channel, Channel::ConnectionState connectionState);
-private:
- LongArrayMonitorPtr longArrayMonitor;
-};
-
-void LAMChannelRequester::channelCreated(const Status& status, Channel::shared_pointer const & channel)
-{
- if(!status.isOK()) messagePvt(status.getMessage(),errorMessage);
- longArrayMonitor->status = status;
- longArrayMonitor->channel = channel;
- longArrayMonitor->event.signal();
-}
-
-void LAMChannelRequester::channelStateChange(Channel::shared_pointer const & channel, Channel::ConnectionState connectionState)
-{
- MessageType messageType = (connectionState==Channel::CONNECTED ? infoMessage : errorMessage);
- messagePvt("channelStateChange",messageType);
-}
-
-
-class LAMMonitorRequester :
- public MonitorRequester,
- public epicsThreadRunable
-{
-public:
- LAMMonitorRequester(LongArrayMonitorPtr const &longArrayMonitor,double waitTime)
- : longArrayMonitor(longArrayMonitor),
- waitTime(waitTime),
- isDestroyed(false),
- runReturned(false),
- threadName("longArrayMonitor")
- {}
- virtual ~LAMMonitorRequester(){}
- void init();
- virtual void destroy();
- virtual void run();
- virtual string getRequesterName() { return requesterName;}
- virtual void message(string const & message, MessageType messageType)
- { messagePvt(message,messageType);}
- virtual void monitorConnect(Status const & status,
- MonitorPtr const & monitor, StructureConstPtr const & structure);
- virtual void monitorEvent(MonitorPtr const & monitor);
- virtual void unlisten(MonitorPtr const & monitor);
-private:
- LongArrayMonitorPtr longArrayMonitor;
- double waitTime;
- bool isDestroyed;
- bool runReturned;
- std::string threadName;
- Event event;
- Mutex mutex;
- std::auto_ptr thread;
-};
-
-void LAMMonitorRequester::init()
-{
- thread = std::auto_ptr(new epicsThread(
- *this,
- threadName.c_str(),
- epicsThreadGetStackSize(epicsThreadStackSmall),
- epicsThreadPriorityLow));
- thread->start();
-}
-
-void LAMMonitorRequester::destroy()
-{
- if(isDestroyed) return;
- isDestroyed = true;
- event.signal();
- while(true) {
- if(runReturned) break;
- epicsThreadSleep(.01);
- }
- thread->exitWait();
- longArrayMonitor.reset();
-}
-
-
-void LAMMonitorRequester::monitorConnect(Status const & status,
- MonitorPtr const & monitor, StructureConstPtr const & structure)
-{
- longArrayMonitor->status = status;
- longArrayMonitor->monitor = monitor;
- if(!status.isOK()) {
- messagePvt(status.getMessage(),errorMessage);
- longArrayMonitor->event.signal();
- return;
- }
- bool structureOK(true);
- FieldConstPtr field = structure->getField("timeStamp");
- if(!field) structureOK = false;
- field = structure->getField("value");
- if(!field) {
- structureOK = false;
- } else {
- if(field->getType()!=scalarArray) {
- structureOK = false;
- } else {
- ScalarArrayConstPtr scalarArray = dynamic_pointer_cast(field);
- if(scalarArray->getElementType()!=pvLong) structureOK = false;
- }
- }
- if(!structureOK) {
- string message("monitorConnect: illegal structure");
- messagePvt(message,errorMessage);
- longArrayMonitor->status = Status(Status::STATUSTYPE_ERROR,message);
- }
- longArrayMonitor->event.signal();
-}
-
-void LAMMonitorRequester::run()
-{
- PVLongArrayPtr pvValue;
- PVTimeStamp pvTimeStamp;
- TimeStamp timeStamp;
- TimeStamp timeStampLast;
- timeStampLast.getCurrent();
- size_t nElements = 0;
- int nSinceLastReport = 0;
- while(true) {
- event.wait();
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- while(true) {
- MonitorElementPtr monitorElement;
- PVStructurePtr pvStructure;
- {
- Lock xx(mutex);
- monitorElement = longArrayMonitor->monitor->poll();
- if(monitorElement) pvStructure = monitorElement->pvStructurePtr;
- }
- if(!monitorElement) break;
- if(waitTime>0.0) epicsThreadSleep(waitTime);
- pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
- pvTimeStamp.get(timeStamp);
- pvValue = dynamic_pointer_cast(pvStructure->getSubField("value"));
- shared_vector data = pvValue->view();
- if(data.size()>0) {
- nElements += data.size();
- int64 first = data[0];
- int64 last = data[data.size()-1];
- if(first!=last) {
- cout << "error first=" << first << " last=" << last << endl;
- }
- double diff = TimeStamp::diff(timeStamp,timeStampLast);
- if(diff>=1.0) {
- ostringstream out;
- out << " monitors/sec " << nSinceLastReport << " ";
- out << "first " << first << " last " << last ;
- BitSetPtr changed = monitorElement->changedBitSet;
- BitSetPtr overrun = monitorElement->overrunBitSet;
- out << " changed " << *changed;
- out << " overrun " << *overrun;
- double elementsPerSec = nElements;
- elementsPerSec /= diff;
- if(elementsPerSec>10.0e9) {
- elementsPerSec /= 1e9;
- out << " gigaElements/sec " << elementsPerSec;
- } else if(elementsPerSec>10.0e6) {
- elementsPerSec /= 1e6;
- out << " megaElements/sec " << elementsPerSec;
- } else if(elementsPerSec>10.0e3) {
- elementsPerSec /= 1e3;
- out << " kiloElements/sec " << elementsPerSec;
- } else {
- out << " Elements/sec " << elementsPerSec;
- }
- cout << out.str() << endl;
- timeStampLast = timeStamp;
- nSinceLastReport = 0;
- nElements = 0;
- }
- ++nSinceLastReport;
- } else {
- cout << "size = 0" << endl;
- }
- longArrayMonitor->monitor->release(monitorElement);
- }
- }
-}
-
-void LAMMonitorRequester::monitorEvent(MonitorPtr const & monitor)
-{
- event.signal();
-}
-
-void LAMMonitorRequester::unlisten(MonitorPtr const & monitor)
-{
- messagePvt("unlisten called",errorMessage);
-}
-
-
-LongArrayMonitorPtr LongArrayMonitor::create(
- string const &providerName,
- string const & channelName,
- int queueSize,
- double waitTime)
-{
- LongArrayMonitorPtr longArrayMonitor(new LongArrayMonitor());
- if(!longArrayMonitor->init(providerName,channelName,queueSize,waitTime)) longArrayMonitor.reset();
- return longArrayMonitor;
-}
-
-LongArrayMonitor::LongArrayMonitor() {}
-
-LongArrayMonitor::~LongArrayMonitor() {}
-
-bool LongArrayMonitor::init(
- string const &providerName,
- string const &channelName,
- int queueSize,
- double waitTime)
-{
- channelRequester = LAMChannelRequesterPtr(new LAMChannelRequester(getPtrSelf()));
- monitorRequester = LAMMonitorRequesterPtr(new LAMMonitorRequester(getPtrSelf(),waitTime));
- monitorRequester->init();
- ChannelProvider::shared_pointer channelProvider =
- getChannelProviderRegistry()->getProvider(providerName);
- if(!channelProvider) {
- cout << "provider " << providerName << " not found" << endl;
- return false;
- }
- channel = channelProvider->createChannel(channelName,channelRequester,0);
- event.wait();
- if(!status.isOK()) return false;
- string request("record[queueSize=");
- char buff[20];
- sprintf(buff,"%d",queueSize);
- request += buff;
- request += "]field(value,timeStamp,alarm)";
- CreateRequest::shared_pointer createRequest = CreateRequest::create();
- PVStructurePtr pvRequest = createRequest->createRequest(request);
- if(!pvRequest) {
- cout << "request logic error " << createRequest->getMessage() << endl;
- return false;
- }
- monitor = channel->createMonitor(monitorRequester,pvRequest);
- event.wait();
- if(!status.isOK()) return false;
- return true;
-}
-
-void LongArrayMonitor::start()
-{
- monitor->start();
-}
-
-void LongArrayMonitor::stop()
-{
- monitor->stop();
-}
-
-void LongArrayMonitor::destroy()
-{
- monitorRequester->destroy();
- monitorRequester.reset();
- monitor->destroy();
- monitor.reset();
- channel->destroy();
- channel.reset();
- channelRequester->destroy();
- channelRequester.reset();
-}
-
-}}
-
-
diff --git a/arrayPerformance/src/longArrayMonitor.h b/arrayPerformance/src/longArrayMonitor.h
deleted file mode 100644
index c84d31f..0000000
--- a/arrayPerformance/src/longArrayMonitor.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* longArrayMonitor.h */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.09
- */
-#ifndef LONGARRAYMONITOR_H
-#define LONGARRAYMONITOR_H
-
-#ifdef epicsExportSharedSymbols
-# define longarraymonitorEpicsExportSharedSymbols
-# undef epicsExportSharedSymbols
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#ifdef longarraymonitorEpicsExportSharedSymbols
-# define epicsExportSharedSymbols
-# undef longarraymonitorEpicsExportSharedSymbols
-# include
-#endif
-
-
-namespace epics { namespace pvDatabase {
-
-
-class LongArrayMonitor;
-typedef std::tr1::shared_ptr LongArrayMonitorPtr;
-
-class LAMChannelRequester;
-typedef std::tr1::shared_ptr LAMChannelRequesterPtr;
-
-class LAMMonitorRequester;
-typedef std::tr1::shared_ptr LAMMonitorRequesterPtr;
-
-class epicsShareClass LongArrayMonitor :
- public std::tr1::enable_shared_from_this
-{
-public:
- POINTER_DEFINITIONS(LongArrayMonitor);
- static LongArrayMonitorPtr create(
- std::string const & providerName,
- std::string const & channelName,
- int queueSize = 1,
- double waitTime = 0.0);
- ~LongArrayMonitor();
- void start();
- void stop();
- void destroy();
-private:
- static epics::pvData::Mutex printMutex;
- bool init(
- std::string const & providerName,
- std::string const & channelName,
- int queueSize,
- double waitTime);
- LongArrayMonitorPtr getPtrSelf()
- {
- return shared_from_this();
- }
- LongArrayMonitor();
-
- LAMChannelRequesterPtr channelRequester;
- LAMMonitorRequesterPtr monitorRequester;
- epics::pvAccess::Channel::shared_pointer channel;
- epics::pvData::Monitor::shared_pointer monitor;
- epics::pvData::Event event;
- epics::pvData::Status status;
- friend class LAMChannelRequester;
- friend class LAMMonitorRequester;
-};
-
-
-}}
-
-#endif /* LONGARRAYMONITOR_H */
diff --git a/arrayPerformance/src/longArrayMonitorMain.cpp b/arrayPerformance/src/longArrayMonitorMain.cpp
deleted file mode 100644
index 74a041f..0000000
--- a/arrayPerformance/src/longArrayMonitorMain.cpp
+++ /dev/null
@@ -1,76 +0,0 @@
-/*longArrayMonitorMain.cpp */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.10
- */
-
-/* Author: Marty Kraimer */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-using namespace std;
-using std::tr1::static_pointer_cast;
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using namespace epics::pvDatabase;
-
-int main(int argc,char *argv[])
-{
- string channelName("arrayPerformance");
- int queueSize = 2;
- double waitTime = 0.0;
- if(argc==2 && string(argv[1])==string("-help")) {
- cout << "longArrayMonitorMain channelName queueSize waitTime" << endl;
- cout << "default" << endl;
- cout << "longArrayMonitorMain " << channelName << " ";
- cout << queueSize << " ";
- cout << "0.0" << endl;
- return 0;
- }
- ClientFactory::start();
- if(argc>1) channelName = argv[1];
- if(argc>2) queueSize = strtol(argv[2],0,0);
- if(argc>3) waitTime = atof(argv[3]);
- cout << "longArrayMonitorMain " << channelName << " ";
- cout << queueSize << " ";
- cout << waitTime << endl;
- LongArrayMonitorPtr longArrayMonitor
- = LongArrayMonitor::create("pvAccess",channelName,queueSize,waitTime);
- longArrayMonitor->start();
- cout << "longArrayMonitor\n";
- string str;
- while(true) {
- cout << "Type exit to stop: \n";
- getline(cin,str);
- if(str.compare("exit")==0) break;
-
- }
- longArrayMonitor->destroy();
- longArrayMonitor.reset();
- ClientFactory::stop();
- epicsThreadSleep(1.0);
- return 0;
-}
-
diff --git a/arrayPerformance/src/longArrayPut.cpp b/arrayPerformance/src/longArrayPut.cpp
deleted file mode 100644
index 4aca1bb..0000000
--- a/arrayPerformance/src/longArrayPut.cpp
+++ /dev/null
@@ -1,383 +0,0 @@
-/* longArrayPut.cpp */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.09
- */
-
-#include
-#include
-
-#define epicsExportSharedSymbols
-#include
-
-namespace epics { namespace pvDatabase {
-
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using std::tr1::static_pointer_cast;
-using std::tr1::dynamic_pointer_cast;
-using std::cout;
-using std::endl;
-using std::ostringstream;
-using std::string;
-
-static string requesterName("longArrayPut");
-static string request("value");
-static epics::pvData::Mutex printMutex;
-
-class LongArrayChannelPut :
- virtual public ChannelRequester,
- virtual public ChannelPutRequester,
- public std::tr1::enable_shared_from_this,
- public epicsThreadRunable
-{
-public:
- LongArrayChannelPut(
- string providerName,
- string channelName,
- size_t arraySize,
- int iterBetweenCreateChannel,
- int iterBetweenCreateChannelPut,
- double delayTime)
- : providerName(providerName),
- channelName(channelName),
- arraySize(arraySize),
- iterBetweenCreateChannel(iterBetweenCreateChannel),
- iterBetweenCreateChannelPut(iterBetweenCreateChannelPut),
- delayTime(delayTime),
- isDestroyed(false),
- runReturned(false),
- threadName("longArrayPut")
- {}
- virtual ~LongArrayChannelPut(){}
- bool init();
- virtual void destroy();
- virtual void run();
- virtual string getRequesterName() { return requesterName;}
- virtual void message(string const & message, MessageType messageType)
- {
- Lock guard(printMutex);
- cout << requesterName << " message " << message << endl;
- }
- virtual void channelCreated(
- const Status& status,
- Channel::shared_pointer const & channel);
- virtual void channelStateChange(
- Channel::shared_pointer const & channel,
- Channel::ConnectionState connectionState);
- virtual void channelPutConnect(
- Status const & status,
- ChannelPut::shared_pointer const & channelPut,
- StructureConstPtr const &structure);
- virtual void putDone(
- Status const & status,
- ChannelPut::shared_pointer const & channelPut);
- virtual void getDone(
- Status const & status,
- ChannelPut::shared_pointer const & channelPut,
- PVStructurePtr const &pvStructure,
- BitSetPtr const & bitSet){}
-private:
- LongArrayChannelPutPtr getPtrSelf()
- {
- return shared_from_this();
- }
- string providerName;
- string channelName;
- size_t arraySize;
- int iterBetweenCreateChannel;
- int iterBetweenCreateChannelPut;
- double delayTime;
- bool isDestroyed;
- bool runReturned;
- std::string threadName;
- Status status;
- Event event;
- Mutex mutex;
- std::auto_ptr thread;
- Channel::shared_pointer channel;
- ChannelPut::shared_pointer channelPut;
- PVStructurePtr pvStructure;
- PVLongArrayPtr pvLongArray;
- BitSetPtr bitSet;
-};
-
-bool LongArrayChannelPut::init()
-{
- ChannelProvider::shared_pointer channelProvider = getChannelProviderRegistry()->getProvider(providerName);
- if(!channelProvider) {
- cout << "provider " << providerName << " not found" << endl;
- return false;
- }
- channel = channelProvider->createChannel(channelName,getPtrSelf(),0);
- event.wait();
- if(!status.isOK()) return false;
- CreateRequest::shared_pointer createRequest = CreateRequest::create();
- PVStructurePtr pvRequest = createRequest->createRequest(request);
- if(!pvRequest) {
- cout << "request logic error " << createRequest->getMessage() << endl;
- return false;
- }
- channelPut = channel->createChannelPut(getPtrSelf(),pvRequest);
- event.wait();
- if(!status.isOK()) return false;
- thread = std::auto_ptr(new epicsThread(
- *this,
- threadName.c_str(),
- epicsThreadGetStackSize(epicsThreadStackSmall),
- epicsThreadPriorityLow));
- thread->start();
- event.signal();
- return true;
-}
-
-void LongArrayChannelPut::destroy()
-{
- if(isDestroyed) return;
- isDestroyed = true;
- event.signal();
- while(true) {
- if(runReturned) break;
- epicsThreadSleep(.01);
- }
- thread->exitWait();
- channel->destroy();
- channelPut.reset();
- channel.reset();
-}
-
-void LongArrayChannelPut::channelCreated(
- const Status& status,
- Channel::shared_pointer const & channel)
-{
- if(!status.isOK()) message(status.getMessage(),errorMessage);
- this->status = status;
- this->channel = channel;
- event.signal();
-}
-
-void LongArrayChannelPut::channelStateChange(
- Channel::shared_pointer const & channel,
- Channel::ConnectionState connectionState)
-{
- MessageType messageType =
- (connectionState==Channel::CONNECTED ? infoMessage : errorMessage);
- message("channelStateChange",messageType);
-}
-
-
-void LongArrayChannelPut::channelPutConnect(
- Status const & status,
- ChannelPut::shared_pointer const & channelPut,
- StructureConstPtr const &structure)
-{
- this->status = status;
- if(!status.isOK()) {
- message(status.getMessage(),errorMessage);
- event.signal();
- return;
- }
- this->channelPut = channelPut;
- pvStructure = getPVDataCreate()->createPVStructure(structure);
- bitSet = BitSetPtr(new BitSet(pvStructure->getNumberFields()));
- bool structureOK(true);
- PVFieldPtr pvField = pvStructure->getSubField("value");
- if(!pvField) {
- structureOK = false;
- } else {
- FieldConstPtr field = pvField->getField();
- if(field->getType()!=scalarArray) {
- structureOK = false;
- } else {
- ScalarArrayConstPtr scalarArray = dynamic_pointer_cast(field);
- if(scalarArray->getElementType()!=pvLong) structureOK = false;
- }
- }
- if(!structureOK) {
- string mess("channelPutConnect: illegal structure");
- message(mess,errorMessage);
- this->status = Status(Status::STATUSTYPE_ERROR,mess);
- }
- pvLongArray = static_pointer_cast(pvField);
- event.signal();
-}
-
-void LongArrayChannelPut::run()
-{
- while(true) {
- event.wait();
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- TimeStamp timeStamp;
- TimeStamp timeStampLast;
- timeStampLast.getCurrent();
- int numChannelPut = 0;
- int numChannelCreate = 0;
- size_t nElements = 0;
- while(true) {
- nElements += sizeof(int64) * arraySize;
- shared_vector xxx(arraySize,numChannelPut);
- shared_vector data(freeze(xxx));
- pvLongArray->replace(data);
- bitSet->set(pvLongArray->getFieldOffset());
- channelPut->put(pvStructure,bitSet);
- event.wait();
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- if(delayTime>0.0) epicsThreadSleep(delayTime);
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- timeStamp.getCurrent();
- double diff = TimeStamp::diff(timeStamp,timeStampLast);
- if(diff>=1.0) {
- ostringstream out;
- out << "put numChannelPut " << numChannelPut;
- out << " time " << diff ;
- double elementsPerSec = nElements;
- elementsPerSec /= diff;
- if(elementsPerSec>10.0e9) {
- elementsPerSec /= 1e9;
- out << " gigaElements/sec " << elementsPerSec;
- } else if(elementsPerSec>10.0e6) {
- elementsPerSec /= 1e6;
- out << " megaElements/sec " << elementsPerSec;
- } else if(elementsPerSec>10.0e3) {
- elementsPerSec /= 1e3;
- out << " kiloElements/sec " << elementsPerSec;
- } else {
- out << " Elements/sec " << elementsPerSec;
- }
- cout << out.str() << endl;
- timeStampLast = timeStamp;
- nElements = 0;
- }
- ++numChannelCreate;
- bool createPut = false;
- if(iterBetweenCreateChannel!=0) {
- if(numChannelCreate>=iterBetweenCreateChannel) {
- channel->destroy();
- ChannelProvider::shared_pointer channelProvider =
- getChannelProviderRegistry()->getProvider(providerName);
- channel = channelProvider->createChannel(
- channelName,getPtrSelf(),0);
- event.wait();
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- if(!status.isOK()) {
- message(status.getMessage(),errorMessage);
- return;
- }
- cout<< "createChannel success" << endl;
- createPut = true;
- numChannelCreate = 0;
- }
- }
- ++numChannelPut;
- if(iterBetweenCreateChannelPut!=0) {
- if(numChannelPut>=iterBetweenCreateChannelPut) createPut = true;
- }
- if(createPut) {
- numChannelPut = 0;
- channelPut->destroy();
- CreateRequest::shared_pointer createRequest = CreateRequest::create();
- PVStructurePtr pvRequest = createRequest->createRequest(request);
- if(!pvRequest) {
- cout << "request logic error " << createRequest->getMessage() << endl;
- return ;
- }
- channelPut = channel->createChannelPut(getPtrSelf(),pvRequest);
- event.wait();
- if(isDestroyed) {
- runReturned = true;
- return;
- }
- if(!status.isOK()) {
- message(status.getMessage(),errorMessage);
- return;
- }
- cout<< "createChannelPut success" << endl;
- }
- }
- }
-}
-
-void LongArrayChannelPut::putDone(
- Status const & status,
- ChannelPut::shared_pointer const & channelPut)
-{
- event.signal();
-}
-
-
-LongArrayPutPtr LongArrayPut::create(
- string const &providerName,
- string const & channelName,
- size_t arraySize,
- int iterBetweenCreateChannel,
- int iterBetweenCreateChannelPut,
- double delayTime)
-{
- LongArrayPutPtr longArrayPut(
- new LongArrayPut(
- providerName,
- channelName,
- arraySize,
- iterBetweenCreateChannel,
- iterBetweenCreateChannelPut,
- delayTime));
- if(!longArrayPut->init()) longArrayPut.reset();
- return longArrayPut;
-}
-
-LongArrayPut::LongArrayPut(
- string const &providerName,
- string const & channelName,
- size_t arraySize,
- int iterBetweenCreateChannel,
- int iterBetweenCreateChannelPut,
- double delayTime)
-: providerName(providerName),
- channelName(channelName),
- arraySize(arraySize),
- iterBetweenCreateChannel(iterBetweenCreateChannel),
- iterBetweenCreateChannelPut(iterBetweenCreateChannelPut),
- delayTime(delayTime)
-{}
-
-
-LongArrayPut::~LongArrayPut() {}
-
-bool LongArrayPut::init()
-{
- longArrayChannelPut = LongArrayChannelPutPtr(new LongArrayChannelPut(
- providerName,
- channelName,
- arraySize,
- iterBetweenCreateChannel,
- iterBetweenCreateChannelPut,
- delayTime));
- return longArrayChannelPut->init();
-}
-
-void LongArrayPut::destroy()
-{
- longArrayChannelPut->destroy();
- longArrayChannelPut.reset();
-}
-
-}}
-
-
diff --git a/arrayPerformance/src/longArrayPut.h b/arrayPerformance/src/longArrayPut.h
deleted file mode 100644
index efca9bb..0000000
--- a/arrayPerformance/src/longArrayPut.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/* longArrayPut.h */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.09
- */
-#ifndef LONGARRAYPUT_H
-#define LONGARRAYPUT_H
-
-
-#ifdef epicsExportSharedSymbols
-# define longarrayputEpicsExportSharedSymbols
-# undef epicsExportSharedSymbols
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-#ifdef longarrayputEpicsExportSharedSymbols
-# define epicsExportSharedSymbols
-# undef longarrayputEpicsExportSharedSymbols
-# include
-#endif
-
-namespace epics { namespace pvDatabase {
-
-
-class LongArrayPut;
-typedef std::tr1::shared_ptr LongArrayPutPtr;
-
-
-class LongArrayChannelPut;
-typedef std::tr1::shared_ptr LongArrayChannelPutPtr;
-
-class epicsShareClass LongArrayPut :
- public std::tr1::enable_shared_from_this
-{
-public:
- POINTER_DEFINITIONS(LongArrayPut);
- static LongArrayPutPtr create(
- std::string const & providerName,
- std::string const & channelName,
- size_t arraySize = 100,
- int iterBetweenCreateChannel = 0,
- int iterBetweenCreateChannelPut = 0,
- double delayTime = 0.0);
- ~LongArrayPut();
- void destroy();
-private:
- LongArrayPutPtr getPtrSelf()
- {
- return shared_from_this();
- }
- LongArrayPut(
- std::string const & providerName,
- std::string const & channelName,
- size_t arraySize,
- int iterBetweenCreateChannel,
- int iterBetweenCreateChannelPut,
- double delayTime);
- bool init();
-
- std::string providerName;
- std::string channelName;
- size_t arraySize;
- int iterBetweenCreateChannel;
- int iterBetweenCreateChannelPut;
- double delayTime;
- LongArrayChannelPutPtr longArrayChannelPut;
-};
-
-
-}}
-
-#endif /* LONGARRAYPUT_H */
diff --git a/arrayPerformance/src/longArrayPutMain.cpp b/arrayPerformance/src/longArrayPutMain.cpp
deleted file mode 100644
index 1e28df3..0000000
--- a/arrayPerformance/src/longArrayPutMain.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*longArrayPutMain.cpp */
-/**
- * Copyright - See the COPYRIGHT that is included with this distribution.
- * EPICS pvData is distributed subject to a Software License Agreement found
- * in file LICENSE that is included with this distribution.
- */
-/**
- * @author mrk
- * @date 2013.08.10
- */
-
-/* Author: Marty Kraimer */
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-using namespace std;
-using std::tr1::static_pointer_cast;
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using namespace epics::pvDatabase;
-
-int main(int argc,char *argv[])
-{
- string channelName("arrayPerformance");
- size_t arraySize = 10;
- int iterBetweenCreateChannel = 0;
- int iterBetweenCreateChannelPut = 0;
- double delayTime = 1.0;
- if(argc==2 && string(argv[1])==string("-help")) {
- cout << "longArrayPutMain channelName arraySize ";
- cout << "iterBetweenCreateChannel iterBetweenCreateChannelPut delayTime" << endl;
- cout << "default" << endl;
- cout << "longArrayPutMain " << channelName << " ";
- cout << arraySize << " ";
- cout << iterBetweenCreateChannel << " ";
- cout << iterBetweenCreateChannelPut << " ";
- cout << delayTime << endl;
- return 0;
- }
- ClientFactory::start();
- if(argc>1) channelName = argv[1];
- if(argc>2) arraySize = strtoul(argv[2],0,0);
- if(argc>3) iterBetweenCreateChannel = strtol(argv[3],0,0);
- if(argc>4) iterBetweenCreateChannelPut = strtol(argv[4],0,0);
- if(argc>5) delayTime = atof(argv[5]);
- cout << "longArrayPutMain " << channelName << " ";
- cout << arraySize << " ";
- cout << iterBetweenCreateChannel << " ";
- cout << iterBetweenCreateChannelPut << " ";
- cout << delayTime << endl;
- LongArrayPutPtr longArrayPut
- = LongArrayPut::create(
- "pvAccess",
- channelName,
- arraySize,
- iterBetweenCreateChannel,
- iterBetweenCreateChannelPut,
- delayTime);
- cout << "longArrayPut\n";
- string str;
- while(true) {
- cout << "Type exit to stop: \n";
- getline(cin,str);
- if(str.compare("exit")==0) break;
-
- }
- longArrayPut->destroy();
- longArrayPut.reset();
- double xxx = 1.0;
- if(xxx
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-
-using namespace std;
-using std::tr1::static_pointer_cast;
-using namespace epics::pvData;
-
-class VectorPerformanceThread;
-typedef std::tr1::shared_ptr VectorPerformanceThreadPtr;
-
-class VectorPerformanceThread :
- public epicsThreadRunable
-{
-public:
- VectorPerformanceThread(int threadNumber,size_t size,double delay);
- virtual ~VectorPerformanceThread(){};
- void init();
- void start();
- virtual void run();
- void destroy();
-private:
- bool isDestroyed;
- bool runReturned;
- int threadNumber;
- size_t size;
- epics::pvData::int64 value;
- double delay;
- Mutex mutex;
- std::vector vector;
- std::auto_ptr thread;
-};
-
-VectorPerformanceThread::VectorPerformanceThread(
- int threadNumber,size_t size,double delay)
-:
- isDestroyed(false),
- runReturned(false),
- threadNumber(threadNumber),
- size(size),
- value(0),
- delay(delay)
-{}
-
-void VectorPerformanceThread::init()
-{
- vector.resize(size);
- thread = std::auto_ptr(new epicsThread(
- *this,
- "vectorPerform",
- epicsThreadGetStackSize(epicsThreadStackSmall),
- epicsThreadPriorityHigh));
-}
-
-void VectorPerformanceThread::start()
-{
- thread->start();
-}
-
-void VectorPerformanceThread::destroy()
-{
- Lock lock(mutex);
- if(isDestroyed) return;
- isDestroyed = true;
- while(true) {
- if(runReturned) break;
- lock.unlock();
- epicsThreadSleep(.01);
- lock.lock();
- }
- thread->exitWait();
- thread.reset();
-}
-
-
-void VectorPerformanceThread::run()
-{
- TimeStamp timeStamp;
- TimeStamp timeStampLast;
- timeStampLast.getCurrent();
- int nSinceLastReport = 0;
- while(true) {
- if(delay>0.0) epicsThreadSleep(delay);
- {
- Lock lock(mutex);
- if(isDestroyed) {
-cout << " found isDestroyed " << threadNumber << endl;
- runReturned = true;
- return;
- }
- }
- timeStamp.getCurrent();
- double diff = TimeStamp::diff(timeStamp,timeStampLast);
- if(diff>=1.0) {
- cout << "thread" << threadNumber;
- cout << " value " << value;
- cout << " time " << diff;
- double iterations = nSinceLastReport;
- iterations /= diff;
- cout << " iterations/sec " << iterations;
- double elementSize = size;
- double elementsPerSecond = elementSize*nSinceLastReport;
- elementsPerSecond /= diff;
- elementsPerSecond /= 1e6;
- cout << " elements/sec " << elementsPerSecond << "million" << endl;
- cout.flush();
- timeStampLast = timeStamp;
- nSinceLastReport = 0;
- }
- ++nSinceLastReport;
- ++value;
- for(size_t i=0; i1) size = strtoul(argv[1],0,0);
- if(argc>2) delay = atof(argv[2]);
- if(argc>3) nThread = strtoul(argv[3],0,0);
- cout << "vectorPerformance ";
- cout << size << " ";
- cout << delay << " ";
- cout << nThread << " ";
- cout << endl;
- cout << "vectorPerformance\n";
- std::vector threads;
- for(size_t i=0; iinit();
- }
- for(size_t i=0; istart();
- }
- string str;
- while(true) {
- cout << "Type exit to stop: \n";
- getline(cin,str);
- if(str.compare("exit")==0) break;
-
- }
- for(size_t i=0; idestroy();
- threads[i].reset();
- }
- return 0;
-}
-
diff --git a/configure/ExampleRELEASE.local b/configure/ExampleRELEASE.local
index 1912f46..3d164df 100644
--- a/configure/ExampleRELEASE.local
+++ b/configure/ExampleRELEASE.local
@@ -1,10 +1,8 @@
+EPICS4_DIR=/home/epicsv4/master
+
+PVACCESS=${EPICS4_DIR}/pvAccessCPP
+PVDATA=${EPICS4_DIR}/pvDataCPP
+PVCOMMON=${EPICS4_DIR}/pvCommonCPP
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
-
EPICS_BASE=/home/install/epics/base
-V4BASE=/home/epicsv4
-PVCOMMON=${V4BASE}/pvCommonCPP
-PVDATA=${V4BASE}/pvDataCPP
-NORMATIVETYPES=${V4BASE}/normativeTypesCPP
-PVACCESS=${V4BASE}/pvAccessCPP
-PVASRV=${V4BASE}/pvaSrv
diff --git a/documentation/pvDatabaseCPP.html b/documentation/pvDatabaseCPP.html
index e84aff8..8eba339 100644
--- a/documentation/pvDatabaseCPP.html
+++ b/documentation/pvDatabaseCPP.html
@@ -36,29 +36,8 @@
pvDatabaseCPP
-
+
Release 4.2 - 2016.01.12
-
EPICS v4 Working Group, Working Draft, 23-October-2015
-
- - Latest version:
- - pvDatabaseCPP.html
-
- - This version:
- - pvDatabaseCPP20151023.html
-
- - Previous version:
- - pvDatabaseCPP20151002.html
-
- - Editors:
- - Marty Kraimer, BNL
-
-
-
This product is made available subject to acceptance of the EPICS open source license.
-
Abstract
@@ -69,25 +48,22 @@ pvData. The framework includes a complete implementation of ChannelProvider as d
The framework can be extended in order to create record instances that implements services.
The minimum that an extension must provide is a top level PVStructure and a process method.
-
-
EPICS version 4 is a set of related products in the EPICS
-V4 control system programming environment:
-relatedDocumentsV4.html
-
+
+
For more information about EPICS generally, please refer to the home page of the Experimental Physics and Industrial
+ Control System.
-
Status of this Document
-
-
This is the 23-October-2015 version of of pvDatabaseCPP.
-
This version is a complete implementation of what is described in this manual.
-
-
Table of Contents
+ Table of Contents
-
+
+
+
+
Introduction
Overview
@@ -151,104 +127,10 @@ level PVStructure and the following three methods:
href="./html/index.html">doxygenDoc
Getting started
The first step is to build pvDatabaseCPP as described in the next section.
-
One of the examples is exampleServer.
-It can be started either via a main program or as part of a V3 IOC.
+
A separate project exampleCPP has examples for pvDatabaseCPP
+and for pvaClientCPP.
+See it for examples.
-
To start it as a main program do the following:
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer
-mrk> bin/linux-x86_64/exampleServerMain
-
-
You should see something like the following:
-
-result of addRecord exampleServer 1
-VERSION : pvAccess Server v3.0.5-SNAPSHOT
-PROVIDER_NAMES : local
-BEACON_ADDR_LIST :
-AUTO_BEACON_ADDR_LIST : 1
-BEACON_PERIOD : 15
-BROADCAST_PORT : 5076
-SERVER_PORT : 5075
-RCV_BUFFER_SIZE : 16384
-IGNORE_ADDR_LIST:
-STATE : INITIALIZED
-exampleServer
-Type exit to stop:
-
-
Then in another window execute a pvput and pvget as follows:
-
-mrk> pvput -r "field(argument.value)" exampleServer World
-...
-mrk> pvget -r "record[process=true]field(result.value)" exampleServer
-exampleServer
-structure
- string value Hello World
-mrk>
-
-
To run the example as part of a V3 IOC do the following:
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer/iocBoot/exampleServer
-mrk> ../../bin/linux-x86_64/exampleServer st.cmd
-
-
You will see the following:
-
-> envPaths
-epicsEnvSet("ARCH","linux-x86_64")
-epicsEnvSet("IOC","exampleServer")
-epicsEnvSet("TOP","/home/hg/pvDatabaseCPP/exampleServer")
-epicsEnvSet("EPICS_BASE","/home/install/epics/base")
-epicsEnvSet("EPICSV4HOME","/home/hg")
-cd /home/hg/pvDatabaseCPP/exampleServer
-## Register all support components
-dbLoadDatabase("dbd/exampleServer.dbd")
-exampleServer_registerRecordDeviceDriver(pdbbase)
-## Load record instances
-dbLoadRecords("db/dbScalar.db","name=pvdouble,type=ao")
-dbLoadRecords("db/dbArray.db","name=pvdoubleArray,type=DOUBLE")
-dbLoadRecords("db/dbStringArray.db","name=pvstringArray")
-dbLoadRecords("db/dbEnum.db","name=pvenum")
-dbLoadRecords("db/dbCounter.db","name=pvcounter");
-cd /home/hg/pvDatabaseCPP/exampleServer/iocBoot/exampleServer
-iocInit()
-Starting iocInit
-############################################################################
-## EPICS R3.14.12.3 $Date: Mon 2012-12-17 14:11:47 -0600$
-## EPICS Base built Dec 21 2013
-############################################################################
-iocRun: All initialization complete
-dbl
-pvdouble
-pvcounter
-pvenum
-pvdoubleArray
-pvstringArray
-epicsThreadSleep(1.0)
-exampleServerCreateRecord pvaServer
-startPVAServer
-VERSION : pvAccess Server v3.0.5-SNAPSHOT
-PROVIDER_NAMES : dbPv local
-BEACON_ADDR_LIST :
-AUTO_BEACON_ADDR_LIST : 1
-BEACON_PERIOD : 15
-BROADCAST_PORT : 5076
-SERVER_PORT : 5075
-RCV_BUFFER_SIZE : 16384
-IGNORE_ADDR_LIST:
-STATE : INITIALIZED
-pvdbl
-pvaServer
-epics>
-
-
Just like previously you can then execute a pvput and pvget and see Hello World.
-
-
The examples, i. e. exampleServer, exampleLink, examplePowerSupply,
-and exampleDatabase, are described in separate sections below.
-In addition arrayPerformance can be used to measure that performance of big
-arrays. It is also described in a later section.
-
Reading section exampleServer and looking at it's code is a good way
-to learn how to implement a service.
Features Required for localChannelProvider
@@ -314,94 +196,31 @@ Than at the top level just execute make:
mrk> cd ..
mrk> pwd
-/home/hg/pvDatabaseCPP
+/home/epicsv4/master/pvDatabaseCPP
mrk> make
-This builds pvDatabaseCPP and also the tests and all examples.
-Each example and arrayPerformance is a completely separate top,
+
This builds pvDatabase and also test.
+test is a completely separate top,
but is also built when make is run in pvDatabaseCPP itself.
-
-Each is a separate top for the following reasons:
-
- -
- It is easier to understand each example including how it is built so that
- it can be run as a main or as part of a V3 IOC.
-
- -
- Each example can be copied somewhere else and used as the basis
- for creating a new service.
-
-
-
-If it is desired to build an example all by itself,
-just follow the same instructions as for building pvDatabaseCPP itself.
-For example:
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer/configure
-mrk> cp ExampleRELEASE.local RELEASE.local
-
-Then edit RELEASE.local so that it has the correct location of each
-product the example requires.
-Than at the top level of the example just execute make:
-
-mrk> cd ..
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer
-mrk> make
-
-This builds the example.
iocshell commands
Shell commands are made available via the standard DBD include mechanism
provided by iocCore.
The following provide EPICS V4 shell commands:
-
- - pvAccessCPP
- - PVAClientRegister.dbd and PVAServerRegister.dbd
- - pvaSrv
- - dbPv.dbd
- - pvDatabaseCPP
- - registerChannelProviderLocal.dbd
-
-
-Look at exampleServer/ioc/src/exampleServerInclude.dbd for an example
-of how an application can make the shell commands available.
-
-Commands From pvAccessCPP
-The following iocsh commands are provided for a V3IOC:
-
- - startPVAClient
- - Starts the client side of pvAccess.s
- It makes channel provider pvAccess available.
- After startPVAServer is called the channel provider local will
- also be available.
-
- - stopPVAClient
- - Stops pvAccess.
- - startPVAServer
- - Starts the local channel provider
- - stopPVAServer
- - Stop the local channel provider
-
+
+pvAccessCPP
+pvaSrv
+pvDatabaseCPP
+
-Commands implemented by pvDatabaseCPP
-The following iocsh commands are provided for a V3IOC:
+pvDatabaseCPP provides the following iocshell command.
- pvdbl
- Provides a list of all the pvRecords in database master
In addition any code that implements a PVRecord must implement an ioc command.
-Look at any of the examples to see how to implement shell commands.
-Commands implemented by pvaSrv
-pvaSrv provides a pvAccess server that provides access to iocCore records.
-pvaSrv does not provide any shell commands but it can be part of an IOC.
-Just make sure your application configures pvaSrv and then include the following file:
-
-
-include "dbPv.dbd"
-
+Look at any of the examples in exampleCPP to see how to implement shell commands.
database
src/database
@@ -1054,950 +873,6 @@ result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
-exampleServer
-Overview
-The example implements a simple service that has a top level pvStructure:
-
-
-structure
- structure argument
- string value
- structure result
- string value
- time_t timeStamp
- long secondsPastEpoch
- int nanoseconds
- int userTag
-
-It is designed to be accessed via a channelPutGet request.
-The client sets argument.value
-When the record processes it sets result.value to "Hello "
-concatenated with argument.value.
-Thus if the client sets argument.value equal to "World"
-result.value will be "Hello World".
-In addition the timeStamp is set to the time when process is called.
-
-The example can be run on linux as follows:
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleService
-mrk> bin/linux-x86_64/exampleService
-
-Directory Layout
-
-The directory layout is:
-
-
-exampleServer
- configure
- ExampleRELEASE.local
- ...
- src
- exampleServer.h
- exampleServer.cpp
- exampleServerInclude.dbd
- exampleServerMain.cpp
- exampleServerRegister.cpp
- exampleServerRegister.dbd
- ioc
- Db
- ...
- src
- exampleServerInclude.dbd
- exampleServerMain.cpp
- iocBoot
- exampleServer
- st.cmd
- ...
-
-where
-
- - ExampleRELEASE.local
- -
- If you make a copy of exampleServer and use it
- to create a new server,
- This is the file that must be copied to RELEASE.local
- and edited.
- - exampleServer.h
- - The header file for the service.
- - exampleServer.cpp
- - The service implementation.
- - exampleServerMain.cpp
- - A main program that runs the example so that it can be accessed
- by a pvAccess client.
-
- - exampleServerInclude.dbd
- - This has a register command so that the service can be started
- on a V3 IOC via iocsh.
-
- - exampleServerRegister.cpp
- - This has the code to start the service via the following iocsh
- command.
-
- - exampleServerRegister.dbd
- - This is the file that is used to create the shell command
- exampleServerCreateRecord.
-
-exampleServerCreateRecord exampleServer
-
- Multiple commands can be issued to create multiple service records.
-
- - ioc
- - This is for building a V3 IOC application.
- - ioc/Db
- - This has template files for creating V3 records.
- - ioc/src
- - The files for running a V3 IOC.
- - iocBoot/exampleServer
- - A place to start exampleServer as part of a V3IOC.
- It has a st.cmd file that starts the ioc and also starts pvAccess
- and the example.
-
-If only a main program is desired then the directory layout is:
-
-exampleServer
- configure
- ExampleRELEASE.local
- ...
- src
- exampleServer.h
- exampleServer.cpp
- exampleServerMain.cpp
-
-Thus if only a main program is required the directory layout is simple.
-Also many sites will want to build the src directory in an area
-separate from where the iocs are build.
-exampleServer.h
-The example resides in src
-The implementation is in exampleServer.cpp.
-
-The description consists of
-
-class ExampleServer;
-typedef std::tr1::shared_ptr<ExampleServer> ExampleServerPtr;
-
-class ExampleServer :
- public PVRecord
-{
-public:
- POINTER_DEFINITIONS(ExampleServer);
- static ExampleServerPtr create(
- std::string const & recordName);
- virtual ~ExampleServer();
- virtual void destroy();
- virtual bool init();
- virtual void process();
-private:
- ExampleServer(std::string const & recordName,
- epics::pvData::PVStructurePtr const & pvStructure);
-
- epics::pvData::PVStringPtr pvArgumentValue;
- epics::pvData::PVStringPtr pvResultValue;
- epics::pvData::PVTimeStamp pvTimeStamp;
- epics::pvData::TimeStamp timeStamp;
-};
-
-where
-
- - create
- - This is example specific but each support could provide
- a similar static method.
-
- - ~ExampleServer
- - The destructor must be declared virtual.
- - destroy
- - Called when the record is being destroyed.
- This must call the base class destroy method.
-
- - init
- - A method to initialize the support. It returns true
- if initialization is successful and false if not.
- NOTE that this is a virtual method of PVRecord itself.
- - process
- -
- This again is a virtual method of PVRecord.
-
- - ExampleServer
- - For the example this is private.
- - pvValue
- - This is the field of the top level structure that process
- accesses.
-
-
-The implementation of create method is:
-
-ExampleServerPtr ExampleServer::create(
- std::string const & recordName)
-{
- StandardFieldPtr standardField = getStandardField();
- FieldCreatePtr fieldCreate = getFieldCreate();
- PVDataCreatePtr pvDataCreate = getPVDataCreate();
- StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
- addNestedStructure("argument")->
- add("value",pvString)->
- endNested()->
- addNestedStructure("result") ->
- add("value",pvString) ->
- add("timeStamp",standardField->timeStamp()) ->
- endNested()->
- createStructure();
- PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
-
- ExampleServerPtr pvRecord(
- new ExampleServer(recordName,pvStructure));
- if(!pvRecord->init()) pvRecord.reset();
- return pvRecord;
-}
-
-This:
-
- - Creates the top level structure.
- - Creates a ExampleServerPtr via the constructor.
- - Calls init and if it fails resets the shared pointer.
- - Returns the shared pointer to the newly created record.
-
-The private constructor method is:
-
-ExampleServer::ExampleServer(
- std::string const & recordName,
- epics::pvData::PVStructurePtr const & pvStructure)
-: PVRecord(recordName,pvStructure)
-{
-}
-
-The example is very simple. Note that it calls the base class constructor.
-The destructor and destroy methods are:
-
-ExampleServer::~ExampleServer()
-{
-}
-
-void ExampleServer::destroy()
-{
- PVRecord::destroy();
-}
-
-The destructor has nothing to do.
-The destroy method, which is virtual, just calls the destroy method of the base class.
-A more complicated example can clean up any resources it used but must call the base
-class destroy method.
-The implementation of init is:
-
-bool ExampleServer::init()
-{
- initPVRecord();
- PVFieldPtr pvField;
- pvArgumentValue = getPVStructure()->getStringField("argument.value");
- if(pvArgumentValue.get()==NULL) return false;
- pvResultValue = getPVStructure()->getStringField("result.value");
- if(pvResultValue.get()==NULL) return false;
- pvTimeStamp.attach(getPVStructure()->getSubField("result.timeStamp"));
- return true;
-}
-
-The implementation of process is:
-
-void ExampleServer::process()
-{
- pvResultValue->put(String("Hello ") + pvArgumentValue->get());
- timeStamp.getCurrent();
- pvTimeStamp.set(timeStamp);
-}
-
-It gives a value to result.value and
-then sets the timeStamp to the current time.
-src/exampleServerMain.cpp
-NOTE:
-This is a shorter version of the actual code.
-It shows the essential code.
-The actual example shows how create an additional record.
-
-The main program is:
-
-int main(int argc,char *argv[])
-{
- PVDatabasePtr master = PVDatabase::getMaster();
- ChannelProviderLocalPtr channelProvider = ChannelProviderLocal::create();
- String recordName("exampleServer");
- PVRecordPtr pvRecord = ExampleServer::create(recordName);
- bool result = master->addRecord(pvRecord);
- if(!result) cout<< "record " << recordName << " not added" << endl;
- recordName = "traceRecordPGRPC";
- pvRecord = TraceRecord::create(recordName);
- result = master->addRecord(pvRecord);
- if(!result) cout<< "record " << recordName << " not added" << endl;
- ServerContext::shared_pointer pvaServer =
- startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
- PVStringArrayPtr pvNames = master->getRecordNames();
- shared_vector<const string> names = pvNames->view();
- for(size_t i=0; i<names.size(); ++i) cout << names[i] << endl;
- string str;
- while(true) {
- cout << "Type exit to stop: \n";
-
- }
- return 0;
-}
-
-This:
-
- - Gets a pointer to the master database.
- - Creates the local Channel Provider. This starts the pvAccess server.
- - Creates record exampleServer
- - creates record traceRecordPGRPC
- - lists all the records
- - Runs forever until the user types exit on standard in.
-
-V3IOC exampleServer
-To start exampleServer as part of a V3IOC:
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer/iocBoot/exampleServer
-mrk> ../../../bin/linux-x86_64/exampleServer st.cmd
-
-You can then issue the commands dbl and pvdbl:
-
-epics> dbl
-pvdouble
-pvcounter
-pvenum
-pvdoubleArray
-pvstringArray
-epics> pvdbl
-exampleServer
-epics>
-
-dbl shows the V3 records.
-pvdbl shows the pvRecords.
-
-It starts pvaSrv so that the V3 records can be accessed via Channel Access
-or via PVAccess.
-
-exampleDatabase
-The exampleServer pvDatabase has many records including the following:
-
- - exampleDouble
- - A record that is an instance of a record with a process method
- that does nothing. To test it start a channelPut and a channelGet and/or monitor.
- - exampleDoubleArray
- - An array record that is an instance of a record with a process method
- that does nothing. It can be tested like exampleDouble. In addition channelArray can
- also be used.
- - traceRecordPGRPC
- - This can be used via channelPutGet to set the trace level of another record.
-
-It also has a number of other scalar and array records.
-exampleDatabase can be started as a main program or as a V3 IOIC.
-If started as a V3 IOC it also has a number of V3 records,
-and starts pvaSrv so that the V3 records can be accessed via Channel Access
-or via PVAccess.
-exampleLink
-This example show how a service can access other PVRecords.
-This section 1) starts with a discussion of accessing data via pvAccess
-and 2) gives a brief description of an example that gets data for an array of doubles.
-Discussion
-Access Alternatives
-The process routine of a PVRecord can access other PVRecords in two ways:
-
- - Directly accessing local pvDatabase
- -
- If the other PVRecord is accessed via the master PVDatabase then
- threading issues are up to the implementation.
- For now this method will not be discussed.
- - Access via pvAccess
- -
- If access is via pvAccess then locking is handled by pvAccess.
-
-Access via pvAccess can be done either by local or remote channel provider.
-
- - Access via channelProviderLocal
- -
- If the local pvAccess server is used the implementation must be careful that it does not
- cause deadlocks.
- When the process method is called the pvRecord for the process method is locked.
- When it makes a pvAccess get, put, etc request the other record is locked.
- Thus if a set of pvAccess links are implemented the possibility of deadlocks
- exists. A simple example is two records that have links to each other.
- More complex sets are easily created.
- Unless the developer has complete control of the set of records then remote pvAccess should
- be used.
- But this results in more context switches.
-
- - Access via remote pvAccess
- - If remote pvAccess is used then all locking issues are handled by pvAccess.
- The linked channel can be a pvRecord in the local pvDatabase or can be implemented
- by a remote pvAccess server.
-
-Data synchronization
-If pvAccess is used then it handles data synchronization.
-This is done by making a copy of the data that is transferred between the two pvRecords.
-This is true if either remote or local pvAccess is used.
-Each get, put, etc request results in data being copied between the two records.
-
-If the linked channel is a local pvRecord then,
-for scalar and structure arrays,
-raw data is NOT copied for gets.
-This is because pvData uses shared_vector to hold the raw data.
-Instead of copying the raw data the reference count is incremented.
-For puts the linked array will force a new allocation of the raw data in the linked record,
-i. e. copy on write semantics are enforced. This is done automatically
-by pvData and not by pvDatabase.
-Some details
-As mentioned before a pvDatabase server can be either a separate process,
-i. e. a main program, or can be part of a V3IOC.
-A main pvDatabase server issues the following calls:
-
- ClientFactory::start();
- ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
- ...
- ServerContext::shared_pointer serverContext =
- startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
-
-The first call is only necessary if some of the pvRecords
-have pvAccess links.
-These must be called before any code that uses links is initialized.
-After these two calls there will be two channel providers: local, and pvAccess.
-
-
-A pvDatabase that is part of a V3IOC has the following in the st.cmd file.
-
-...
-iocInit()
-startPVAClient
-startPVAServer
-## commands to create pvRecords
-
-
-Once the client and local provider code has started then the following creates a channel access link.
-
-
-PVDatabasePtr master = PVDatabase::getMaster();
-ChannelProvider::shared_pointer provider =
- getChannelProviderRegistry()->getProvider(providerName);
-Channel::shared_pointer channel = provider->createChannel(channelName,channelRequester);
-
-
-Directory Layout
-
-exampleLink
- configure
- ExampleRELEASE.local
- ...
- src
- exampleLink.h
- exampleLink.cpp
- exampleLinkInclude.dbd
- exampleLinkRegister.cpp
- ioc
- Db
- src
- exampleLinkInclude.dbd
- exampleLinkMain.cpp
- iocBoot
- exampleLink
- st.local
- st.remote
- ...
-
-This example is only built to be run as part of a V3 IOC.
-Note that two startup files are available: st.local and st.remote.
-st.local has two records: doubleArray and exampleLink.
-doubleArray is a record that can be changed via a call to pvput.
-exampleLink is a record that, when processed, gets the value from doubleArray and sets its value equal
-to the value read.
-st.local has both records.
-st.remote has only one record named exampleLinkRemote.
-
-To start the example:
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleLink/iocBoot/exampleLink
-mrk> ../../bin/linux-x86_64/exampleLink st.local
-
-then in another window:
-
-mrk> pvput doubleArray 4 100 200 300 400
-Old : doubleArray 0
-New : doubleArray 4 100 200 300 400
-mrk> pvget -r "record[process=true]field(value)" exampleLink
-exampleLink
-structure
- double[] value [100,200,300,400]
-mrk>
-
-exampleLink Implementation
-exampleLink.h contains the following:
-
-...
-class ExampleLink :
- public PVRecord,
- public epics::pvAccess::ChannelRequester,
- public epics::pvAccess::ChannelGetRequester
-{
-public:
- POINTER_DEFINITIONS(ExampleLink);
- static ExampleLinkPtr create(
- std::string const & recordName,
- std::string const & providerName,
- std::string const & channelName
- );
- virtual ~ExampleLink() {}
- virtual void destroy();
- virtual bool init();
- virtual void process();
- virtual void channelCreated(
- const epics::pvData::Status& status,
- epics::pvAccess::Channel::shared_pointer const & channel);
- virtual void channelStateChange(
- epics::pvAccess::Channel::shared_pointer const & channel,
- epics::pvAccess::Channel::ConnectionState connectionState);
- virtual void channelGetConnect(
- const epics::pvData::Status& status,
- epics::pvAccess::ChannelGet::shared_pointer const & channelGet,
- epics::pvData::PVStructure::shared_pointer const & pvStructure,
- epics::pvData::BitSet::shared_pointer const & bitSet);
- virtual void getDone(const epics::pvData::Status& status);
-private:
-...
-
-All the non-static methods are either PVRecord, PVChannel, or PVChannelGet methods
-and will not be discussed further.
-The create method is called to create a new PVRecord instance with code that will issue
-a ChannelGet::get request every time the process method of the instance is called.
-Some other pvAccess client can issue a channelGet, to the record instance, with a request
-to process in order to test the example.
-All of the initialization is done by a combination of the create and init methods so
-lets look at them:
-
-ExampleLinkPtr ExampleLink::create(
- String const & recordName,
- String const & providerName,
- String const & channelName)
-{
- PVStructurePtr pvStructure = getStandardPVField()->scalarArray(
- pvDouble,"alarm.timeStamp");
- ExampleLinkPtr pvRecord(
- new ExampleLink(
- recordName,providerName,channelName,pvStructure));
- if(!pvRecord->init()) pvRecord.reset();
- return pvRecord;
-}
-
-This first creates a new ExampleLink instance,
-and then calls the init method and the returns a ExampleLinkPtr.
-Note that if init returns false it returns a pointer to NULL.
-The init method is:
-
-bool ExampleLink::init()
-{
- initPVRecord();
-
- PVStructurePtr pvStructure = getPVRecordStructure()->getPVStructure();
- pvTimeStamp.attach(pvStructure->getSubField("timeStamp"));
- pvAlarm.attach(pvStructure->getSubField("alarm"));
- pvValue = static_pointer_cast<PVDoubleArray>(
- pvStructure->getScalarArrayField("value",pvDouble));
- if(pvValue==NULL) {
- return false;
- }
- ChannelAccess::shared_pointer channelAccess = getChannelAccess();
- ChannelProvider::shared_pointer provider =
- channelAccess->getProvider(providerName);
- if(provider==NULL) {
- cout << getRecordName() << " provider "
- << providerName << " does not exist" << endl;
- return false;
- }
- ChannelRequester::shared_pointer channelRequester =
- dynamic_pointer_cast<ChannelRequester>(getPtrSelf());
- channel = provider->createChannel(channelName,channelRequester);
- event.wait();
- if(!status.isOK()) {
- cout << getRecordName() << " createChannel failed "
- << status.getMessage() << endl;
- return false;
- }
- ChannelGetRequester::shared_pointer channelGetRequester =
- dynamic_pointer_cast<ChannelGetRequester>(getPtrSelf());
- PVStructurePtr pvRequest = getCreateRequest()->createRequest(
- "value,alarm,timeStamp",getPtrSelf());
- channelGet = channel->createChannelGet(channelGetRequester,pvRequest);
- event.wait();
- if(!status.isOK()) {
- cout << getRecordName() << " createChannelGet failed "
- << status.getMessage() << endl;
- return false;
- }
- getPVValue = static_pointer_cast<PVDoubleArray>(
- getPVStructure->getScalarArrayField("value",pvDouble));
- if(getPVValue==NULL) {
- cout << getRecordName() << " get value not PVDoubleArray" << endl;
- return false;
- }
- return true;
-}
-
-This first makes sure the pvStructure has the fields it requires:
-
- - timeStamp
- - A timeStamp structure. This will be set to the current time when process is called.
- - alarm
- - An alarm structure. This will be used to pass status information to the client when
- process is called.
- - value
- - This must be a scalarArray of type double.
- It is where data is copied when the channelGet is issued.
-
-Next it makes sure the channelProvider exists.
-Next it creates the channel and waits until it connects.
-Next it creates the channelGet and waits until it is created.
-Next it makes sure it has connected to a double array field.
-If anything goes wrong during initialization it returns false.
-This a return of true means that it has successfully created a channelGet and is ready
-to issue gets when process is called.
-Look at the code for more details.
-examplePowerSupply
-This is an example of creating a service that requires a somewhat complicated
-top level PVStructure.
-Look at the code for details.
-
-Array Performance and Memory Example
-This section describes main programs that demonstrate performance
-of large arrays and can also be used to check for memory leaks.
-Checking for memory leaks can be accomplished by running the programs with valgrind
-or some other memory check program.
-
-Brief Summary
-The programs are:
-
- - arrayPerformanceMain
- - This is server and also a configurable number of longArrayMonitor clients.
- The clients can use either the local or
- remote providers. The monitor code is the same code that is used by longArrayMonitorMain.
-
- - longArrayMonitorMain
- - Remote client that monitors the array served by arrayPerformanceMain.
- - longArrayGetMain
- - Remote client that uses channelGet to access the array served by arrayPerformanceMain.
- - longArrayPutMain
- - Remote client that uses channelPut to access the array served by arrayPerformanceMain.
-
-Each has support for -help.
-
-mrk> pwd
-/home/hg/pvDatabaseCPP-md
-mrk> bin/linux-x86_64/arrayPerformanceMain -help
-arrayPerformanceMain recordName size delay providerName nMonitor queueSize waitTime
-default
-arrayPerformanceMain arrayPerformance 10000000 0.0001 local 1 2 0.0
-
-mrk> bin/linux-x86_64/longArrayMonitorMain -help
-longArrayMonitorMain channelName queueSize waitTime
-default
-longArrayMonitorMain arrayPerformance 2 0.0
-
-mrk> bin/linux-x86_64/longArrayGetMain -help
-longArrayGetMain channelName iterBetweenCreateChannel iterBetweenCreateChannelGet delayTime
-default
-longArrayGetMain arrayPerformance 0 0 1
-
-mrk> bin/linux-x86_64/longArrayPutMain -help
-longArrayPutMain channelName arraySize iterBetweenCreateChannel iterBetweenCreateChannelPut delayTime
-default
-longArrayPutMain arrayPerformance 10 0 0 1
-
-mrk>
-
-Example output
-Note: These may fail if run on a platform that does not have sufficient memory,
-To see an example just execute the following commands in four different terminal windows:
-
-bin/linux/<arch>/arrayPerformanceMain
-bin/linux/<arch>/longArrayMonitorMain
-bin/linux/<arch>/longArrayGetMain
-bin/linux/<arch>/longArrayPutMain
-
-Each program generates a report every second when it has something to report.
-Examples are:
-
-mrk> bin/linux-x86_64/arrayPerformanceMain
-arrayPerformance arrayPerformance 10000000 0.0001 local 1 2 0
-...
- monitors/sec 66 first 131 last 131 changed {1, 2} overrun {} megaElements/sec 656.999
-arrayPerformance value 132 time 1.00486 Iterations/sec 65.681 megaElements/sec 656.81
- monitors/sec 66 first 197 last 197 changed {1, 2} overrun {} megaElements/sec 656.304
-arrayPerformance value 198 time 1.00563 Iterations/sec 65.6307 megaElements/sec 656.307
- monitors/sec 66 first 263 last 263 changed {1, 2} overrun {} megaElements/sec 654.824
-...
-
-
-mrk> bin/linux-x86_64/longArrayMonitorMain
-longArrayMonitorMain arrayPerformance 2 0
-...
- monitors/sec 6 first 2357 last 2357 changed {1, 2} overrun {} megaElements/sec 68.6406
- monitors/sec 13 first 2385 last 2385 changed {1, 2} overrun {} megaElements/sec 118.72
- monitors/sec 9 first 2418 last 2418 changed {1, 2} overrun {1, 2} megaElements/sec 85.0984
-...
-
-
-mrk> bin/linux-x86_64/longArrayPutMain
-longArrayPutMain arrayPerformance 10 0 0 1
-...
-put numChannelPut 0 time 1.00148 Elements/sec 79.8819
-put numChannelPut 1 time 1.00176 Elements/sec 79.8598
-...
-
-
-mrk> bin/linux-x86_64/longArrayGetMain
-longArrayGetMain arrayPerformance 0 0 1
-...
-get kiloElements/sec 7384.61
-get kiloElements/sec 8726.34
-...
-
-
-arrayPerformance
-The arguments for arrayPerforamanceMain are:
-
- - recordName
- - The name for the arrayPerform record.
- - size
- - The size for the long array of the value field.
- - delay
- - The time in seconds to sleep after each iteration.
- - providerName
- - The name of the channel provider for the longArrayMonitors
- created by the main program. This must be either local
- or pvAccess.
-
- - nMonitor
- - The number of longArrayMonitors to create.
- - queueSize
- - The queueSize for the element queue.
- A value less than 1 will become 1.
-
- - waitTime
- - The time that longArrayMonitor will sleep after poll returns a monitorElement.
-
-
-arrayPerformance creates a PVRecord that has the structure:.
-
-
-recordName
- long[] value
- timeStamp timeStamp
- alarm alarm
-
-Thus it holds an array of 64 bit integers.
-The record has support that consists of a separate thread that runs
-until the record is destroyed executing the following algorithm:
-
- - report
- - Once a second it produces a report.
- In the above example output each line starting with
- ArrayPerformance is an arrayPerformance report.
-
- - create array
- - A new shared_vector is created and each element is set equal
- to the iteration count.
- - lock
- - The arrayPerformance record is locked.
- - Begin group put
- - beginGroupReport is called.
- - replace
- - The value field of the record is replaced
- with the newly created shared_vector.
- - process
- - The record is then processed. This causes the timeStamp to
- be set to the current time.
- - End group put
- - endGroupPut is called.
- - unlock
- - The arrayPerformance record is unlocked.
- - delay
- - If delay is greater than zero epicsThreadSleep is called.
-
-longArrayMonitor
-This is a pvAccess client that monitors an arrayPerformance record.
-It generates a report every second showing how many elements has received.
-For every monitor it also checks that the number of elements is >0 and the
-the first element equals the last element. It reports an error if either
-of these conditions is not true.
-The arguments for longArrayMonitorMain are:
-
- - channelName
- - The name for the arrayPerform record.
- - queueSize
- - The queueSize. Note that any size <2 is made 2.
- - waitTime
- - The time to wait after a poll request returns a monitorElement.
- This can be used to force an overrun of the client even if there is no
- overrun on the server.
-
-longArrayGet
-This is a pvAccess client that uses channelGet to access an arrayPerformance record.
-Every second it produces a report.
-
-The arguments for longArrayGetMain are:
-
- - channelName
- - The name for the arrayPerform record.
- - iterBetweenCreateChannel
- - The number of iterations between destroying and recreating the channel.
- A value of 0 means never destroy and recreate.
-
- - iterBetweenCreateChannelGet
- - The number of iterations between destroying and recreating the channelGet.
- A value of 0 means never destroy and recreate.
-
- - delayTime
- - The time to delay between gets.
-
-longArrayPut
-This is a pvAccess client that uses channelPut to access an arrayPerformance record.
-Every second it produces a report.
-
-The arguments for longArrayPutMain are:
-
- - channelName
- - The name for the arrayPerform record.
- - arraySize
- - The capacity and length of the array to put to the server.
- - iterBetweenCreateChannel
- - The number of iterations between destroying and recreating the channel.
- A value of 0 means never destroy and recreate.
-
- - iterBetweenCreateChannelPut
- - The number of iterations between destroying and recreating the channelPut.
- A value of 0 means never destroy and recreate.
-
- - delayTime
- - The time to delay between gets.
-
-
-Some results
-array performance
-The results were from my laptop in 2013
-It had a 2.2Ghz intel core i7 with 4Gbytes of memory.
-The operating system was linux fedora 16.
-When test are performed with large arrays it is a good idea to also
-run a system monitor facility and check memory and swap history.
-If a test configuration causes physical memory to be exhausted
-then performance becomes very poor.
-You do not want to do this.
-arrayPerformance results
-The simplest test to run arrayPerformance with the defaults:
-
-mrk> pwd
-/home/hg/pvDatabaseCPP-md
-mrk> bin/linux-x86_64/arrayPerformanceMain
-
-This means that the array will hold 10 million elements.
-The delay will be a millisecond.
-There will be a single monitor and it will connect directly
-to the local channelProvider, i. e. it will not use any network
-connection.
-The report shows that arrayPerformance can perform about 50 iterations per second
-and is putting about 500million elements per second.
-Since each element is an int64 this means about 4gigaBytes per second.
-
-When no monitors are requested and a remote longArrayMonitorMain is run:
-
-mr> pwd
-/home/hg/pvDatabaseCPP-md
-mrk> bin/linux-x86_64/longArrayMonitorMain
-
-The performance drops to about 25 iterations per second and 250 million elements per second.
-The next section has an example that demonstrates what happens.
-Note that if the array size is small enough to fit in the local cache then running longArrayMonitor
-has almost no effect of arrayPerforance.
-
-memory leaks
-Running longArrayMonitorMain, longArrayPutMain, and longArrayGetMain
-under valgrind shows no memory leaks.
-arrayPerformanceMain shows the following:
-
-==9125== LEAK SUMMARY:
-==9125== definitely lost: 0 bytes in 0 blocks
-==9125== indirectly lost: 0 bytes in 0 blocks
-==9125== possibly lost: 576 bytes in 2 blocks
-
-The possibly leaked is either 1 or 2 blocks.
-It seems to be the same if clients are connected.
-
-Vector Performance
-This example demonstrates how array size effects performance.
-The example is run as:
-
-bin/linux-x86_64/vectorPerformanceMain -help
-vectorPerformanceMain size delay nThread
-default
-vectorPerformance 50000000 0.01 1
-
-Consider the following:
-
-bin/linux-x86_64/vectorPerformanceMain 50000000 0.00 1
-...
-thread0 value 20 time 1.01897 iterations/sec 19.6277 elements/sec 981.383million
-thread0 value 40 time 1.01238 iterations/sec 19.7554 elements/sec 987.772million
-thread0 value 60 time 1.00878 iterations/sec 19.826 elements/sec 991.299million
-...
-bin/linux-x86_64/vectorPerformanceMain 50000000 0.00 2
-...
-thread0 value 21 time 1.00917 iterations/sec 9.90911 elements/sec 495.455million
-thread1 value 31 time 1.05659 iterations/sec 9.46443 elements/sec 473.221million
-thread0 value 31 time 1.07683 iterations/sec 9.28648 elements/sec 464.324million
-thread1 value 41 time 1.0108 iterations/sec 9.89312 elements/sec 494.656million
-...
-bin/linux-x86_64/vectorPerformanceMain 50000000 0.00 3
-thread0 value 7 time 1.0336 iterations/sec 6.77244 elements/sec 338.622million
-thread1 value 7 time 1.03929 iterations/sec 6.73534 elements/sec 336.767million
-thread2 value 7 time 1.04345 iterations/sec 6.70852 elements/sec 335.426million
-thread0 value 14 time 1.03335 iterations/sec 6.77406 elements/sec 338.703million
-thread1 value 14 time 1.03438 iterations/sec 6.76734 elements/sec 338.367million
-thread2 value 14 time 1.04197 iterations/sec 6.71805 elements/sec 335.903million
-...
-bin/linux-x86_64/vectorPerformanceMain 50000000 0.00 4
-thread2 value 5 time 1.00746 iterations/sec 4.96298 elements/sec 248.149million
-thread1 value 5 time 1.02722 iterations/sec 4.86751 elements/sec 243.376million
-thread3 value 5 time 1.032 iterations/sec 4.84496 elements/sec 242.248million
-thread0 value 6 time 1.18882 iterations/sec 5.04703 elements/sec 252.351million
-thread2 value 10 time 1.00388 iterations/sec 4.98068 elements/sec 249.034million
-thread3 value 10 time 1.02755 iterations/sec 4.86592 elements/sec 243.296million
-thread1 value 10 time 1.04836 iterations/sec 4.76936 elements/sec 238.468million
-thread0 value 11 time 1.01575 iterations/sec 4.92249 elements/sec 246.124million
-
-As more threads are running the slower each thread runs.
-But now consider a size that fits in a local cache.
-
-bin/linux-x86_64/vectorPerformanceMain 5000 0.00n/linux-x86_64/vectorPerformanceMain 5000 0.00 1
-...
-thread0 value 283499 time 1 iterations/sec 283498 elements/sec 1417.49million
-thread0 value 569654 time 1 iterations/sec 286154 elements/sec 1430.77million
-thread0 value 856046 time 1 iterations/sec 286392 elements/sec 1431.96million
-...
-bin/linux-x86_64/vectorPerformanceMain 5000 0.00 2
-...
-thread0 value 541790 time 1 iterations/sec 271513 elements/sec 1357.56million
-thread1 value 541798 time 1 iterations/sec 271418 elements/sec 1357.09million
-thread0 value 813833 time 1 iterations/sec 272043 elements/sec 1360.21million
-thread1 value 813778 time 1 iterations/sec 271979 elements/sec 1359.89million
-thread0 value 541790 time 1 iterations/sec 271513 elements/sec 1357.56million
-thread1 value 541798 time 1 iterations/sec 271418 elements/sec 1357.09million
-thread0 value 813833 time 1 iterations/sec 272043 elements/sec 1360.21million
-thread1 value 813778 time 1 iterations/sec 271979 elements/sec 1359.89million
-...
-bin/linux-x86_64/vectorPerformanceMain 5000 0.00 3
-...
-thread0 value 257090 time 1 iterations/sec 257089 elements/sec 1285.45million
-thread1 value 256556 time 1 iterations/sec 256556 elements/sec 1282.78million
-thread2 value 514269 time 1 iterations/sec 257839 elements/sec 1289.19million
-thread0 value 514977 time 1 iterations/sec 257887 elements/sec 1289.43million
-thread1 value 514119 time 1 iterations/sec 257563 elements/sec 1287.81million
-thread2 value 770802 time 1 iterations/sec 256532 elements/sec 1282.66million
-
-Now the number of threads has a far smaller effect on the performance of each thread.
-
-
-
-
-Abstract
-
-This document describes pvDatabaseCPP,
-which is a framework for implementing a network accessable database of smart memory resident
-records. Network access is via pvAccess. The data in each record is a top level PVStructure as defined by
-pvData. The framework includes a complete implementation of ChannelProvider as defined by pvAccess.
-The framework must be extended in order to create record instances.
-The minimum that an extenson must provide is a top level PVStructure and a process method
-but the framework provides for complex extensions.
-
-EPICS version 4 is a set of related products in the EPICS
-V4 control system programming environment:
-relatedDocumentsV4.html
-
-
-Status of this Document
-
-This is the 27-Nov-2012 version of the definition of pvDatabaseCPP.
-This is the original version.
-
-This is the beginning of the implementation of pvDataBaseCPP.
-It describes the features that will be provided.
-The class definitions for PVRecord and PVDatabase are defined but not implemented.
-
-
-
-
Table of Contents
-
-
-
-
-
Introduction
-
Overview
-
This document descibes a C++ implementation of some of the components in pvIOCJava.
-It extracts the core components required to create a network accessible database of smart
-memory resident records.
-pvDatabaseCPP does not and will not implement any of the specialized support that pvIOCJava
-provides. Instead other projects will implement the specialized support.
-It is expected that many services will be created that do not require the full features provided
-by pvIOCJava. In the future pvIOCJava should be split into multiple projects with one of
-them named pvDatabaseJava.
-
-
-
A brief description of a pvDatase is that it is a network accessible set of smart memory resident
-records. Each record has data composed of a top level PVStructure. Each record has a name which is
-the channelName for pvAccess. A local Channel Provider implements the complete ChannelProvider and
-Channel interfaces as defined by pvAccess.
-This local provider is accessed by the remote pvAccess server.
-A record is smart because code can be attached to a record.
-
This document describes components that provides the following features:
-
- - database
-
-
- This encapsulates the concept of a database of memory resident smart records.
- The two main components are:
-
- - pvRecord
- - This encapsulates the concept of a smart record. It can be processed.
- Changes to field values can be trapped. A record can be locked.
- - pvDatabase
-
-
- This is a database of pvRecords.
- Records can be added and removed from a database.
-
- - localChannelProvider
- - This is a complete implementation of ChannelProvider and Channel as defined by pvAccess.
- It is used by the server side of pvAccess to attach to pvRecords.
- This component also includes the monitor and pvCopy components from pvIOCJava
-
-
database does not itself implement pvRecord instances.
-Instead it provides a base classes that make it easy to create record instances.
-What does have to be implemented is a top
-level PVStructure and the following two methods:
-
- - process
- - This is what makes a record smart.
- What process does is up to the implementation except that it must decide if
- it's execution model is synchronous or asynchronous.
- Synchronous means that when process returns the processing is complete.
- Asynchronous means that when process returns the processing is not complete.
- Instead process invokes other threads that will complete the processing at a later time.
- - isSynchronous
- - Which execution model is being implemented.
-
-
Example PVRecord Extension
-
Directory example/record has an example PVRecord implementation.
-It implements a counter.
-The top level structure is:
-
-structure
- long value
-
-
NOTE: The example compiles but does not build because nothing
-is implemented.
-
-
exampleRecord.h
-
This is the class description.
-The example extends PVRecord.
-
-class ExampleRecord :
- public virtual PVRecord
-{
-public:
- POINTER_DEFINITIONS(ExampleRecord);
- static PVRecordPtr create(epics::pvData::String const & recordName);
- virtual ~ExampleRecord();
- virtual bool isSynchronous();
- virtual void process(
- epics::pvDatabase::RecordProcessRequesterPtr const &processRequester);
-private:
- ExampleRecord(epics::pvData::String const & recordName,
- epics::pvData::PVStructurePtr const & pvStructure,
- epics::pvData::PVLongPtr const &pvValue);
- epics::pvData::PVLongPtr pvValue;
-};
-
-
where
-
- - create
-
-
- This is example specific. See the implemention for details.
- - ~ExampleRecord
-
-
- The destructor must be declared virtual.
- - isSynchronous
-
-
- The implementation must say if process is synchronous or asynchronous.
- - process
-
-
- The implementation.
- - ExampleRecord
-
-
- For the example this is private.
-
-
-exampleRecord.cpp
-This is the class implementation.
-
-ExampleRecord::~ExampleRecord(){}
-
-PVRecordPtr ExampleRecord::create(String const & recordName)
-{
- String properties;
- PVStructurePtr pvStructure = getStandardPVField()->scalar(pvLong,properties);
- PVLongPtr pvValue = pvStructure->getLongField("value");
- PVRecordPtr pvRecord(new ExampleRecord(recordName,pvStructure,pvValue));
- return pvRecord;
-}
-
-ExampleRecord::ExampleRecord(
- String const & recordName,
- PVStructurePtr const & pvStructure,
- PVLongPtr const &pvValue)
-: PVRecord(recordName,pvStructure),
- pvValue(pvValue)
-{}
-
-bool ExampleRecord::isSynchronous() {return true;}
-
-void ExampleRecord::process(
- RecordProcessRequesterPtr const &processRequester)
-{
- pvValue->put(pvValue->get() + 1);
- processRequester->recordProcessResult(Status::Ok);
- processRequester->recordProcessComplete();
-}
-
-where
-
- - create
-
-
- Creates a PVStructure with a single subfield named value.
- It gets the interface to the value field.
- It then creates an ExampleRecord and returns it.
-
- - ~ExampleRecord
-
-
- Does not have to do anything because of shared pointers.
- - ExampleRecord
-
-
- Calls the base class constructor and sets pvValue.
- - isSynchronous
-
-
- The example is synchronous.
- - process
-
-
- Gets the curent value, increments it, and puts the new value.
- It than calls two processRequester callbacks.
-
-
-exampleRecordMain.cpp
-This is a main for creating and running the example.
-
-int main(int argc,char *argv[])
-{
- String recordName("exampleRecord");
- PVRecordPtr pvRecord = ExampleRecord::create(recordName);
- PVDatabasePtr pvDatabase = PVDatabase::getMaster();
- pvDatabase->addRecord(pvRecord);
- cout << recordName << "\n";
- string str;
- while(true) {
- cout << "Type exit to stop: \n";
- getline(cin,str);
- if(str.compare("exit")==0) break;
-
- }
- return 0;
-}
-
-The main program creates an example record and adds it to the database.
-It then runs until the process is stopped by typing exit.
-
Until the process is stopped,
-pvAccess clients can put and get the value field.
-For example
-
-pvget exampleRecord
-pvput exampleRecord 5
-
-Will both work.
-Phased Development
-This documentation describes the first phase of a phased implementation of pvDatabaseCPP:
-
- - pvRecord
-
- Wrapper on PVStructure that implements methods required by Local Channel Provider.
- - pvDatabase
-
- Database of PVRecords. Has methods find, add, and remove.
- - Local Channel Provider
- - These two features will be the first phase.
- But only synchronous record processing will be supported.
-
-Future phases of pvDatabaseCPP should include:
-
- - Install
- - This provides on-line add and delete.
- - Field support
- - Add ability to optionally add support to fields.
- In addition some of the basic support defined in pvIOCJava will also be implemented.
- - XML parser
- - This provides the ability to create record instances without writing any code.
-
-The completion of each phase provides useful features that can be used without waiting for the
-completion of later phases.
-The rest of this document discusses only the first phase.
-Features Required for localChannelProvider
-
- - pvCopy
- - Creates a PVStructure that contains a copy of an arbitary
- subset of the fields of another top level PVStructure.
- It can copy data between the two and maintains a bitSet that show
- which fields are changed.
-
-
- monitor
- - This provides the ability to monitor changes to fields of a record.
- - PVRecord and PVDatabase
- - Defined below.
- - local ChannelProvider
- - This is the pvAccess package in pvIOCJava.
- The localChannelProvider will access data from PVRecords.
- It will implement all channel methods except channelRPC.
-
-Minumum Features Required for pvRecord
-The first phase will only implement record processing, i. e.
-the process method has to do everything itself without any generic field support.
-This will be sufficient for starting to implement services.
-The following are the minimium features required
-
- - PVDatabase
- - This holds a set of PVRecords. It has methods to find, add, and remove records.
- - PVRecord
- - This, and a set of related interfaces, provide the following:
-
- - PVStructure
- - PVRecord is a wrapper on a top level pvStructure.
- - Record locking
- - A record can be locked and unlocked.
- A record must be locked whenever data in the pvStructure is accessed.
- - Trapping data changes
- - A client can request to be notified when data in the pvStructure is modified.
- It can do this on a field by field basis.
-
-
-
-The following sections provide a first attempt to describe the classes required for the first
-phase.
-The last section gives a brief overview of the features provided by pvIOCJava.
-
-database
-The classes in pvDatabase.h implement a database of memory resident
-smart records. The next subsection has the definitions for all the classes
-defined in this header file.
-It describes the following classes:
-
- - PVRecord
- - This provides the methods required by localChannelProvider to implement Channel.
- - PVRecordField
- - PVRecordStructure
- - These wrap PVField and PVStructure so that pvCopy and monitor can be implemented.
- - PVListener
- - This is implemented by anything that wants to trap calls to the PVRecord::message.
- - RecordProcessRequester
- - This is implemented by anything that calls PVRecord::queueProcessRequest.
- - PVRecordClient
- - This is called by anything that acceses PVRecord.
- - PVDatabase
- - This is a database of PVRecords.
-
-Each class is described in a separate subsection.
-
-class PVRecord
-
-class PVRecord
-{
-public:
- POINTER_DEFINITIONS(PVRecord);
- PVRecord(
- epics::pvData::String const & recordName,
- epics::pvData::PVStructurePtr const & pvStructure);
- virtual ~PVRecord();
- virtual void process(
- RecordProcessRequesterPtr const &recordProcessRequester) = 0;
- virtual bool isSynchronous() = 0;
- epics::pvData::String getRecordName();
- PVRecordStructurePtr getPVRecordStructure();
- PVRecordFieldPtr findPVRecordField(
- epics::pvData::PVFieldPtr const & pvField);
- void lock();
- void unlock();
- void registerClient(PVRecordClientPtr const & pvRecordClient);
- void unregisterClient(PVRecordClientPtr const & pvRecordClient);
- void detachClients();
- void beginGroupPut();
- void endGroupPut();
- void registerListener(PVListenerPtr const & pvListener);
- void unregisterListener(PVListenerPtr const & pvListener);
- void removeEveryListener();
- epics::pvData::Status processRequest();
- void queueProcessRequest(
- RecordProcessRequesterPtr const &recordProcessRequester);
- void addRequester(epics::pvData::RequesterPtr const & requester);
- void removeRequester(epics::pvData::RequesterPtr const & requester);
- void message(
- epics::pvData::String const & message,
- epics::pvData::MessageType messageType);
- epics::pvData::String toString();
- epics::pvData::String toString(int indentLevel);
-};
-
-The methods are:
-
- - PVRecord
- - The constructor. It requires a recordName and a top level PVStructure.
- - ~PVRecord
- - The desctructor which must be virtual. A derived class must also have
- a virtual destructor.
- - process
- - Pure virtual method. Derived classes must implement this method.
- - isSynchronous
- - Pure virtual method. Derived classes must implement this method.
- - getRecordName
- - Return the recordName.
- - getPVRecordStructure
- - Get the top level PVStructure.
- - findPVRecordField
- - Given a PVFieldPtr return the PVRecordFieldPtr for the field.
- - lock
- - unlock
- - Lock and Unlock the record.
- Any code accessing the data in the record or calling other PVRecord methods
- must have the record locked.
- - registerClient
- - Every client that accesses the record must call this so that the client can be notified when the record is deleted.
- - unregisterClient
- - Client is no longer accessing the record.
- - detachClients
- - Ask all clients to detach from the record
- - beginGroupPut
- - Begin a group of puts. This results in all registered PVListeners being called
- - endGroupPut
- - End a group of puts. This results in all registered PVListeners being called.
- - registerListener
- - Register a PVListener. This must be called before calling pvRecordField.addListener.
- - unregisterListener
- - Unregister a listener. The listener will also be removed from all fields to which it is attached.
- - removeEveryListener
- - This must be called by any code that is deleting or changing the structure of a record.
- - processRequest
- - This is a convenience method for clients that are willing to block if
- process is asynchronous. It implements RecordProcessRequester.
- If process is synchronous it just calls process and returns the result
- to the caller. If process is asynchronous it calls queueProcessRequest,
- and process and waits for completion and then returns the result to the caller.
- - queueProcessRequest
- - Queue a process request.
- - addRequester
- - Add a requester to receive messages.
- - removeRequester
- - Remove a message requester.
- - message
- - Can be called by implementation code.
- The message will be sent to every requester.
-
-class PVRecordField
-
-class PVRecordField {
-public:
- POINTER_DEFINITIONS(PVRecordField);
- PVRecordField(
- epics::pvData::PVFieldPtr const & pvField,
- PVRecordPtr const & pvRecord);
- virtual ~PVRecordField();
- PVRecordStructurePtr getParent();
- epics::pvData::PVFieldPtr getPVField();
- epics::pvData::String getFullFieldName();
- epics::pvData::String getFullName();
- PVRecordPtr getPVRecord();
- bool addListener(PVListenerPtr const & pvListener);
- void removeListener(PVListenerPtr const & pvListener);
- void postPut();
- virtual void message(
- epics::pvData::String const & message,
- epics::pvData::MessageType messageType);
-};
-
-When PVRecord is created it creates a PVRecordField for every field in the PVStructure
-that holds the data. It has the following methods:
-
-
-
- - PVRecordField
- - The constructor.
- - ~PVRecordField
- - The destructor.
- - getParent
- - Get the parent PVRecordStructure for this field.
- - getPVField
- - Get the PVField associated with this PVRecordField.
- - getFullFieldName
- - This gets the full name of the field, i.e. field,field,..
- - getFullName
- - This gets recordName plus the full name of the field, i.e. recordName.field,field,..
- - getPVRecord
- - Returns the PVRecord to which this field belongs.
- - addListener
- - Add A PVListener to this field.
- Whenever this field or any subfield if this field is modified the listener will be notified.
- PVListener is described below.
- Before a listener can call addListener it must first call PVRecord.registerListener.
- - removeListener
- - Remove a PVListener.
- - postPut
- - This is called by the code that implements the data interface.
- It is called whenever the put method is called.
- - message
- - Called by implementation code. It calls PVRecord::message after prepending the full
- fieldname.
-
-class PVRecordStructure
-
-class PVRecordStructure : public PVRecordField {
-public:
- POINTER_DEFINITIONS(PVRecordStructure);
- PVRecordStructure(
- epics::pvData::PVStructurePtr const & pvStructure,
- PVRecordFieldPtrArrayPtr const & pvRecordField);
- virtual ~PVRecordStructure();
- PVRecordFieldPtrArrayPtr getPVRecordFields();
- epics::pvData::PVStructurePtr getPVStructure();
- virtual void message(
- epics::pvData::String const & message,
- epics::pvData::MessageType messageType);
-};
-
-When PVRecord is created it creates a PVRecordStructure for every structure field in the PVStructure
-that holds the data. It has the following methods:
-
-
- - PVRecordStructure
- - The constructor.
- - ~PVRecordStructure
- - The destructor.
- - getPVRecordFields
- - Get the PVRecordField array for the subfields
- - getPVStructure
- - Get the PVStructure for this field.
- - message
- - Called by implementation code. It calls PVRecord::message after prepending the full
- fieldname.
-
-class PVListener
-
-class PVListener {
-public:
- POINTER_DEFINITIONS(PVListener);
- virtual ~PVListener();
- virtual void dataPut(PVRecordFieldPtr const & pvRecordField) = 0;
- virtual void dataPut(
- PVRecordStructurePtr const &
- requested,PVRecordFieldPtr const & pvRecordField) = 0;
- virtual void beginGroupPut(PVRecordPtr const & pvRecord) = 0;
- virtual void endGroupPut(PVRecordPtr const & pvRecord) = 0;
- virtual void unlisten(PVRecordPtr const & pvRecord) = 0;
-};
-
-where
-
- - ~PVListener
- - The destructor.
- - dataPut(PVRecordFieldPtr const & pvRecordField)
- - pvField has been modified.
- This is called if the listener has called PVRecordField::addListener for pvRecordField.
- - dataPut(
- PVRecordStructurePtr const &
- requested,PVRecordFieldPtr const & pvRecordField)
- - pvField has been modified.
- Requested is the field to which the requester issued a pvField-&addListener.
- This is called if the listener has called PVRecordField-&addListener for requested.
- - beginGroupPut
- - A related set of changes is being started.
- - endGroupPut
- - A related set of changes is done.
- - unlisten
- - The PVLister is being removed from the record.
- This is called when the record is being destroyed or when the record structure
- (not the data values) is being changed.
-
-class RecordProcessRequester
-
-class RecordProcessRequester :
- virtual public epics::pvData::Requester
-{
-public:
- POINTER_DEFINITIONS(RecordProcessRequester);
- virtual ~RecordProcessRequester();
- virtual void becomeProcessor() = 0;
- virtual void recordProcessResult(epics::pvData::Status status) = 0;
- virtual void recordProcessComplete() = 0;
-};
-
-where
-
- - ~RecordProcessRequester
- - The destructor.
- - becomeProcessor
- - Called as a result of queueRequeProcessst. The requester can the call process.
- - recordProcessResult
- - The results of record processing.
- This is called with the record locked so that the process requester
- can access data from the record.
- - recordProcessComplete
- - Processing is complete.
- This is called with the record unlocked.
- If the process requester called process with leaveActive true then the requester
- must call setInactive.
-
-class PVRecordClient
-
-class PVRecordClient {
- POINTER_DEFINITIONS(PVRecordClient);
- virtual ~PVRecordClient();
- virtual void detach(PVRecordPtr const & pvRecord);
-};
-
-where
-
- - ~PVRecordClient
- - The destructor.
- - detach
- - The record is being removed from the master database,
-
-class PVDatabase
-
-class PVDatabase : virtual public epics::pvData::Requester {
-public:
- POINTER_DEFINITIONS(PVDatabase);
- static PVDatabasePtr getMaster();
- virtual ~PVDatabase();
- PVRecordPtr findRecord(epics::pvData::String const& recordName);
- bool addRecord(PVRecordPtr const & record);
- bool removeRecord(PVRecordPtr const & record);
-private:
- PVDatabase();
-};
-
-where
-
- - getMaster
- - Get the master database. This is the database that localChannelProvider access.
- - ~PVDatabase
- - The destructor.
- - findRecord
- - Find a record. An empty pointer is returned if the record is not in the database.
- - addRecord
- - Add a record to the database.
- If the record already exists it is not modified and false is returned.
- - removeRecord
- - Remove a record from the database.
- If the record was not in the database false is returned.
-
-Local Channel Provider
-Not yet described.
-A brief description is that it must implement the following components of pvIOCJava:
-
- - pvCopy
- - monitor
- - pvAccess
- - See the next section for a description
-
-Summary of Packages in pvIOCJAVA
-The following are the direct sub packages of pvIOCJava/src/org/epics/pvioc:
-
- - pvCopy
- - This provides a copy of an arbitrary subset of the fields in a PVRecord.
- It also provides the ability to detect and report changes to fields.
- It is required for pvAccess.
- - monitor
- - This provides the ability to monitor changes to a PVRecord. It is required for pvAccess monitors.
- - pvAccess
- - The local implementation of Channel Provider and Channel.
- It is accessed by the remote pvAccess server and can also be accessed by code in the same IOC.
- - database
- - This defines and implements PVRecord, PVDatabase , and PVListener.
- It supports the basic feature required the implement a local Channel Provider.
- - support
- - This provides the ability to optionally attach code to any field of a pvRecord.
- It and several sub packages provide a set of standard support modules.
- - install
- - This provides the ability to dynamically initialize and add new PVRecords. It also provides
- the ability to dynamicall delete PVRecords.
-
- xml
- - This provides the ability to configure record instances without writing code.
- - util
- - This is misnamed since it is code related to scanning.
- - pdrv
- - This is portDriver, which is a proposed sucessor to the asynManager component of asynDriver.
- - swtshell
- - This is shell that is can either run under the same process as a JavaIOC or as a remote shell.
- It is like a version of probe but for pvData/pvAccess.
- Almost all of it's features work in either local or remote mode.
- With a little more work all or it's features could work remotely.
- This should be done and then only remote mode should be supported.
- It can then be rewritten in a completely different language and using a complely different GUI
- framework.
-
- - caV3
- - This has two components:
-
- - ClientFactory
- - This is a small wrapper on top of the caV3 client support implemented by pvAccess.
- It allows code in the pvIOC to access V3Records via pvAccess.
- - ServerFactory
- - This is a caV3 server that allows a caV3 client to access a PVRecord.
- The Java implementation uses CAJ, which does most of the work.
- For now it will not be discussed in this document.
-
-
- - v3a
- - I do not know what this is.
-
-In addition there is one class file JavaIOC.java.
-This is starting a IOC instance.
-This is not required for pvIOCCPP which is either a main or runs as part of a V3 IOC.
-
-
-
diff --git a/documentation/pvDatabaseCPP_20121127.html b/documentation/pvDatabaseCPP_20121127.html
deleted file mode 100644
index c53af75..0000000
--- a/documentation/pvDatabaseCPP_20121127.html
+++ /dev/null
@@ -1,714 +0,0 @@
-
-
-
-