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 This product is made available subject to acceptance of the EPICS open source license. EPICS version 4 is a set of related products in the EPICS
-V4 control system programming environment: For more information about EPICS generally, please refer to the home page of the Experimental Physics and Industrial
+ Control System. This is the 23-October-2015 version of of pvDatabaseCPP. This version is a complete implementation of what is described in this manual.
- The main purpose of this project to make it easier to implement services that are accessed via pvAccess.
-This project supplies a complete implementation of the server side of pvAccess.
-All that a service has to provide is a top level PVStructure and a process method.
+
+This project supplies a complete implementation of the server side of pvAccess,
+which has the provider name local.
+
+A service must provide a top level PVStructure and a process method.
A service can be run as a main process or can be part of a V3 IOC.
Thus services can be developed that interact with V3 records, asynDriver,
areaDetector, etc.
@@ -151,104 +132,10 @@ level PVStructure and the following three methods: 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: You should see something like the following: Then in another window execute a pvput and pvget as follows: To run the example as part of a V3 IOC do the following: You will see the following: 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. To build pvDatabaseCPP You must provide a file RELEASE.local
-in directory configure.
-Thus do the following:
+If a proper RELEASE.local is present one directory level above pvDatabaseCPP.
+
+Just type:
+
+An example of a proper RELEASE.local is:
+ pvDatabaseCPP can also be built if a file RELEASE.local exists in directory configure.
+To create one do the following: This builds pvDatabaseCPP and also the tests and all examples. Each example and arrayPerformance 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:
-If it is desired to build an example all by itself,
-just follow the same instructions as for building pvDatabaseCPP itself.
-For example: 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: This builds the example. Shell commands are made available via the standard DBD include mechanism
provided by iocCore.
The following provide EPICS V4 shell commands:
-Look at exampleServer/ioc/src/exampleServerInclude.dbd for an example
-of how an application can make the shell commands available.
- The following iocsh commands are provided for a V3IOC: The following iocsh commands are provided for a V3IOC: pvDatabaseCPP provides the following iocshell command. 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. 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:
- The implementation is a complete implementation of channelProvider
-and channel except for channelRPC, which is implement by pvAccess as a separate
-channel provider. The following provides a brief description of each channel method that
is implemented. Needs to be described. Implements channelProcess. Needs to be described. Implements channelGet. Needs to be described. Implements channelPut. Needs to be described. Implements channelPutGet. Needs to be described. Implements channelArray. Implements channelRPC. This is the code that implements monitors on changes to fields of a PVRecord.
Because it is called by pvAccess client (monitor methods) and by
@@ -1006,11 +856,8 @@ active element but never modifies the pvStructure.
This section provides two useful record support modules
-and one that is used for testing. This implements a PVRecord that allows a client to set
-the trace level of a record. It follows the pattern of a channelPutGet
+ This section provides traceRecord which implements a PVRecord that allows a client to set
+the trace level of another PVRecord. It follows the pattern of a channelPutGet
record: The example implements a simple service that has a top level pvStructure:
- 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:
-The directory layout is:
- If only a main program is desired then the directory layout is: 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. The example resides in src
-The implementation is in exampleServer.cpp.
- The description consists of where The implementation of create method is: The private constructor method is: The destructor and destroy methods are: The implementation of init is: The implementation of process is: 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: To start exampleServer as part of a V3IOC: You can then issue the commands dbl and pvdbl:
-It starts pvaSrv so that the V3 records can be accessed via Channel Access
-or via PVAccess. The exampleServer pvDatabase has many records including the following: 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. 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. The process routine of a PVRecord can access other PVRecords in two ways: Access via pvAccess can be done either by local or remote channel provider. 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. 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: 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.
-Once the client and local provider code has started then the following creates a channel access link.
- 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: then in another window: exampleLink.h contains the following: 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: 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: This first makes sure the pvStructure has the fields it requires: 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. This is an example of creating a service that requires a somewhat complicated
-top level PVStructure.
-Look at the code for details.
- 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.
- The programs are: Each has support for -help. 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: Each program generates a report every second when it has something to report.
-Examples are: The arguments for arrayPerforamanceMain are:
-arrayPerformance creates a PVRecord that has the structure:.
- The record has support that consists of a separate thread that runs
-until the record is destroyed executing the following algorithm: 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: This is a pvAccess client that uses channelGet to access an arrayPerformance record.
-Every second it produces a report. The arguments for longArrayGetMain are: This is a pvAccess client that uses channelPut to access an arrayPerformance record.
-Every second it produces a report. The arguments for longArrayPutMain are: 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. The simplest test to run arrayPerformance with the defaults: 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: 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.
- Running longArrayMonitorMain, longArrayPutMain, and longArrayGetMain
-under valgrind shows no memory leaks. arrayPerformanceMain shows the following: The possibly leaked is either 1 or 2 blocks.
-It seems to be the same if clients are connected.
- This example demonstrates how array size effects performance.
-The example is run as: Consider the following: As more threads are running the slower each thread runs. But now consider a size that fits in a local cache. Now the number of threads has a far smaller effect on the performance of each thread.
-pvDatabaseCPP
-
+Release 4.2 - 2016.01.12
-EPICS v4 Working Group, Working Draft, 23-October-2015
-
-
-
-
Abstract
@@ -69,31 +48,33 @@ 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.
-
-
-relatedDocumentsV4.html
-Status of this Document
-
-Table of Contents
+ Table of Contents
Introduction
Overview
Getting started
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer
-mrk> bin/linux-x86_64/exampleServerMain
-
-
-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:
-
-
-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>
-
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer/iocBoot/exampleServer
-mrk> ../../bin/linux-x86_64/exampleServer st.cmd
-
-
-> 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>
-
-Features Required for localChannelProvider
@@ -300,9 +187,34 @@ to learn how to implement a service.
Building pvDatabaseCPP
-
+make
+
+
+EPICS4_DIR=/home/epicsv4/master
+EXAMPLE=${EPICS4_DIR}/exampleCPP
+PVDATABASE=${EPICS4_DIR}/pvDatabaseCPP
+PVACLIENT=${EPICS4_DIR}/pvaClientCPP
+PVASRV=${EPICS4_DIR}/pvaSrv
+PVACCESS=${EPICS4_DIR}/pvAccessCPP
+NORMATIVETYPES=${EPICS4_DIR}/normativeTypesCPP
+PVDATA=${EPICS4_DIR}/pvDataCPP
+PVCOMMON=${EPICS4_DIR}/pvCommonCPP
+
+EPICS_BASE=/home/install/epics/base
+
+
+
mrk> pwd
/home/hg/pvDatabaseCPP/configure
@@ -314,94 +226,31 @@ Than at the top level just execute make:
mrk> cd ..
mrk> pwd
-/home/hg/pvDatabaseCPP
+/home/epicsv4/master/pvDatabaseCPP
mrk> make
-
-
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer/configure
-mrk> cp ExampleRELEASE.local RELEASE.local
-
-
-mrk> cd ..
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer
-mrk> make
-
-iocshell commands
-
-Commands From pvAccessCPP
-
-
+
+pvAccessCPP
+pvaSrv
+pvDatabaseCPP
+
-Commands implemented by pvDatabaseCPP
-
+
Commands implemented by pvaSrv
-
-include "dbPv.dbd"
-
+Look at any of the examples in exampleCPP to see how to implement shell commands.
database
src/database
@@ -838,20 +687,21 @@ It uses the copy and monitor facilities from pvDataCPP and connects
them to a PVRecord.
channelProcessLocal
-channelGetLocal
-channelPutLocal
-channelPutGetLocal
-channelArrayLocal
-ChannelRPCLocal
+MonitorLocal
special
-traceRecord
-
traceRecord
@@ -1054,950 +901,6 @@ result = master->addRecord(pvRecord);
if(!result) cout<< "record " << recordName << " not added" << endl;
-exampleServer
-Overview
-
-structure
- structure argument
- string value
- structure result
- string value
- time_t timeStamp
- long secondsPastEpoch
- int nanoseconds
- int userTag
-
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleService
-mrk> bin/linux-x86_64/exampleService
-
-Directory Layout
-
-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
-
-
-
-exampleServerCreateRecord exampleServer
-
- Multiple commands can be issued to create multiple service records.
-
-exampleServer
- configure
- ExampleRELEASE.local
- ...
- src
- exampleServer.h
- exampleServer.cpp
- exampleServerMain.cpp
-
-exampleServer.h
-
-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;
-};
-
-
-
-
-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:
-
-
-
-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.
-
-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.
-
-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;
-}
-
-
-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
-
-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:
-
-
-V3IOC exampleServer
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleServer/iocBoot/exampleServer
-mrk> ../../../bin/linux-x86_64/exampleServer st.cmd
-
-
-epics> dbl
-pvdouble
-pvcounter
-pvenum
-pvdoubleArray
-pvstringArray
-epics> pvdbl
-exampleServer
-epics>
-
-dbl shows the V3 records.
-pvdbl shows the pvRecords.
-exampleDatabase
-
-
-exampleLink
-Discussion
-Access Alternatives
-
-
-
-
-Data synchronization
-Some details
-
- ClientFactory::start();
- ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
- ...
- ServerContext::shared_pointer serverContext =
- startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
-
-
-...
-iocInit()
-startPVAClient
-startPVAServer
-## commands to create pvRecords
-
-
-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
- ...
-
-
-mrk> pwd
-/home/hg/pvDatabaseCPP/exampleLink/iocBoot/exampleLink
-mrk> ../../bin/linux-x86_64/exampleLink st.local
-
-
-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
-
-...
-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:
-...
-
-
-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;
-}
-
-
-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;
-}
-
-
-
-examplePowerSupply
-Array Performance and Memory Example
-Brief Summary
-
-
-
-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
-
-bin/linux/<arch>/arrayPerformanceMain
-bin/linux/<arch>/longArrayMonitorMain
-bin/linux/<arch>/longArrayGetMain
-bin/linux/<arch>/longArrayPutMain
-
-
-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
-
-
-
-recordName
- long[] value
- timeStamp timeStamp
- alarm alarm
-
-Thus it holds an array of 64 bit integers.
-
-
-longArrayMonitor
-
-
-longArrayGet
-
-
-longArrayPut
-
-
-
-Some results
-array performance
-arrayPerformance results
-
-mrk> pwd
-/home/hg/pvDatabaseCPP-md
-mrk> bin/linux-x86_64/arrayPerformanceMain
-
-
-mr> pwd
-/home/hg/pvDatabaseCPP-md
-mrk> bin/linux-x86_64/longArrayMonitorMain
-
-memory leaks
-
-==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
-
-Vector Performance
-
-bin/linux-x86_64/vectorPerformanceMain -help
-vectorPerformanceMain size delay nThread
-default
-vectorPerformance 50000000 0.01 1
-
-
-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
-
-
-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
-
-
This product is made available subject to acceptance of the EPICS open source license.
-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
-
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.
- - -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 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:
-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.
- -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
-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
-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.
-This documentation describes the first phase of a phased implementation of pvDatabaseCPP: -
Future phases of pvDatabaseCPP should include:
-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.
-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
-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.
- -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:
-Each class is described in a separate subsection.
- --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: -
-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: -
- --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: -
--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
--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
--class PVRecordClient { - POINTER_DEFINITIONS(PVRecordClient); - virtual ~PVRecordClient(); - virtual void detach(PVRecordPtr const & pvRecord); -}; --
where
--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
-Not yet described.
-A brief description is that it must implement the following components of pvIOCJava:
-The following are the direct sub packages of pvIOCJava/src/org/epics/pvioc:
-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 @@ - - - -
- -
- - - - - - - -
-