Compare commits
72 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f5bfd067f | ||
|
|
85165e6579 | ||
|
|
476a8f1e32 | ||
| 31e883dbbc | |||
| 57cbf66833 | |||
| 7f31332a80 | |||
|
|
12015309d8 | ||
|
|
1e62844a22 | ||
|
|
ad479309b0 | ||
|
|
2f7c82757f | ||
|
|
634153a28d | ||
|
|
e664037063 | ||
|
|
75c16bd423 | ||
|
|
083dffac3c | ||
|
|
42ba054e5f | ||
|
|
3173e9aeae | ||
|
|
785d654129 | ||
|
|
22ce4440b7 | ||
|
|
80baccfd9c | ||
|
|
0c92f07749 | ||
|
|
73a9f1f84f | ||
|
|
3c3f0ab7f1 | ||
|
|
803098922a | ||
|
|
c028af8b6d | ||
|
|
d33d03189e | ||
|
|
d7bd5628d4 | ||
|
|
70ee857782 | ||
|
|
07f09e0759 | ||
|
|
ba832ddfd0 | ||
|
|
93c2284091 | ||
|
|
cc5b6f6351 | ||
|
|
a26a625e49 | ||
|
|
93b4892528 | ||
|
|
e57348a4c5 | ||
|
|
7059cb0354 | ||
|
|
f2d6e05816 | ||
|
|
e949493722 | ||
|
|
6969bbd571 | ||
|
|
9edea59ab9 | ||
|
|
1928b87634 | ||
|
|
d9ed321298 | ||
|
|
935f915e5d | ||
|
|
6263f4c335 | ||
|
|
62134efd19 | ||
|
|
8a06b9ee8e | ||
|
|
bc6fd2b9ff | ||
|
|
3b6f23515f | ||
|
|
3c5f419ce7 | ||
|
|
3418c22cde | ||
|
|
22806c5301 | ||
|
|
62fb27fdf8 | ||
|
|
6250625036 | ||
|
|
d77ec8a978 | ||
|
|
322bb4800b | ||
|
|
0437602236 | ||
|
|
bd37756ba3 | ||
|
|
fb4e7f0fc1 | ||
|
|
5279e4e739 | ||
|
|
ffef21e58c | ||
|
|
e901ae3ea0 | ||
|
|
8a050e0f81 | ||
|
|
a72112f928 | ||
|
|
be701cc98a | ||
|
|
9b000ffe6c | ||
|
|
6c91249340 | ||
|
|
b052e28788 | ||
|
|
247839b94d | ||
|
|
ecdf70d858 | ||
|
|
a004f7ea08 | ||
|
|
898868d5f4 | ||
|
|
eb4dab73e9 | ||
|
|
e1adfe30df |
17
.readthedocs.yml
Normal file
17
.readthedocs.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# .readthedocs.yml
|
||||||
|
# Read the Docs configuration file
|
||||||
|
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||||
|
|
||||||
|
# Required
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
# Build documentation in the documentation/ directory with Sphinx
|
||||||
|
sphinx:
|
||||||
|
configuration: documentation/conf.py
|
||||||
|
|
||||||
|
# Build documentation with MkDocs
|
||||||
|
#mkdocs:
|
||||||
|
# configuration: mkdocs.yml
|
||||||
|
|
||||||
|
# Optionally build your docs in additional formats such as PDF and ePub
|
||||||
|
formats: all
|
||||||
@@ -28,4 +28,4 @@ env:
|
|||||||
- BRBASE=7.0 RTEMS=4.9 TEST=NO
|
- BRBASE=7.0 RTEMS=4.9 TEST=NO
|
||||||
- BRBASE=3.16
|
- BRBASE=3.16
|
||||||
- BRBASE=3.15
|
- BRBASE=3.15
|
||||||
- BRBASE=3.14
|
|
||||||
|
|||||||
6
Doxyfile
6
Doxyfile
@@ -38,7 +38,7 @@ PROJECT_NAME = pvDatabaseCPP
|
|||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER =
|
PROJECT_NUMBER = 4.5.2
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
@@ -765,7 +765,7 @@ WARN_LOGFILE =
|
|||||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||||
# Note: If this tag is empty the current directory is searched.
|
# Note: If this tag is empty the current directory is searched.
|
||||||
|
|
||||||
INPUT = include
|
INPUT = src
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
@@ -1035,7 +1035,7 @@ GENERATE_HTML = YES
|
|||||||
# The default directory is: html.
|
# The default directory is: html.
|
||||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||||
|
|
||||||
HTML_OUTPUT = documentation/html
|
HTML_OUTPUT = html/doxygen
|
||||||
|
|
||||||
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
|
||||||
# generated HTML page (for example: .htm, .php, .asp).
|
# generated HTML page (for example: .htm, .php, .asp).
|
||||||
|
|||||||
12
configure/CONFIG_PVDATABASE_VERSION
Normal file
12
configure/CONFIG_PVDATABASE_VERSION
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# Version number for the PV Database API and shared library
|
||||||
|
|
||||||
|
EPICS_PVDATABASE_MAJOR_VERSION = 4
|
||||||
|
EPICS_PVDATABASE_MINOR_VERSION = 5
|
||||||
|
EPICS_PVDATABASE_MAINTENANCE_VERSION = 2
|
||||||
|
|
||||||
|
# Development flag, set to zero for release versions
|
||||||
|
|
||||||
|
EPICS_PVDATABASE_DEVELOPMENT_FLAG = 0
|
||||||
|
|
||||||
|
# Immediately after a release the MAINTENANCE_VERSION
|
||||||
|
# will be incremented and the DEVELOPMENT_FLAG set to 1
|
||||||
@@ -2,6 +2,8 @@ TOP=..
|
|||||||
|
|
||||||
include $(TOP)/configure/CONFIG
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
|
CFG += CONFIG_PVDATABASE_VERSION
|
||||||
|
|
||||||
TARGETS = $(CONFIG_TARGETS)
|
TARGETS = $(CONFIG_TARGETS)
|
||||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,23 @@
|
|||||||
|
|
||||||
This document summarizes the changes to the module between releases.
|
This document summarizes the changes to the module between releases.
|
||||||
|
|
||||||
|
## Release 4.5.2 (EPICS 7.0.3.2 May 2020)
|
||||||
|
|
||||||
|
* plugin support is new
|
||||||
|
* fixed issues #53 and #52
|
||||||
|
|
||||||
|
## Release 4.5.1 (EPICS 7.0.3.1, Nov 2019)
|
||||||
|
|
||||||
|
* addRecord is new.
|
||||||
|
* Doxygen updates and read-the-docs integration.
|
||||||
|
|
||||||
|
|
||||||
|
## Release 4.5.0 (EPICS 7.0.3, Jul 2019)
|
||||||
|
|
||||||
|
* support is a new feature.
|
||||||
|
* processRecord is new.
|
||||||
|
|
||||||
|
|
||||||
## Release 4.4.2 (EPICS 7.0.2.2, Apr 2019)
|
## Release 4.4.2 (EPICS 7.0.2.2, Apr 2019)
|
||||||
|
|
||||||
Formerly if a client makes a request for a subfield of a non structure field
|
Formerly if a client makes a request for a subfield of a non structure field
|
||||||
@@ -15,6 +32,7 @@ Now if a request is made for a subfield of a non structure field
|
|||||||
b) if the subfield is the type for the current union the request succeeds
|
b) if the subfield is the type for the current union the request succeeds
|
||||||
c) if type is not the same an exception is thrown
|
c) if type is not the same an exception is thrown
|
||||||
|
|
||||||
|
|
||||||
## Release 4.4.1 (EPICS 7.0.2.1, Mar 2019)
|
## Release 4.4.1 (EPICS 7.0.2.1, Mar 2019)
|
||||||
|
|
||||||
* Cleaned up some build warnings.
|
* Cleaned up some build warnings.
|
||||||
|
|||||||
@@ -1,17 +1,6 @@
|
|||||||
TODO
|
TODO
|
||||||
===========
|
===========
|
||||||
|
|
||||||
monitorPlugin
|
|
||||||
-------------
|
|
||||||
|
|
||||||
A debate is on-going about what semantics should be.
|
|
||||||
|
|
||||||
Must test record delete.
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
Must test removing a record from the PVDatabase while a pvAccess client
|
|
||||||
is attached. Also why do both unlisten and detach exists?
|
|
||||||
|
|
||||||
|
|
||||||
create more regression tests
|
create more regression tests
|
||||||
----------------
|
----------------
|
||||||
|
|||||||
7
documentation/_static/css/custom.css
Normal file
7
documentation/_static/css/custom.css
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
.wy-side-nav-search {
|
||||||
|
background-color: #18334B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wy-side-nav-search input[type="text"] {
|
||||||
|
border-color: #18334b;
|
||||||
|
}
|
||||||
80
documentation/conf.py
Normal file
80
documentation/conf.py
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Configuration file for the Sphinx documentation builder.
|
||||||
|
#
|
||||||
|
# This file only contains a selection of the most common options. For a full
|
||||||
|
# list see the documentation:
|
||||||
|
# http://www.sphinx-doc.org/en/master/config
|
||||||
|
|
||||||
|
# -- Path setup --------------------------------------------------------------
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#
|
||||||
|
# import os
|
||||||
|
# import sys
|
||||||
|
# sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
|
||||||
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = 'normativeTypes (C++)'
|
||||||
|
copyright = '2019, EPICS Controls.'
|
||||||
|
author = 'EPICS'
|
||||||
|
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.intersphinx',
|
||||||
|
]
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This pattern also affects html_static_path and html_extra_path.
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# Intersphinx links to subprojects
|
||||||
|
intersphinx_mapping = {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
html_theme = 'sphinx_rtd_theme'
|
||||||
|
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
html_css_files = [
|
||||||
|
'css/custom.css',
|
||||||
|
]
|
||||||
|
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
html_theme_options = {
|
||||||
|
'logo_only': True,
|
||||||
|
}
|
||||||
|
html_logo = "images/EPICS_white_logo_v02.png"
|
||||||
|
|
||||||
|
html_extra_path = [
|
||||||
|
'../html',
|
||||||
|
'pvDatabaseCPP.html',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# -- Run Doxygen ------------------------------------------------------------
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
|
||||||
BIN
documentation/images/EPICS_white_logo_v02.png
Normal file
BIN
documentation/images/EPICS_white_logo_v02.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.5 KiB |
17
documentation/index.rst
Normal file
17
documentation/index.rst
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
pvDatabase (C++) Library
|
||||||
|
========================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
EPICS Website <https://epics-controls.org>
|
||||||
|
EPICS Documentation Home <https://docs.epics-controls.org>
|
||||||
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 1
|
||||||
|
:caption: pvDatabaseCPP
|
||||||
|
|
||||||
|
Reference Manual <https://docs.epics-controls.org/projects/pvdatabase-cpp/en/latest/pvDatabaseCPP.html>
|
||||||
|
API Documentation <https://docs.epics-controls.org/projects/pvdatabase-cpp/en/latest/doxygen>
|
||||||
|
Source Code Repository on GitHub <https://github.com/epics-base/pvDatabaseCPP>
|
||||||
@@ -36,7 +36,8 @@
|
|||||||
|
|
||||||
<div class="head">
|
<div class="head">
|
||||||
<h1>pvDatabaseCPP</h1>
|
<h1>pvDatabaseCPP</h1>
|
||||||
<h2 class="nocount">Release 4.4 - December 2018</h2>
|
<h2 class="nocount">Release ? - TBD</h2>
|
||||||
|
Latest update 2019.09.11.
|
||||||
|
|
||||||
|
|
||||||
<h2 class="nocount">Abstract</h2>
|
<h2 class="nocount">Abstract</h2>
|
||||||
@@ -69,8 +70,6 @@ pvDatabaseCPP is one of the components of
|
|||||||
EPICS Version 7
|
EPICS Version 7
|
||||||
</p>
|
</p>
|
||||||
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP
|
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
It is intended for developers that want to use pvDatabaseCPP.
|
It is intended for developers that want to use pvDatabaseCPP.
|
||||||
</p>
|
</p>
|
||||||
<h2>Developer Guide</h2>
|
<h2>Developer Guide</h2>
|
||||||
@@ -87,7 +86,7 @@ In particular read everything related to pvDatabase.
|
|||||||
</p>
|
</p>
|
||||||
<p>pvDatabase has plugin support, which is implemented in <b>pvCopy</b>.
|
<p>pvDatabase has plugin support, which is implemented in <b>pvCopy</b>.
|
||||||
<b>pvCopy</b> was originally implemented in <b>pvDataCPP</b>,
|
<b>pvCopy</b> was originally implemented in <b>pvDataCPP</b>,
|
||||||
but pvDatabaseCPP now implemnents its own version and adds plugin support.
|
but pvDatabaseCPP now implements its own version and adds plugin support.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
See
|
See
|
||||||
@@ -98,7 +97,7 @@ pvRequest
|
|||||||
for details.
|
for details.
|
||||||
</p>
|
</p>
|
||||||
<p>The developerGuide discusses code in a way that applies to both CPP and C++.
|
<p>The developerGuide discusses code in a way that applies to both CPP and C++.
|
||||||
For the descriptions of the CPP specific code consult the next section.
|
For the descriptions of the CPP specific code consult the following sections.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>doxygen</h2>
|
<h2>doxygen</h2>
|
||||||
@@ -108,22 +107,86 @@ href="./html/index.html">doxgen</a>
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>pvDatabaseCPP</h2>
|
<h2>pvDatabaseCPP</h2>
|
||||||
<p>pvDatabaseCPP itself has the following implementations of a <b>PVRecord</b></p>
|
<h3>include/pv</h3>
|
||||||
|
<p>The header files that describe the various components implemented by pvDatabase.
|
||||||
|
</p>
|
||||||
<dl>
|
<dl>
|
||||||
<dt>RemoveRecord.cpp</dt>
|
<dt>pvDatabase.h</dt>
|
||||||
<dd>
|
<dd>
|
||||||
This is the code that is used to delete another record in the same <b>IOC</b>.
|
This describes PVRecord and PVDatabase.
|
||||||
</dd>
|
</dd>
|
||||||
<dt>TraceRecord.cpp</dt>
|
<dt>channelProviderLocal.h </dt>
|
||||||
<dd>
|
<dd>
|
||||||
This is the code that is used to set the trace level
|
This describes a channel provider for PVDatabase
|
||||||
in another record in the same <b>IOC</b>.
|
</dd>
|
||||||
</dd>
|
<dt>pvSupport.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is the base class for support attached to a field of a record.
|
||||||
|
</dd>
|
||||||
|
<dt>controlSupport.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is support that implements control limits.
|
||||||
|
</dd>
|
||||||
|
<dt>scalarAlarmSupport.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is support for a alarm limits for a scalar numeric field.
|
||||||
|
</dd>
|
||||||
|
<dt>processRecord.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is a PVRecord that periodical processes a set of PVRecords in the local PVDatabase.
|
||||||
|
</dd>
|
||||||
|
<dt>addRecord.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is a PVRecord that adds a new PVRecord to the local PVDatabase.
|
||||||
|
</dd>
|
||||||
|
<dt>removeRecord.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is a PVRecord that removes a PVRecord in the local PVDatabase.
|
||||||
|
</dd>
|
||||||
|
<dt>traceRecord.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is a PVRecord that sets the trace value for another PVRecord in the local PVDatabase.
|
||||||
|
</dd>
|
||||||
|
<dt>pvStructureCopy.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is a facility that allows a client to access a subfield of the fields in a PVRecord.
|
||||||
|
It also provides record and field options an plugin support.
|
||||||
|
</dd>
|
||||||
|
<dt>pvPlugin.h</dt>
|
||||||
|
<dd>
|
||||||
|
This is the base class for a plugin attached to a record or field of PVRecord.
|
||||||
|
</dd>
|
||||||
|
<dt>pvArrayPlugin.h</dt>
|
||||||
|
<dd>
|
||||||
|
A plugin for accessing a subset of the elements in an array field.
|
||||||
|
</dd>
|
||||||
|
<dt>pvDeadbandPlugin.h</dt>
|
||||||
|
<dd>
|
||||||
|
A deadband plugin for monitors.
|
||||||
|
</dd>
|
||||||
|
<dt>pvTimestampPlugin.h</dt>
|
||||||
|
<dd>
|
||||||
|
A plugin for timeStamp.
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
<h3>src/database</h3>
|
||||||
|
<p>This has the code that implements pvDatabase and pvRecord.</p>
|
||||||
|
<h3>src/pvAccess</h3>
|
||||||
|
<p>This has the code for the channel provider for pvDatabase.
|
||||||
|
</p>
|
||||||
|
<h3>src/support</h3>
|
||||||
|
<p>This has the pvSupport code.</p>
|
||||||
|
<h3>src/special</h3>
|
||||||
|
<p>
|
||||||
|
This has the code for processRecord, addRecord, removeRecord, and traceRecord.
|
||||||
|
</p>
|
||||||
|
<h3>src/copy</h3>
|
||||||
|
<p>This has the code for pvStructureCopy and all the plugin support.
|
||||||
|
</p>
|
||||||
<h2>exampleCPP</h2>
|
<h2>exampleCPP</h2>
|
||||||
<p>Example code is available as part of this release.
|
<p>Example code is available as part of this release.
|
||||||
<a
|
<a
|
||||||
href="http://epics-pvdata.sourceforge.net/docbuild/exampleCPP/tip/documentation/exampleCPP.html">
|
href="https://github.com/epics-base/exampleCPP">
|
||||||
exampleCPP
|
exampleCPP
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
@@ -173,6 +236,24 @@ other functionality.</p>
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
<h3>support</h3>
|
||||||
|
<p>This creates records that have the following features:</p>
|
||||||
|
<dl>
|
||||||
|
<dt>value</dt>
|
||||||
|
<dd>
|
||||||
|
Each record has a value field the is a numeric scalar field.
|
||||||
|
In addition each has the following fields:
|
||||||
|
alarm,timeStamp,control,scalarAlarm, and display.
|
||||||
|
</dd>
|
||||||
|
<dt>support</dt>
|
||||||
|
<dd>
|
||||||
|
Each record uses the control and scalarAlarm support provided by pvDatabaseCPP.
|
||||||
|
</dd>
|
||||||
|
</dl>
|
||||||
|
<p>
|
||||||
|
It also creates records that can be used by clients to show example of the plugin support.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h2>iocshell commands</h2>
|
<h2>iocshell commands</h2>
|
||||||
<p>Shell commands are made available via the standard DBD include mechanism
|
<p>Shell commands are made available via the standard DBD include mechanism
|
||||||
provided by iocCore.
|
provided by iocCore.
|
||||||
@@ -194,7 +275,7 @@ pvDatabaseCPP
|
|||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
<p>In addition any code that implements a PVRecord must implement an ioc command.
|
<p>In addition any code that implements a PVRecord must implement an ioc command.
|
||||||
Look at any of the examples in <b>exampleCPP</b> to see how to implement shell commands.</p>
|
Look at the examples in <b>exampleCPP/support</b> to see how to implement shell commands.</p>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
25
example/createdestroy/Makefile
Executable file
25
example/createdestroy/Makefile
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
TOP=../..
|
||||||
|
include $(TOP)/configure/CONFIG
|
||||||
|
#----------------------------------------
|
||||||
|
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
||||||
|
#=============================
|
||||||
|
|
||||||
|
#=============================
|
||||||
|
# Build the application
|
||||||
|
|
||||||
|
TESTPROD_HOST = createdestroy
|
||||||
|
|
||||||
|
createdestroy_SRCS += createdestroy.cpp
|
||||||
|
|
||||||
|
# Add all the support libraries needed by this application
|
||||||
|
#pvatest_LIBS += xxx
|
||||||
|
|
||||||
|
# Finally link to the EPICS Base libraries
|
||||||
|
createdestroy_LIBS += pvDatabase pvAccess pvData
|
||||||
|
createdestroy_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||||
|
|
||||||
|
#===========================
|
||||||
|
|
||||||
|
include $(TOP)/configure/RULES
|
||||||
|
#----------------------------------------
|
||||||
|
# ADD RULES AFTER THIS LINE
|
||||||
20
example/createdestroy/README.md
Normal file
20
example/createdestroy/README.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# pvDatabaseCPP/example/createdestroy
|
||||||
|
|
||||||
|
This is an example that:
|
||||||
|
|
||||||
|
1) Gets the master PVDatabase
|
||||||
|
2) Create ChannelProviderLocal
|
||||||
|
3) Creates a ServerContext
|
||||||
|
|
||||||
|
Then it executes a forever loop that:
|
||||||
|
|
||||||
|
1) creates a pvRecord and adds it to the pvDatabase.
|
||||||
|
2) creates a pvac::ClientProvider
|
||||||
|
3) creates a pvac::ClientChannel
|
||||||
|
4) creates a monitor on the channel
|
||||||
|
5) runs a loop 10 times that: does a put to the channel, and then gets the data for any outstanding monitors
|
||||||
|
6) removes the pvRecord from the pvDatabase
|
||||||
|
|
||||||
|
It also has options to set trace level for the pvRecord and to periodically pause by asking for input.
|
||||||
|
|
||||||
|
|
||||||
179
example/createdestroy/createdestroy.cpp
Normal file
179
example/createdestroy/createdestroy.cpp
Normal file
@@ -0,0 +1,179 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* This is modeled after a test program created by Bertrand Bauvir from the ITER Organization
|
||||||
|
******************************************************************************/
|
||||||
|
#include <iostream>
|
||||||
|
#include <epicsGetopt.h>
|
||||||
|
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvDatabase.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
#include <pv/channelProviderLocal.h>
|
||||||
|
#include <pva/client.h>
|
||||||
|
#include <epicsEvent.h>
|
||||||
|
|
||||||
|
// Local header files
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
|
||||||
|
#define DEFAULT_RECORD_NAME "examplechannel"
|
||||||
|
|
||||||
|
using std::tr1::static_pointer_cast;
|
||||||
|
|
||||||
|
class Record : public ::epics::pvDatabase::PVRecord
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::shared_ptr<::epics::pvData::PVStructure> __pv;
|
||||||
|
static std::shared_ptr<Record> create (std::string const & name, std::shared_ptr<::epics::pvData::PVStructure> const & pvstruct);
|
||||||
|
Record (std::string const & name, std::shared_ptr<epics::pvData::PVStructure> const & pvstruct)
|
||||||
|
: epics::pvDatabase::PVRecord(name, pvstruct) { __pv = pvstruct; };
|
||||||
|
virtual void process (void);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::shared_ptr<Record> Record::create (std::string const & name, std::shared_ptr<::epics::pvData::PVStructure> const & pvstruct)
|
||||||
|
{
|
||||||
|
std::shared_ptr<Record> pvrecord (new Record (name, pvstruct));
|
||||||
|
// Need to be explicitly called .. not part of the base constructor
|
||||||
|
if(!pvrecord->init()) pvrecord.reset();
|
||||||
|
return pvrecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Record::process (void)
|
||||||
|
{
|
||||||
|
PVRecord::process();
|
||||||
|
std::string name = this->getRecordName();
|
||||||
|
std::cout << this->getRecordName()
|
||||||
|
<< " process\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
class MyMonitor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::tr1::shared_ptr<::pvac::MonitorSync> monitor;
|
||||||
|
MyMonitor(std::tr1::shared_ptr<::pvac::ClientChannel> const &channel)
|
||||||
|
{
|
||||||
|
monitor = std::tr1::shared_ptr<::pvac::MonitorSync>(new ::pvac::MonitorSync(channel->monitor()));
|
||||||
|
}
|
||||||
|
public:
|
||||||
|
static std::tr1::shared_ptr<MyMonitor> create(std::tr1::shared_ptr<::pvac::ClientChannel> const &channel)
|
||||||
|
{
|
||||||
|
return std::tr1::shared_ptr<MyMonitor>(new MyMonitor(channel));
|
||||||
|
}
|
||||||
|
void getData();
|
||||||
|
};
|
||||||
|
|
||||||
|
void MyMonitor::getData()
|
||||||
|
{
|
||||||
|
while (true) {
|
||||||
|
if(!monitor->wait(.001)) break;
|
||||||
|
switch(monitor->event.event) {
|
||||||
|
case pvac::MonitorEvent::Fail:
|
||||||
|
std::cerr<<monitor->name()<<" : Error : "<<monitor->event.message<<"\n";
|
||||||
|
return;
|
||||||
|
case pvac::MonitorEvent::Cancel:
|
||||||
|
std::cout<<monitor->name()<<" <Cancel>\n";
|
||||||
|
return;
|
||||||
|
case pvac::MonitorEvent::Disconnect:
|
||||||
|
std::cout<<monitor->name()<<" <Disconnect>\n";
|
||||||
|
return;
|
||||||
|
case pvac::MonitorEvent::Data:
|
||||||
|
while(monitor->poll()) {
|
||||||
|
std::cout<<monitor->name()<<" : "<<monitor->root;
|
||||||
|
}
|
||||||
|
if(monitor->complete()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main (int argc, char** argv)
|
||||||
|
{
|
||||||
|
int verbose = 0;
|
||||||
|
unsigned loopctr = 0;
|
||||||
|
unsigned pausectr = 0;
|
||||||
|
bool allowExit = false;
|
||||||
|
bool callRecord = false;
|
||||||
|
bool callDatabase = false;
|
||||||
|
int opt;
|
||||||
|
while((opt = getopt(argc, argv, "v:ardh")) != -1) {
|
||||||
|
switch(opt) {
|
||||||
|
case 'v':
|
||||||
|
verbose = std::stoi(optarg);
|
||||||
|
break;
|
||||||
|
case 'a' :
|
||||||
|
allowExit = true;
|
||||||
|
break;
|
||||||
|
case 'r' :
|
||||||
|
callRecord = true;
|
||||||
|
break;
|
||||||
|
case 'd' :
|
||||||
|
callDatabase = true;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
std::cout << " -v level -a -r -d -h \n";
|
||||||
|
std::cout << "-r call pvRecord->remove -d call master->removeRecord\n";
|
||||||
|
std::cout << "default\n";
|
||||||
|
std::cout << "-v " << verbose
|
||||||
|
<< " -a false"
|
||||||
|
<< " -d"
|
||||||
|
<< "\n";
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
std::cerr<<"Unknown argument: "<<opt<<"\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!callRecord && !callDatabase) callDatabase = true;
|
||||||
|
::epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
|
||||||
|
::epics::pvDatabase::ChannelProviderLocalPtr channelProvider = epics::pvDatabase::getChannelProviderLocal();
|
||||||
|
epics::pvAccess::ServerContext::shared_pointer context
|
||||||
|
= epics::pvAccess::startPVAServer(epics::pvAccess::PVACCESS_ALL_PROVIDERS, 0, true, true);
|
||||||
|
std::string startset("starting set of puts valuectr = ");
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
loopctr++;
|
||||||
|
std::string name = DEFAULT_RECORD_NAME + std::to_string(loopctr);
|
||||||
|
|
||||||
|
// Create record
|
||||||
|
// Create record structure
|
||||||
|
::epics::pvData::FieldBuilderPtr builder = epics::pvData::getFieldCreate()->createFieldBuilder();
|
||||||
|
builder->add("value", ::epics::pvData::pvULong);
|
||||||
|
std::shared_ptr<::epics::pvData::PVStructure> pvstruct
|
||||||
|
= ::epics::pvData::getPVDataCreate()->createPVStructure(builder->createStructure());
|
||||||
|
std::shared_ptr<Record> pvrecord = Record::create(std::string(name), pvstruct);
|
||||||
|
master->addRecord(pvrecord);
|
||||||
|
pvrecord->setTraceLevel(verbose);
|
||||||
|
// Start PVA (local) client
|
||||||
|
std::tr1::shared_ptr<::pvac::ClientProvider> provider
|
||||||
|
= std::tr1::shared_ptr<::pvac::ClientProvider>(new ::pvac::ClientProvider ("pva"));
|
||||||
|
std::tr1::shared_ptr<::pvac::ClientChannel> channel
|
||||||
|
= std::tr1::shared_ptr<::pvac::ClientChannel>(new ::pvac::ClientChannel (provider->connect(name)));
|
||||||
|
std::tr1::shared_ptr<MyMonitor> mymonitor = MyMonitor::create(channel);
|
||||||
|
unsigned valuectr = loopctr;
|
||||||
|
std::cout << startset << loopctr << "\n";
|
||||||
|
for (int ind=0; ind<100; ind++) {
|
||||||
|
channel->put().set("value",valuectr++).exec();
|
||||||
|
mymonitor->getData();
|
||||||
|
}
|
||||||
|
pausectr++;
|
||||||
|
if(allowExit && pausectr>10) {
|
||||||
|
pausectr = 0;
|
||||||
|
std::cout << "Type exit to stop: \n";
|
||||||
|
int c = std::cin.peek(); // peek character
|
||||||
|
if ( c == EOF ) continue;
|
||||||
|
std::string str;
|
||||||
|
std::getline(std::cin,str);
|
||||||
|
if(str.compare("exit")==0) break;
|
||||||
|
}
|
||||||
|
if(callRecord) {
|
||||||
|
std::cout << "callRecord\n";
|
||||||
|
pvrecord->remove();
|
||||||
|
}
|
||||||
|
if(callDatabase) {
|
||||||
|
std::cout << "callDatabase\n";
|
||||||
|
master->removeRecord(pvrecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
23
src/Makefile
23
src/Makefile
@@ -3,22 +3,41 @@
|
|||||||
TOP = ..
|
TOP = ..
|
||||||
include $(TOP)/configure/CONFIG
|
include $(TOP)/configure/CONFIG
|
||||||
|
|
||||||
|
# needed for Windows
|
||||||
|
LIB_SYS_LIBS_WIN32 += netapi32 ws2_32
|
||||||
|
|
||||||
PVDATABASE_SRC = $(TOP)/src
|
PVDATABASE_SRC = $(TOP)/src
|
||||||
|
|
||||||
LIBRARY += pvDatabase
|
LIBRARY += pvDatabase
|
||||||
|
|
||||||
# shared library ABI version.
|
# shared library ABI version.
|
||||||
SHRLIB_VERSION ?= 4.4.2
|
SHRLIB_VERSION ?= $(EPICS_PVDATABASE_MAJOR_VERSION).$(EPICS_PVDATABASE_MINOR_VERSION).$(EPICS_PVDATABASE_MAINTENANCE_VERSION)
|
||||||
|
|
||||||
|
INC += pv/pvPlugin.h
|
||||||
|
INC += pv/pvStructureCopy.h
|
||||||
|
INC += pv/pvArrayPlugin.h
|
||||||
|
INC += pv/pvDeadbandPlugin.h
|
||||||
|
INC += pv/pvTimestampPlugin.h
|
||||||
|
|
||||||
|
INC += pv/pvDatabase.h
|
||||||
|
|
||||||
INC += pv/channelProviderLocal.h
|
INC += pv/channelProviderLocal.h
|
||||||
INC += pv/pvDatabase.h
|
|
||||||
INC += pv/traceRecord.h
|
INC += pv/traceRecord.h
|
||||||
INC += pv/removeRecord.h
|
INC += pv/removeRecord.h
|
||||||
|
INC += pv/addRecord.h
|
||||||
|
INC += pv/processRecord.h
|
||||||
|
|
||||||
|
INC += pv/pvSupport.h
|
||||||
|
INC += pv/controlSupport.h
|
||||||
|
INC += pv/scalarAlarmSupport.h
|
||||||
|
|
||||||
|
|
||||||
include $(PVDATABASE_SRC)/copy/Makefile
|
include $(PVDATABASE_SRC)/copy/Makefile
|
||||||
include $(PVDATABASE_SRC)/database/Makefile
|
include $(PVDATABASE_SRC)/database/Makefile
|
||||||
include $(PVDATABASE_SRC)/pvAccess/Makefile
|
include $(PVDATABASE_SRC)/pvAccess/Makefile
|
||||||
include $(PVDATABASE_SRC)/special/Makefile
|
include $(PVDATABASE_SRC)/special/Makefile
|
||||||
|
include $(PVDATABASE_SRC)/support/Makefile
|
||||||
|
|
||||||
pvDatabase_LIBS += $(EPICS_BASE_PVA_CORE_LIBS)
|
pvDatabase_LIBS += $(EPICS_BASE_PVA_CORE_LIBS)
|
||||||
pvDatabase_LIBS += $(EPICS_BASE_IOC_LIBS)
|
pvDatabase_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
|
|
||||||
# This is a Makefile fragment, see ../Makefile
|
# This is a Makefile fragment, see ../Makefile
|
||||||
|
|
||||||
SRC_DIRS += $(PVDATABASE_SRC)/copy
|
SRC_DIRS += $(PVDATABASE_SRC)/copy
|
||||||
|
|
||||||
INC += pv/pvStructureCopy.h
|
|
||||||
INC += pv/pvPlugin.h
|
|
||||||
INC += pv/pvArrayPlugin.h
|
|
||||||
INC += pv/pvDeadbandPlugin.h
|
|
||||||
INC += pv/pvTimestampPlugin.h
|
|
||||||
|
|
||||||
LIBSRCS += pvCopy.cpp
|
|
||||||
LIBSRCS += pvPlugin.cpp
|
LIBSRCS += pvPlugin.cpp
|
||||||
|
LIBSRCS += pvCopy.cpp
|
||||||
LIBSRCS += pvArrayPlugin.cpp
|
LIBSRCS += pvArrayPlugin.cpp
|
||||||
LIBSRCS += pvDeadbandPlugin.cpp
|
LIBSRCS += pvDeadbandPlugin.cpp
|
||||||
LIBSRCS += pvTimestampPlugin.cpp
|
LIBSRCS += pvTimestampPlugin.cpp
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
#include <pv/pvSubArrayCopy.h>
|
#include <pv/pvSubArrayCopy.h>
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvArrayPlugin.h>
|
#include "pv/pvArrayPlugin.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::size_t;
|
using std::size_t;
|
||||||
@@ -76,9 +76,19 @@ static vector<string> split(string const & colonSeparatedList) {
|
|||||||
|
|
||||||
PVArrayFilterPtr PVArrayFilter::create(
|
PVArrayFilterPtr PVArrayFilter::create(
|
||||||
const std::string & requestValue,
|
const std::string & requestValue,
|
||||||
const PVFieldPtr & master)
|
const PVFieldPtr & masterField)
|
||||||
{
|
{
|
||||||
Type type = master->getField()->getType();
|
bool masterIsUnion = false;
|
||||||
|
PVUnionPtr pvUnion;
|
||||||
|
Type type = masterField->getField()->getType();
|
||||||
|
if(type==epics::pvData::union_) {
|
||||||
|
pvUnion = std::tr1::static_pointer_cast<PVUnion>(masterField);
|
||||||
|
PVFieldPtr pvField = pvUnion->get();
|
||||||
|
if(pvField) {
|
||||||
|
masterIsUnion = true;
|
||||||
|
type = pvField->getField()->getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
if(type!=scalarArray) {
|
if(type!=scalarArray) {
|
||||||
PVArrayFilterPtr filter = PVArrayFilterPtr();
|
PVArrayFilterPtr filter = PVArrayFilterPtr();
|
||||||
return filter;
|
return filter;
|
||||||
@@ -112,60 +122,82 @@ PVArrayFilterPtr PVArrayFilter::create(
|
|||||||
PVArrayFilterPtr filter = PVArrayFilterPtr();
|
PVArrayFilterPtr filter = PVArrayFilterPtr();
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
PVScalarArrayPtr masterArray;
|
||||||
|
if(masterIsUnion) {
|
||||||
|
masterArray = static_pointer_cast<PVScalarArray>(pvUnion->get());
|
||||||
|
} else {
|
||||||
|
masterArray = static_pointer_cast<PVScalarArray>(masterField);
|
||||||
|
}
|
||||||
PVArrayFilterPtr filter =
|
PVArrayFilterPtr filter =
|
||||||
PVArrayFilterPtr(
|
PVArrayFilterPtr(
|
||||||
new PVArrayFilter(
|
new PVArrayFilter(start,increment,end,masterField,masterArray));
|
||||||
start,increment,end,static_pointer_cast<PVScalarArray>(master)));
|
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVArrayFilter::PVArrayFilter(long start,long increment,long end,const PVScalarArrayPtr & masterArray)
|
PVArrayFilter::PVArrayFilter(
|
||||||
|
long start,long increment,long end,
|
||||||
|
const PVFieldPtr & masterField,
|
||||||
|
const epics::pvData::PVScalarArrayPtr masterArray)
|
||||||
: start(start),
|
: start(start),
|
||||||
increment(increment),
|
increment(increment),
|
||||||
end(end),
|
end(end),
|
||||||
|
masterField(masterField),
|
||||||
masterArray(masterArray)
|
masterArray(masterArray)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool PVArrayFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet,bool toCopy)
|
bool PVArrayFilter::filter(const PVFieldPtr & pvField,const BitSetPtr & bitSet,bool toCopy)
|
||||||
{
|
{
|
||||||
PVScalarArrayPtr copyArray = static_pointer_cast<PVScalarArray>(pvCopy);
|
PVFieldPtr pvCopy = pvField;
|
||||||
|
PVScalarArrayPtr copyArray;
|
||||||
|
bool isUnion = false;
|
||||||
|
Type type = masterField->getField()->getType();
|
||||||
|
if(type==epics::pvData::union_) {
|
||||||
|
isUnion = true;
|
||||||
|
PVUnionPtr pvMasterUnion = std::tr1::static_pointer_cast<PVUnion>(masterField);
|
||||||
|
PVUnionPtr pvCopyUnion = std::tr1::static_pointer_cast<PVUnion>(pvCopy);
|
||||||
|
if(toCopy) pvCopyUnion->copy(*pvMasterUnion);
|
||||||
|
PVFieldPtr pvField = pvCopyUnion->get();
|
||||||
|
copyArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||||
|
} else {
|
||||||
|
copyArray = static_pointer_cast<PVScalarArray>(pvCopy);
|
||||||
|
}
|
||||||
long len = 0;
|
long len = 0;
|
||||||
long start = this->start;
|
long start = this->start;
|
||||||
long end = this->end;
|
long end = this->end;
|
||||||
long no_elements = masterArray->getLength();
|
long no_elements = masterArray->getLength();
|
||||||
if(start<0) {
|
if(start<0) {
|
||||||
start = no_elements+start;
|
start = no_elements+start;
|
||||||
if(start<0) start = 0;
|
if(start<0) start = 0;
|
||||||
}
|
}
|
||||||
if (end < 0) {
|
if (end < 0) {
|
||||||
end = no_elements + end;
|
end = no_elements + end;
|
||||||
if (end < 0) end = 0;
|
if (end < 0) end = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
if(toCopy) {
|
if(toCopy) {
|
||||||
if (end >= no_elements) end = no_elements - 1;
|
if (end >= no_elements) end = no_elements - 1;
|
||||||
if (end - start >= 0) len = 1 + (end - start) / increment;
|
if (end - start >= 0) len = 1 + (end - start) / increment;
|
||||||
if(len<=0 || start>=no_elements) {
|
if(len<=0 || start>=no_elements) {
|
||||||
copyArray->setLength(0);
|
copyArray->setLength(0);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
long indfrom = start;
|
long indfrom = start;
|
||||||
long indto = 0;
|
long indto = 0;
|
||||||
copyArray->setCapacity(len);
|
copyArray->setCapacity(len);
|
||||||
if(increment==1) {
|
if(increment==1) {
|
||||||
copy(*masterArray,indfrom,1,*copyArray,indto,1,len);
|
copy(*masterArray,indfrom,1,*copyArray,indto,1,len);
|
||||||
} else {
|
} else {
|
||||||
for(long i=0; i<len; ++i) {
|
for(long i=0; i<len; ++i) {
|
||||||
copy(*masterArray,indfrom,1,*copyArray,indto,1,1);
|
copy(*masterArray,indfrom,1,*copyArray,indto,1,1);
|
||||||
indfrom += increment;
|
indfrom += increment;
|
||||||
indto += 1;
|
indto += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
copyArray->setLength(len);
|
copyArray->setLength(len);
|
||||||
bitSet->set(pvCopy->getFieldOffset());
|
bitSet->set(pvField->getFieldOffset());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (end - start >= 0) len = 1 + (end - start) / increment;
|
if (end - start >= 0) len = 1 + (end - start) / increment;
|
||||||
if(len<=0) return true;
|
if(len<=0) return true;
|
||||||
@@ -173,21 +205,21 @@ bool PVArrayFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet,bo
|
|||||||
long indfrom = 0;
|
long indfrom = 0;
|
||||||
long indto = start;
|
long indto = start;
|
||||||
if(increment==1) {
|
if(increment==1) {
|
||||||
copy(*copyArray,indfrom,1,*masterArray,indto,1,len);
|
copy(*copyArray,indfrom,1,*masterArray,indto,1,len);
|
||||||
} else {
|
} else {
|
||||||
for(long i=0; i<len; ++i) {
|
for(long i=0; i<len; ++i) {
|
||||||
copy(*copyArray,indfrom,1,*masterArray,indto,1,1);
|
copy(*copyArray,indfrom,1,*masterArray,indto,1,1);
|
||||||
indfrom += increment;
|
indfrom += 1;
|
||||||
indto += 1;
|
indto += increment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(isUnion) masterField->postPut();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string PVArrayFilter::getName()
|
string PVArrayFilter::getName()
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
#include <pv/thread.h>
|
#include <pv/thread.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvPlugin.h>
|
#include "pv/pvPlugin.h"
|
||||||
#include <pv/pvStructureCopy.h>
|
#include "pv/pvStructureCopy.h"
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using std::tr1::dynamic_pointer_cast;
|
using std::tr1::dynamic_pointer_cast;
|
||||||
@@ -212,19 +212,91 @@ bool PVCopy::updateCopyFromBitSet(
|
|||||||
return checkIgnore(copyPVStructure,bitSet);
|
return checkIgnore(copyPVStructure,bitSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PVCopy::updateMasterField(
|
||||||
|
CopyNodePtr const & node,
|
||||||
|
PVFieldPtr const & pvCopy,
|
||||||
|
PVFieldPtr const &pvMaster,
|
||||||
|
BitSetPtr const &bitSet)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
for(size_t i=0; i< node->pvFilters.size(); ++i) {
|
||||||
|
PVFilterPtr pvFilter = node->pvFilters[i];
|
||||||
|
if(pvFilter->filter(pvCopy,bitSet,false)) result = true;
|
||||||
|
}
|
||||||
|
if(result) return;
|
||||||
|
pvMaster->copyUnchecked(*pvCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PVCopy::updateMasterCheckBitSet(
|
||||||
|
PVStructurePtr const ©PVStructure,
|
||||||
|
BitSetPtr const &bitSet,
|
||||||
|
size_t nextSet)
|
||||||
|
{
|
||||||
|
if(!bitSet->get(nextSet)) {
|
||||||
|
size_t next = bitSet->nextSetBit(nextSet);
|
||||||
|
if(next==string::npos) return;
|
||||||
|
updateMasterCheckBitSet(copyPVStructure,bitSet,next);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PVFieldPtr pvField = copyPVStructure;
|
||||||
|
if(nextSet!=0) pvField = copyPVStructure->getSubField(nextSet);
|
||||||
|
if(pvField->getField()->getType()==epics::pvData::structure) {
|
||||||
|
bitSet->clear(nextSet);
|
||||||
|
PVStructurePtr pv = static_pointer_cast<PVStructure>(pvField);
|
||||||
|
PVFieldPtrArray pvFieldArray = pv->getPVFields();
|
||||||
|
for(size_t i=0; i<pvFieldArray.size(); ++i) {
|
||||||
|
PVFieldPtr pvField = pvFieldArray[i];
|
||||||
|
bitSet->set(pvField->getFieldOffset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t next = bitSet->nextSetBit(nextSet+1);
|
||||||
|
if(next==string::npos) return;
|
||||||
|
updateMasterCheckBitSet(copyPVStructure,bitSet,next);
|
||||||
|
}
|
||||||
|
|
||||||
|
CopyNodePtr PVCopy::getCopyNode(std::size_t fieldOffset)
|
||||||
|
{
|
||||||
|
if(fieldOffset==0) return headNode;
|
||||||
|
CopyNodePtr node = headNode;
|
||||||
|
while(true) {
|
||||||
|
if(!node->isStructure) return node;
|
||||||
|
CopyStructureNodePtr structNode = static_pointer_cast<CopyStructureNode>(node);
|
||||||
|
CopyNodePtrArrayPtr nodes = structNode->nodes;
|
||||||
|
bool okToContinue = false;
|
||||||
|
for(size_t i=0; i< nodes->size(); i++) {
|
||||||
|
node = (*nodes)[i];
|
||||||
|
size_t soff = node->structureOffset;
|
||||||
|
if(fieldOffset>=soff && fieldOffset<soff+node->nfields) {
|
||||||
|
okToContinue = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(okToContinue) continue;
|
||||||
|
}
|
||||||
|
throw std::logic_error("PVCopy::getCopyNode fieldOffset not valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PVCopy::updateMaster(
|
void PVCopy::updateMaster(
|
||||||
PVStructurePtr const ©PVStructure,
|
PVStructurePtr const ©PVStructure,
|
||||||
BitSetPtr const &bitSet)
|
BitSetPtr const &bitSet)
|
||||||
{
|
{
|
||||||
if(bitSet->get(0)) {
|
updateMasterCheckBitSet(copyPVStructure,bitSet,0);
|
||||||
for(size_t i=0; i< copyPVStructure->getNumberFields(); ++i) {
|
size_t nextSet =0;
|
||||||
bitSet->set(i,true);
|
while(true) {
|
||||||
|
nextSet = bitSet->nextSetBit(nextSet);
|
||||||
|
if(nextSet==string::npos) return;
|
||||||
|
PVFieldPtr pvCopy = copyPVStructure->getSubField(nextSet);
|
||||||
|
PVFieldPtr pvMaster = headNode->masterPVField;
|
||||||
|
if(pvMaster->getField()->getType()==epics::pvData::structure) {
|
||||||
|
PVStructurePtr pv = static_pointer_cast<PVStructure>(pvMaster);
|
||||||
|
pvMaster = pv->getSubField(pvCopy->getFullName());
|
||||||
}
|
}
|
||||||
|
updateMasterField(getCopyNode(nextSet),pvCopy,pvMaster,bitSet);
|
||||||
|
bitSet->clear(nextSet);
|
||||||
}
|
}
|
||||||
updateMaster(copyPVStructure,headNode,bitSet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
|
PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
|
||||||
{
|
{
|
||||||
if(fieldOffset==0) return headNode->options;
|
if(fieldOffset==0) return headNode->options;
|
||||||
@@ -248,7 +320,7 @@ PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(okToContinue) continue;
|
if(okToContinue) continue;
|
||||||
throw std::logic_error("PVCopy logic error: fieldOffset not valid");
|
throw std::logic_error("PVCopy::getOptions logic error: fieldOffset not valid");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -349,36 +421,6 @@ void PVCopy::updateCopyFromBitSet(
|
|||||||
updateCopyFromBitSet(pvCopyFields[i],(*structureNode->nodes)[i],bitSet);
|
updateCopyFromBitSet(pvCopyFields[i],(*structureNode->nodes)[i],bitSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void PVCopy::updateMaster(
|
|
||||||
PVFieldPtr const & pvCopy,
|
|
||||||
CopyNodePtr const & node,
|
|
||||||
BitSetPtr const & bitSet)
|
|
||||||
{
|
|
||||||
bool result = false;
|
|
||||||
bool update = bitSet->get(pvCopy->getFieldOffset());
|
|
||||||
if(update) {
|
|
||||||
for(size_t i=0; i< node->pvFilters.size(); ++i) {
|
|
||||||
PVFilterPtr pvFilter = node->pvFilters[i];
|
|
||||||
if(pvFilter->filter(pvCopy,bitSet,false)) result = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!node->isStructure) {
|
|
||||||
if(result) return;
|
|
||||||
PVFieldPtr pvMaster = node->masterPVField;
|
|
||||||
pvMaster->copy(*pvCopy);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
CopyStructureNodePtr structureNode = static_pointer_cast<CopyStructureNode>(node);
|
|
||||||
size_t offset = structureNode->structureOffset;
|
|
||||||
size_t nextSet = bitSet->nextSetBit(offset);
|
|
||||||
if(nextSet==string::npos) return;
|
|
||||||
if(offset>=pvCopy->getNextFieldOffset()) return;
|
|
||||||
PVStructurePtr pvCopyStructure = static_pointer_cast<PVStructure>(pvCopy);
|
|
||||||
PVFieldPtrArray const & pvCopyFields = pvCopyStructure->getPVFields();
|
|
||||||
for(size_t i=0; i<pvCopyFields.size(); ++i) {
|
|
||||||
updateMaster(pvCopyFields[i],(*structureNode->nodes)[i],bitSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PVCopy::PVCopy(
|
PVCopy::PVCopy(
|
||||||
PVStructurePtr const &pvMaster)
|
PVStructurePtr const &pvMaster)
|
||||||
@@ -493,7 +535,7 @@ CopyNodePtr PVCopy::createStructureNodes(
|
|||||||
requestPVStructure->getSubField<PVStructure>("_options");
|
requestPVStructure->getSubField<PVStructure>("_options");
|
||||||
PVFieldPtr pvMasterField = pvMasterStructure->getSubField(fieldName);
|
PVFieldPtr pvMasterField = pvMasterStructure->getSubField(fieldName);
|
||||||
if(!pvMasterField) {
|
if(!pvMasterField) {
|
||||||
throw std::logic_error("PVCopy logic error: did not find field in master");
|
throw std::logic_error("PVCopy::createStructureNodes did not find field in master");
|
||||||
}
|
}
|
||||||
size_t numberRequest = requestPVStructure->getPVFields().size();
|
size_t numberRequest = requestPVStructure->getPVFields().size();
|
||||||
bool haveOptions = false;
|
bool haveOptions = false;
|
||||||
@@ -668,7 +710,7 @@ void PVCopy::setIgnore(CopyNodePtr const &node) {
|
|||||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||||
for(size_t i=0; i<nodes->size(); ++i) {
|
for(size_t i=0; i<nodes->size(); ++i) {
|
||||||
CopyNodePtr node = (*nodes)[i];
|
CopyNodePtr node = (*nodes)[i];
|
||||||
setIgnore(node); }
|
setIgnore(node); }
|
||||||
} else {
|
} else {
|
||||||
size_t num = node->masterPVField->getNumberFields();
|
size_t num = node->masterPVField->getNumberFields();
|
||||||
if(num>1) {
|
if(num>1) {
|
||||||
|
|||||||
@@ -4,12 +4,15 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <pv/lock.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/bitSet.h>
|
#include <pv/bitSet.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
#include <pv/pvSubArrayCopy.h>
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvDeadbandPlugin.h>
|
#include "pv/pvDeadbandPlugin.h"
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::size_t;
|
using std::size_t;
|
||||||
@@ -64,9 +67,9 @@ PVDeadbandFilterPtr PVDeadbandFilter::create(
|
|||||||
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
|
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
|
||||||
if(!ScalarTypeFunc::isNumeric(scalar->getScalarType())) return PVDeadbandFilterPtr();
|
if(!ScalarTypeFunc::isNumeric(scalar->getScalarType())) return PVDeadbandFilterPtr();
|
||||||
bool absolute = false;
|
bool absolute = false;
|
||||||
if(requestValue.find("abs")>=0) {
|
if(requestValue.find("abs")==0) {
|
||||||
absolute = true;
|
absolute = true;
|
||||||
} else if(requestValue.find("rel")>=0) {
|
} else if(requestValue.find("rel")==0) {
|
||||||
absolute = false;
|
absolute = false;
|
||||||
} else {
|
} else {
|
||||||
return PVDeadbandFilterPtr();
|
return PVDeadbandFilterPtr();
|
||||||
@@ -125,8 +128,7 @@ bool PVDeadbandFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet
|
|||||||
|
|
||||||
string PVDeadbandFilter::getName()
|
string PVDeadbandFilter::getName()
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -4,9 +4,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <pv/lock.h>
|
||||||
|
#include <pv/bitSet.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvStructureCopy.h>
|
#include "pv/pvPlugin.h"
|
||||||
#include <pv/pvPlugin.h>
|
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
|
|
||||||
@@ -34,4 +38,3 @@ PVPluginPtr PVPluginRegistry::find(const std::string & name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -3,14 +3,17 @@
|
|||||||
* The License for this software can be found in the file LICENSE that is included with the distribution.
|
* The License for this software can be found in the file LICENSE that is included with the distribution.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <pv/lock.h>
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/bitSet.h>
|
#include <pv/bitSet.h>
|
||||||
#include <pv/convert.h>
|
#include <pv/convert.h>
|
||||||
#include <pv/pvTimeStamp.h>
|
#include <pv/pvTimeStamp.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvTimestampPlugin.h>
|
#include "pv/pvPlugin.h"
|
||||||
#include <pv/pvStructureCopy.h>
|
#include "pv/pvTimestampPlugin.h"
|
||||||
|
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::size_t;
|
using std::size_t;
|
||||||
@@ -117,8 +120,7 @@ bool PVTimestampFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSe
|
|||||||
|
|
||||||
string PVTimestampFilter::getName()
|
string PVTimestampFilter::getName()
|
||||||
{
|
{
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <epicsGuard.h>
|
#include <epicsGuard.h>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvDatabase.h>
|
#include "pv/pvStructureCopy.h"
|
||||||
#include <pv/pvStructureCopy.h>
|
#include "pv/pvDatabase.h"
|
||||||
#include <pv/pvPlugin.h>
|
#include "pv/pvPlugin.h"
|
||||||
#include <pv/pvArrayPlugin.h>
|
#include "pv/pvArrayPlugin.h"
|
||||||
#include <pv/pvTimestampPlugin.h>
|
#include "pv/pvTimestampPlugin.h"
|
||||||
#include <pv/pvDeadbandPlugin.h>
|
#include "pv/pvDeadbandPlugin.h"
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -50,14 +56,6 @@ PVDatabase::PVDatabase()
|
|||||||
PVDatabase::~PVDatabase()
|
PVDatabase::~PVDatabase()
|
||||||
{
|
{
|
||||||
if(DEBUG_LEVEL>0) cout << "PVDatabase::~PVDatabase()\n";
|
if(DEBUG_LEVEL>0) cout << "PVDatabase::~PVDatabase()\n";
|
||||||
size_t len = recordMap.size();
|
|
||||||
shared_vector<string> names(len);
|
|
||||||
PVRecordMap::iterator iter;
|
|
||||||
size_t i = 0;
|
|
||||||
for(iter = recordMap.begin(); iter!=recordMap.end(); ++iter) {
|
|
||||||
names[i++] = (*iter).first;
|
|
||||||
}
|
|
||||||
for(size_t i=0; i<len; ++i) removeRecord(findRecord(names[i]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVDatabase::lock() {
|
void PVDatabase::lock() {
|
||||||
@@ -94,17 +92,28 @@ bool PVDatabase::addRecord(PVRecordPtr const & record)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PVDatabase::removeRecord(PVRecordPtr const & record)
|
PVRecordWPtr PVDatabase::removeFromMap(PVRecordPtr const & record)
|
||||||
{
|
{
|
||||||
if(record->getTraceLevel()>0) {
|
|
||||||
cout << "PVDatabase::removeRecord " << record->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||||
string recordName = record->getRecordName();
|
string recordName = record->getRecordName();
|
||||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||||
if(iter!=recordMap.end()) {
|
if(iter!=recordMap.end()) {
|
||||||
PVRecordPtr pvRecord = (*iter).second;
|
PVRecordPtr pvRecord = (*iter).second;
|
||||||
recordMap.erase(iter);
|
recordMap.erase(iter);
|
||||||
|
return pvRecord->shared_from_this();
|
||||||
|
}
|
||||||
|
return PVRecordWPtr();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PVDatabase::removeRecord(PVRecordPtr const & record)
|
||||||
|
{
|
||||||
|
if(record->getTraceLevel()>0) {
|
||||||
|
cout << "PVDatabase::removeRecord " << record->getRecordName() << endl;
|
||||||
|
}
|
||||||
|
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||||
|
PVRecordWPtr pvRecord = removeFromMap(record);
|
||||||
|
if(pvRecord.use_count()!=0) {
|
||||||
|
pvRecord.lock()->unlistenClients();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -8,13 +8,25 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2012.11.21
|
* @date 2012.11.21
|
||||||
*/
|
*/
|
||||||
|
#include <list>
|
||||||
#include <epicsGuard.h>
|
#include <epicsGuard.h>
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
|
#include <pv/status.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/createRequest.h>
|
||||||
|
#include <pv/pvaVersion.h>
|
||||||
|
#include <pv/pvaVersionNum.h>
|
||||||
|
#include <pv/monitor.h>
|
||||||
|
#include <pv/convert.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/timeStamp.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/pvDatabase.h>
|
#include "pv/pvStructureCopy.h"
|
||||||
#include <pv/pvStructureCopy.h>
|
#include "pv/pvDatabase.h"
|
||||||
|
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -46,16 +58,16 @@ PVRecord::PVRecord(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVRecord::notifyClients()
|
PVRecord::~PVRecord()
|
||||||
{
|
{
|
||||||
{
|
if(traceLevel>0) {
|
||||||
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
cout << "~PVRecord() " << recordName << endl;
|
||||||
if(traceLevel>0) {
|
|
||||||
cout << "PVRecord::notifyClients() " << recordName
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pvTimeStamp.detach();
|
}
|
||||||
|
|
||||||
|
void PVRecord::unlistenClients()
|
||||||
|
{
|
||||||
|
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||||
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
|
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
|
||||||
iter!=pvListenerList.end();
|
iter!=pvListenerList.end();
|
||||||
iter++ )
|
iter++ )
|
||||||
@@ -63,8 +75,7 @@ void PVRecord::notifyClients()
|
|||||||
PVListenerPtr listener = iter->lock();
|
PVListenerPtr listener = iter->lock();
|
||||||
if(!listener) continue;
|
if(!listener) continue;
|
||||||
if(traceLevel>0) {
|
if(traceLevel>0) {
|
||||||
cout << "PVRecord::notifyClients() calling listener->unlisten "
|
cout << "PVRecord::remove() calling listener->unlisten " << recordName << endl;
|
||||||
<< recordName << endl;
|
|
||||||
}
|
}
|
||||||
listener->unlisten(shared_from_this());
|
listener->unlisten(shared_from_this());
|
||||||
}
|
}
|
||||||
@@ -76,27 +87,24 @@ void PVRecord::notifyClients()
|
|||||||
PVRecordClientPtr client = iter->lock();
|
PVRecordClientPtr client = iter->lock();
|
||||||
if(!client) continue;
|
if(!client) continue;
|
||||||
if(traceLevel>0) {
|
if(traceLevel>0) {
|
||||||
cout << "PVRecord::notifyClients() calling client->detach "
|
cout << "PVRecord::remove() calling client->detach " << recordName << endl;
|
||||||
<< recordName << endl;
|
|
||||||
}
|
}
|
||||||
client->detach(shared_from_this());
|
client->detach(shared_from_this());
|
||||||
}
|
}
|
||||||
if(traceLevel>0) {
|
|
||||||
cout << "PVRecord::notifyClients() calling clientList.clear() "
|
|
||||||
<< recordName << endl;
|
|
||||||
}
|
|
||||||
clientList.clear();
|
clientList.clear();
|
||||||
if(traceLevel>0) {
|
|
||||||
cout << "PVRecord::notifyClients() returning " << recordName << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PVRecord::~PVRecord()
|
|
||||||
|
void PVRecord::remove()
|
||||||
{
|
{
|
||||||
if(traceLevel>0) {
|
if(traceLevel>0) {
|
||||||
cout << "~PVRecord() " << recordName << endl;
|
cout << "PVRecord::remove() " << recordName << endl;
|
||||||
}
|
}
|
||||||
notifyClients();
|
unlistenClients();
|
||||||
|
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||||
|
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
|
||||||
|
if(pvDatabase) pvDatabase->removeFromMap(shared_from_this());
|
||||||
|
pvTimeStamp.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PVRecord::initPVRecord()
|
void PVRecord::initPVRecord()
|
||||||
|
|||||||
63
src/pv/addRecord.h
Normal file
63
src/pv/addRecord.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/* addRecord.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.04.18
|
||||||
|
*/
|
||||||
|
#ifndef ADDRECORD_H
|
||||||
|
#define ADDRECORD_H
|
||||||
|
|
||||||
|
#include <pv/channelProviderLocal.h>
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
|
||||||
|
class AddRecord;
|
||||||
|
typedef std::tr1::shared_ptr<AddRecord> AddRecordPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add another record in the same database.
|
||||||
|
*
|
||||||
|
* A record to add another record
|
||||||
|
* It is meant to be used via a channelPutGet request.
|
||||||
|
* The argument has one field: recordName.
|
||||||
|
* The result has a field named status.
|
||||||
|
*/
|
||||||
|
class epicsShareClass AddRecord :
|
||||||
|
public PVRecord
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
POINTER_DEFINITIONS(AddRecord);
|
||||||
|
/**
|
||||||
|
* Factory methods to create AddRecord.
|
||||||
|
* @param recordName The name for the AddRecord.
|
||||||
|
* @return A shared pointer to AddRecord..
|
||||||
|
*/
|
||||||
|
static AddRecordPtr create(
|
||||||
|
std::string const & recordName);
|
||||||
|
/**
|
||||||
|
* standard init method required by PVRecord
|
||||||
|
* @return true unless record name already exists.
|
||||||
|
*/
|
||||||
|
virtual bool init();
|
||||||
|
/**
|
||||||
|
* @brief Add the record specified by recordName.
|
||||||
|
*/
|
||||||
|
virtual void process();
|
||||||
|
private:
|
||||||
|
AddRecord(
|
||||||
|
std::string const & recordName,
|
||||||
|
epics::pvData::PVStructurePtr const & pvStructure);
|
||||||
|
epics::pvData::PVStringPtr pvRecordName;
|
||||||
|
epics::pvData::PVStringPtr pvResult;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif /* ADDRECORD_H */
|
||||||
@@ -11,11 +11,6 @@
|
|||||||
#ifndef CHANNELPROVIDERLOCAL_H
|
#ifndef CHANNELPROVIDERLOCAL_H
|
||||||
#define CHANNELPROVIDERLOCAL_H
|
#define CHANNELPROVIDERLOCAL_H
|
||||||
|
|
||||||
#ifdef epicsExportSharedSymbols
|
|
||||||
# define channelProviderLocalEpicsExportSharedSymbols
|
|
||||||
# undef epicsExportSharedSymbols
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
@@ -28,16 +23,10 @@
|
|||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/status.h>
|
#include <pv/status.h>
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
|
#include <pv/pvStructureCopy.h>
|
||||||
|
#include <pv/pvDatabase.h>
|
||||||
#ifdef channelProviderLocalEpicsExportSharedSymbols
|
|
||||||
# define epicsExportSharedSymbols
|
|
||||||
# undef channelProviderLocalEpicsExportSharedSymbols
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
#include <pv/pvDatabase.h>
|
|
||||||
#include <pv/pvStructureCopy.h>
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
|||||||
89
src/pv/controlSupport.h
Normal file
89
src/pv/controlSupport.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* 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 2019.06.01
|
||||||
|
*/
|
||||||
|
#ifndef CONTROLSUPPORT_H
|
||||||
|
#define CONTROLSUPPORT_H
|
||||||
|
|
||||||
|
#include <pv/pvDatabase.h>
|
||||||
|
#include <pv/pvSupport.h>
|
||||||
|
#include <pv/pvStructureCopy.h>
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
class ControlSupport;
|
||||||
|
typedef std::tr1::shared_ptr<ControlSupport> ControlSupportPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base interface for a ControlSupport.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class epicsShareClass ControlSupport :
|
||||||
|
PVSupport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
POINTER_DEFINITIONS(ControlSupport);
|
||||||
|
/**
|
||||||
|
* The Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~ControlSupport();
|
||||||
|
/**
|
||||||
|
* @brief Connects to contol fields.
|
||||||
|
*
|
||||||
|
* @param pvValue The field to support.
|
||||||
|
* @param pvSupport Support specific fields.
|
||||||
|
* @return <b>true</b> for success and <b>false</b> for failure.
|
||||||
|
*/
|
||||||
|
virtual bool init(
|
||||||
|
epics::pvData::PVFieldPtr const & pvValue,
|
||||||
|
epics::pvData::PVFieldPtr const & pvSupport);
|
||||||
|
/**
|
||||||
|
* @brief Honors control fields.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return Returns true is any fields were modified; otherwise false.
|
||||||
|
*/
|
||||||
|
virtual bool process();
|
||||||
|
/**
|
||||||
|
* @brief If implementing minSteps it sets isMinStep to false.
|
||||||
|
*
|
||||||
|
* @return Returns true is any fields were modified; otherwise false.
|
||||||
|
*/
|
||||||
|
virtual void reset();
|
||||||
|
/**
|
||||||
|
* @brief create a ControlSupport
|
||||||
|
*
|
||||||
|
* @param pvRecord - The pvRecord to which the support is attached.
|
||||||
|
* @return The new ControlSupport
|
||||||
|
*/
|
||||||
|
static ControlSupportPtr create(PVRecordPtr const & pvRecord);
|
||||||
|
/**
|
||||||
|
* @brief create a controlSupport required by ControlSupport
|
||||||
|
*
|
||||||
|
* @param scalarType The type for outputValue.
|
||||||
|
* @return The controlField introspection structure.
|
||||||
|
*/
|
||||||
|
static epics::pvData::StructureConstPtr controlField(epics::pvData::ScalarType scalarType);
|
||||||
|
private:
|
||||||
|
ControlSupport(PVRecordPtr const & pvRecord);
|
||||||
|
PVRecordPtr pvRecord;
|
||||||
|
epics::pvData::PVScalarPtr pvValue;
|
||||||
|
epics::pvData::PVStructurePtr pvControl;
|
||||||
|
epics::pvData::PVDoublePtr pvLimitLow;
|
||||||
|
epics::pvData::PVDoublePtr pvLimitHigh;
|
||||||
|
epics::pvData::PVDoublePtr pvMinStep;
|
||||||
|
epics::pvData::PVScalarPtr pvOutputValue;
|
||||||
|
double currentValue;
|
||||||
|
bool isMinStep;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif /* CONTROLSUPPORT_H */
|
||||||
89
src/pv/processRecord.h
Normal file
89
src/pv/processRecord.h
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/* processRecord.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 2019.06.07
|
||||||
|
*/
|
||||||
|
#ifndef PROCESSRECORD_H
|
||||||
|
#define PROCESSRECORD_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <epicsThread.h>
|
||||||
|
#include <pv/event.h>
|
||||||
|
#include <pv/channelProviderLocal.h>
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
|
||||||
|
|
||||||
|
class ProcessRecord;
|
||||||
|
typedef std::tr1::shared_ptr<ProcessRecord> ProcessRecordPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Process another record in the same database.
|
||||||
|
*
|
||||||
|
* A record to process another record
|
||||||
|
* It is meant to be used via a channelPutGet request.
|
||||||
|
* The argument has one field: recordName.
|
||||||
|
* The result has a field named status.
|
||||||
|
*/
|
||||||
|
class epicsShareClass ProcessRecord :
|
||||||
|
public PVRecord,
|
||||||
|
public epicsThreadRunable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
POINTER_DEFINITIONS(ProcessRecord);
|
||||||
|
/**
|
||||||
|
* Factory methods to create ProcessRecord.
|
||||||
|
* @param recordName The name for the ProcessRecord.
|
||||||
|
* @param delay Delay time to wait between process requests.
|
||||||
|
* @return A shared pointer to ProcessRecord.
|
||||||
|
*/
|
||||||
|
static ProcessRecordPtr create(
|
||||||
|
std::string const & recordName,double delay);
|
||||||
|
/**
|
||||||
|
* standard init method required by PVRecord
|
||||||
|
* @return true unless record name already exists.
|
||||||
|
*/
|
||||||
|
virtual bool init();
|
||||||
|
/**
|
||||||
|
* @brief Process the record specified by recordName.
|
||||||
|
*/
|
||||||
|
virtual void process();
|
||||||
|
/**
|
||||||
|
* @brief The run method for the thread.
|
||||||
|
*/
|
||||||
|
virtual void run();
|
||||||
|
/**
|
||||||
|
* @brief Start the thread
|
||||||
|
*/
|
||||||
|
void startThread();
|
||||||
|
/**
|
||||||
|
* @brief Stop the thread
|
||||||
|
*/
|
||||||
|
void stop();
|
||||||
|
private:
|
||||||
|
ProcessRecord(
|
||||||
|
std::string const & recordName,
|
||||||
|
epics::pvData::PVStructurePtr const & pvStructure,double delay);
|
||||||
|
double delay;
|
||||||
|
EpicsThreadPtr thread;
|
||||||
|
epics::pvData::Event runStop;
|
||||||
|
epics::pvData::Event runReturn;
|
||||||
|
PVDatabasePtr pvDatabase;
|
||||||
|
PVRecordMap pvRecordMap;
|
||||||
|
epics::pvData::PVStringPtr pvCommand;
|
||||||
|
epics::pvData::PVStringPtr pvRecordName;
|
||||||
|
epics::pvData::PVStringPtr pvResult;
|
||||||
|
epics::pvData::Mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif /* PROCESSRECORD_H */
|
||||||
@@ -6,10 +6,6 @@
|
|||||||
#ifndef PVARRAYPLUGIN_H
|
#ifndef PVARRAYPLUGIN_H
|
||||||
#define PVARRAYPLUGIN_H
|
#define PVARRAYPLUGIN_H
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
@@ -67,9 +63,13 @@ private:
|
|||||||
long start;
|
long start;
|
||||||
long increment;
|
long increment;
|
||||||
long end;
|
long end;
|
||||||
|
epics::pvData::PVFieldPtr masterField;
|
||||||
epics::pvData::PVScalarArrayPtr masterArray;
|
epics::pvData::PVScalarArrayPtr masterArray;
|
||||||
|
|
||||||
PVArrayFilter(long start,long increment,long end,const epics::pvData::PVScalarArrayPtr & masterArray);
|
PVArrayFilter(
|
||||||
|
long start,long increment,long end,
|
||||||
|
const epics::pvData::PVFieldPtr & masterField,
|
||||||
|
const epics::pvData::PVScalarArrayPtr masterArray);
|
||||||
public:
|
public:
|
||||||
POINTER_DEFINITIONS(PVArrayFilter);
|
POINTER_DEFINITIONS(PVArrayFilter);
|
||||||
virtual ~PVArrayFilter();
|
virtual ~PVArrayFilter();
|
||||||
@@ -99,4 +99,3 @@ public:
|
|||||||
|
|
||||||
}}
|
}}
|
||||||
#endif /* PVARRAYPLUGIN_H */
|
#endif /* PVARRAYPLUGIN_H */
|
||||||
|
|
||||||
@@ -6,26 +6,15 @@
|
|||||||
#ifndef PVDATABASE_H
|
#ifndef PVDATABASE_H
|
||||||
#define PVDATABASE_H
|
#define PVDATABASE_H
|
||||||
|
|
||||||
#ifdef epicsExportSharedSymbols
|
|
||||||
# define pvdatabaseEpicsExportSharedSymbols
|
|
||||||
# undef epicsExportSharedSymbols
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include <pv/pvData.h>
|
#include <pv/pvData.h>
|
||||||
#include <pv/pvTimeStamp.h>
|
#include <pv/pvTimeStamp.h>
|
||||||
#include <pv/rpcService.h>
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/pvStructureCopy.h>
|
||||||
|
|
||||||
#ifdef pvdatabaseEpicsExportSharedSymbols
|
|
||||||
# define epicsExportSharedSymbols
|
|
||||||
# undef pvdatabaseEpicsExportSharedSymbols
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
#include <pv/pvStructureCopy.h>
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
@@ -101,6 +90,15 @@ public:
|
|||||||
* @brief DEPRECATED
|
* @brief DEPRECATED
|
||||||
*/
|
*/
|
||||||
virtual void destroy() {}
|
virtual void destroy() {}
|
||||||
|
/**
|
||||||
|
* @brief remove record from database.
|
||||||
|
*
|
||||||
|
* Remove the PVRecord. Release any resources used and
|
||||||
|
* get rid of listeners and requesters.
|
||||||
|
* If derived class overrides this then it must call PVRecord::remove()
|
||||||
|
* after it has destroyed any resorces it uses.
|
||||||
|
*/
|
||||||
|
virtual void remove();
|
||||||
/**
|
/**
|
||||||
* @brief Optional method for derived class.
|
* @brief Optional method for derived class.
|
||||||
*
|
*
|
||||||
@@ -254,10 +252,12 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void initPVRecord();
|
void initPVRecord();
|
||||||
private:
|
private:
|
||||||
|
friend class PVDatabase;
|
||||||
|
void unlistenClients();
|
||||||
|
|
||||||
PVRecordFieldPtr findPVRecordField(
|
PVRecordFieldPtr findPVRecordField(
|
||||||
PVRecordStructurePtr const & pvrs,
|
PVRecordStructurePtr const & pvrs,
|
||||||
epics::pvData::PVFieldPtr const & pvField);
|
epics::pvData::PVFieldPtr const & pvField);
|
||||||
void notifyClients();
|
|
||||||
|
|
||||||
std::string recordName;
|
std::string recordName;
|
||||||
epics::pvData::PVStructurePtr pvStructure;
|
epics::pvData::PVStructurePtr pvStructure;
|
||||||
@@ -501,6 +501,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Remove a record.
|
* @brief Remove a record.
|
||||||
* @param record The record to remove.
|
* @param record The record to remove.
|
||||||
|
*
|
||||||
* @return <b>true</b> if record was removed.
|
* @return <b>true</b> if record was removed.
|
||||||
*/
|
*/
|
||||||
bool removeRecord(PVRecordPtr const & record);
|
bool removeRecord(PVRecordPtr const & record);
|
||||||
@@ -510,6 +511,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
epics::pvData::PVStringArrayPtr getRecordNames();
|
epics::pvData::PVStringArrayPtr getRecordNames();
|
||||||
private:
|
private:
|
||||||
|
friend class PVRecord;
|
||||||
|
|
||||||
|
PVRecordWPtr removeFromMap(PVRecordPtr const & record);
|
||||||
PVDatabase();
|
PVDatabase();
|
||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
@@ -521,4 +525,3 @@ private:
|
|||||||
}}
|
}}
|
||||||
|
|
||||||
#endif /* PVDATABASE_H */
|
#endif /* PVDATABASE_H */
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,6 @@
|
|||||||
#ifndef PVDEADBANDPLUGIN_H
|
#ifndef PVDEADBANDPLUGIN_H
|
||||||
#define PVDEADBANDPLUGIN_H
|
#define PVDEADBANDPLUGIN_H
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -103,4 +100,3 @@ public:
|
|||||||
|
|
||||||
}}
|
}}
|
||||||
#endif /* PVDEADBANDPLUGIN_H */
|
#endif /* PVDEADBANDPLUGIN_H */
|
||||||
|
|
||||||
@@ -9,14 +9,10 @@
|
|||||||
#ifndef PVPLUGIN_H
|
#ifndef PVPLUGIN_H
|
||||||
#define PVPLUGIN_H
|
#define PVPLUGIN_H
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
#include <pv/pvStructureCopy.h>
|
#include <pv/bitSet.h>
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|
||||||
@@ -26,6 +22,9 @@ class PVPlugin;
|
|||||||
class PVFilter;
|
class PVFilter;
|
||||||
class PVPluginRegistry;
|
class PVPluginRegistry;
|
||||||
|
|
||||||
|
class PVCopy;
|
||||||
|
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
|
||||||
|
|
||||||
typedef std::tr1::shared_ptr<PVPlugin> PVPluginPtr;
|
typedef std::tr1::shared_ptr<PVPlugin> PVPluginPtr;
|
||||||
typedef std::tr1::shared_ptr<PVFilter> PVFilterPtr;
|
typedef std::tr1::shared_ptr<PVFilter> PVFilterPtr;
|
||||||
typedef std::map<std::string,PVPluginPtr> PVPluginMap;
|
typedef std::map<std::string,PVPluginPtr> PVPluginMap;
|
||||||
@@ -10,10 +10,6 @@
|
|||||||
#ifndef PVSTRUCTURECOPY_H
|
#ifndef PVSTRUCTURECOPY_H
|
||||||
#define PVSTRUCTURECOPY_H
|
#define PVSTRUCTURECOPY_H
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -204,10 +200,16 @@ private:
|
|||||||
epics::pvData::PVFieldPtr const &pvCopy,
|
epics::pvData::PVFieldPtr const &pvCopy,
|
||||||
CopyNodePtr const &node,
|
CopyNodePtr const &node,
|
||||||
epics::pvData::BitSetPtr const &bitSet);
|
epics::pvData::BitSetPtr const &bitSet);
|
||||||
void updateMaster(
|
void updateMasterField(
|
||||||
epics::pvData::PVFieldPtr const &pvCopy,
|
CopyNodePtr const & node,
|
||||||
CopyNodePtr const &node,
|
epics::pvData::PVFieldPtr const & pvCopy,
|
||||||
|
epics::pvData::PVFieldPtr const &pvMaster,
|
||||||
epics::pvData::BitSetPtr const &bitSet);
|
epics::pvData::BitSetPtr const &bitSet);
|
||||||
|
void updateMasterCheckBitSet(
|
||||||
|
epics::pvData::PVStructurePtr const ©PVStructure,
|
||||||
|
epics::pvData::BitSetPtr const &bitSet,
|
||||||
|
size_t nextSet);
|
||||||
|
CopyNodePtr getCopyNode(std::size_t fieldOffset);
|
||||||
|
|
||||||
PVCopy(epics::pvData::PVStructurePtr const &pvMaster);
|
PVCopy(epics::pvData::PVStructurePtr const &pvMaster);
|
||||||
bool init(epics::pvData::PVStructurePtr const &pvRequest);
|
bool init(epics::pvData::PVStructurePtr const &pvRequest);
|
||||||
@@ -239,7 +241,6 @@ private:
|
|||||||
std::string *builder,
|
std::string *builder,
|
||||||
CopyNodePtr const &node,
|
CopyNodePtr const &node,
|
||||||
int indentLevel);
|
int indentLevel);
|
||||||
friend class PVCopyMonitor;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}}
|
}}
|
||||||
77
src/pv/pvSupport.h
Normal file
77
src/pv/pvSupport.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* 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 2019.06.01
|
||||||
|
*/
|
||||||
|
#ifndef PVSUPPORT_H
|
||||||
|
#define PVSUPPORT_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/pvStructureCopy.h>
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
class PVSupport;
|
||||||
|
typedef std::tr1::shared_ptr<PVSupport> PVSupportPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base interface for a PVSupport.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class epicsShareClass PVSupport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
POINTER_DEFINITIONS(PVSupport);
|
||||||
|
/**
|
||||||
|
* The Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~PVSupport(){}
|
||||||
|
/**
|
||||||
|
* @brief Optional initialization method.
|
||||||
|
*
|
||||||
|
* Called after PVRecord is created but before record is installed into PVDatabase.
|
||||||
|
*
|
||||||
|
* @param pvValue The field to support.
|
||||||
|
* @param pvSupport Support specific fields.
|
||||||
|
* @return <b>true</b> for success and <b>false</b> for failure.
|
||||||
|
*/
|
||||||
|
virtual bool init(
|
||||||
|
epics::pvData::PVFieldPtr const & pvValue,
|
||||||
|
epics::pvData::PVFieldPtr const & pvSupport) {return true;}
|
||||||
|
/**
|
||||||
|
* @brief Optional method for derived class.
|
||||||
|
*
|
||||||
|
* It is called before record is added to database.
|
||||||
|
*/
|
||||||
|
virtual void start() {}
|
||||||
|
/**
|
||||||
|
* @brief Virtual method for derived class.
|
||||||
|
*
|
||||||
|
* Called when record is processed.
|
||||||
|
* It is the method that implements support.
|
||||||
|
* It is called each time the record is processed.
|
||||||
|
*
|
||||||
|
* @return Returns true is any fields were modified; otherwise false.
|
||||||
|
*/
|
||||||
|
virtual bool process() = 0;
|
||||||
|
/**
|
||||||
|
* @brief Optional method for derived class.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
virtual void reset() {};
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif /* PVSUPPORT_H */
|
||||||
@@ -6,10 +6,6 @@
|
|||||||
#ifndef PVTIMESTAMPPLUGIN_H
|
#ifndef PVTIMESTAMPPLUGIN_H
|
||||||
#define PVTIMESTAMPPLUGIN_H
|
#define PVTIMESTAMPPLUGIN_H
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
|
||||||
#define NOMINMAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <pv/lock.h>
|
#include <pv/lock.h>
|
||||||
@@ -60,7 +56,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A filter that sets a timeStamp to the current time.
|
* @brief A filter that sets a timeStamp to/from the current field or pvCopy.
|
||||||
*/
|
*/
|
||||||
class epicsShareClass PVTimestampFilter : public PVFilter
|
class epicsShareClass PVTimestampFilter : public PVFilter
|
||||||
{
|
{
|
||||||
@@ -102,4 +98,3 @@ public:
|
|||||||
|
|
||||||
}}
|
}}
|
||||||
#endif /* PVTIMESTAMPPLUGIN_H */
|
#endif /* PVTIMESTAMPPLUGIN_H */
|
||||||
|
|
||||||
@@ -11,10 +11,10 @@
|
|||||||
#ifndef REMOVERECORD_H
|
#ifndef REMOVERECORD_H
|
||||||
#define REMOVERECORD_H
|
#define REMOVERECORD_H
|
||||||
|
|
||||||
#include <shareLib.h>
|
|
||||||
|
|
||||||
#include <pv/channelProviderLocal.h>
|
#include <pv/channelProviderLocal.h>
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
110
src/pv/scalarAlarmSupport.h
Normal file
110
src/pv/scalarAlarmSupport.h
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/**
|
||||||
|
* 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 2019.06.01
|
||||||
|
*/
|
||||||
|
#ifndef SCALARALARMSUPPORT_H
|
||||||
|
#define SCALARALARMSUPPORT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <pv/pvDatabase.h>
|
||||||
|
#include <pv/pvSupport.h>
|
||||||
|
#include <pv/alarm.h>
|
||||||
|
#include <pv/pvAlarm.h>
|
||||||
|
#include <pv/pvStructureCopy.h>
|
||||||
|
|
||||||
|
#include <shareLib.h>
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
class ScalarAlarmSupport;
|
||||||
|
typedef std::tr1::shared_ptr<ScalarAlarmSupport> ScalarAlarmSupportPtr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base interface for a ScalarAlarmSupport.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class epicsShareClass ScalarAlarmSupport :
|
||||||
|
PVSupport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
POINTER_DEFINITIONS(ScalarAlarmSupport);
|
||||||
|
/**
|
||||||
|
* The Destructor.
|
||||||
|
*/
|
||||||
|
virtual ~ScalarAlarmSupport();
|
||||||
|
/**
|
||||||
|
* @brief Connects to contol fields.
|
||||||
|
*
|
||||||
|
* @param pvValue The field to support.
|
||||||
|
* @param pvAlarm The alarm field.
|
||||||
|
* @param pvSupport Support specific fields.
|
||||||
|
* @return <b>true</b> for success and <b>false</b> for failure.
|
||||||
|
*/
|
||||||
|
virtual bool init(
|
||||||
|
epics::pvData::PVFieldPtr const & pvValue,
|
||||||
|
epics::pvData::PVStructurePtr const & pvAlarm,
|
||||||
|
epics::pvData::PVFieldPtr const & pvSupport);
|
||||||
|
/**
|
||||||
|
* @brief Honors scalarAlarm fields.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @return Returns true is any fields were modified; otherwise false.
|
||||||
|
*/
|
||||||
|
virtual bool process();
|
||||||
|
/**
|
||||||
|
* @brief If implementing minSteps it sets isMinStep to false.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
virtual void reset();
|
||||||
|
/**
|
||||||
|
* @brief create a ScalarAlarm
|
||||||
|
*
|
||||||
|
* @param pvRecord - The pvRecord to which the support is attached.
|
||||||
|
* @return The new ScalarAlarm
|
||||||
|
*/
|
||||||
|
static ScalarAlarmSupportPtr create(PVRecordPtr const & pvRecord);
|
||||||
|
/**
|
||||||
|
* @brief create a scalarAlarm required by ScalarAlarm
|
||||||
|
*
|
||||||
|
* @return The scalarAlarmField introspection structure.
|
||||||
|
*/
|
||||||
|
static epics::pvData::StructureConstPtr scalarAlarmField();
|
||||||
|
private:
|
||||||
|
|
||||||
|
ScalarAlarmSupport(PVRecordPtr const & pvRecord);
|
||||||
|
enum {
|
||||||
|
range_Lolo = 0,
|
||||||
|
range_Low,
|
||||||
|
range_Normal,
|
||||||
|
range_High,
|
||||||
|
range_Hihi,
|
||||||
|
range_Invalid,
|
||||||
|
range_Undefined
|
||||||
|
} AlarmRange;
|
||||||
|
void setAlarm(
|
||||||
|
epics::pvData::PVStructurePtr const & pvAlarm,
|
||||||
|
int alarmRange);
|
||||||
|
PVRecordPtr pvRecord;
|
||||||
|
int prevAlarmRange;
|
||||||
|
epics::pvData::PVScalarPtr pvValue;
|
||||||
|
epics::pvData::PVStructurePtr pvAlarm;
|
||||||
|
epics::pvData::PVStructurePtr pvScalarAlarm;
|
||||||
|
epics::pvData::PVBooleanPtr pvActive;
|
||||||
|
epics::pvData::PVDoublePtr pvLowAlarmLimit;
|
||||||
|
epics::pvData::PVDoublePtr pvLowWarningLimit;
|
||||||
|
epics::pvData::PVDoublePtr pvHighWarningLimit;
|
||||||
|
epics::pvData::PVDoublePtr pvHighAlarmLimit;
|
||||||
|
epics::pvData::PVDoublePtr pvHysteresis;
|
||||||
|
double requestedValue;
|
||||||
|
double currentValue;
|
||||||
|
bool isHystersis;
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#endif /* SCALARALARMSUPPORT_H */
|
||||||
@@ -11,9 +11,10 @@
|
|||||||
#ifndef TRACERECORD_H
|
#ifndef TRACERECORD_H
|
||||||
#define TRACERECORD_H
|
#define TRACERECORD_H
|
||||||
|
|
||||||
|
#include <pv/channelProviderLocal.h>
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|
||||||
#include <pv/channelProviderLocal.h>
|
|
||||||
|
|
||||||
namespace epics { namespace pvDatabase {
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,21 @@
|
|||||||
|
|
||||||
#include <epicsGuard.h>
|
#include <epicsGuard.h>
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
#include <pv/timeStamp.h>
|
#include <pv/timeStamp.h>
|
||||||
|
#include <pv/createRequest.h>
|
||||||
|
#include <pv/pvaVersion.h>
|
||||||
|
#include <pv/pvaVersionNum.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
#include <pv/pvSubArrayCopy.h>
|
#include <pv/pvSubArrayCopy.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
#include <pv/channelProviderLocal.h>
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/channelProviderLocal.h"
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
@@ -59,7 +68,7 @@ static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
|
|||||||
return pvString->get().compare("true")==0 ? true : false;
|
return pvString->get().compare("true")==0 ? true : false;
|
||||||
} else if(scalar->getScalarType()==pvBoolean) {
|
} else if(scalar->getScalarType()==pvBoolean) {
|
||||||
PVBooleanPtr pvBoolean = static_pointer_cast<PVBoolean>(pvField);
|
PVBooleanPtr pvBoolean = static_pointer_cast<PVBoolean>(pvField);
|
||||||
return pvBoolean->get();
|
return pvBoolean->get();
|
||||||
}
|
}
|
||||||
return processDefault;
|
return processDefault;
|
||||||
}
|
}
|
||||||
@@ -123,7 +132,7 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
|
|||||||
if(pvField) {
|
if(pvField) {
|
||||||
PVStringPtr pvString = pvOptions->getSubField<PVString>("nProcess");
|
PVStringPtr pvString = pvOptions->getSubField<PVString>("nProcess");
|
||||||
if(pvString) {
|
if(pvString) {
|
||||||
int size;
|
int size=0;
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << pvString->get();
|
ss << pvString->get();
|
||||||
ss >> size;
|
ss >> size;
|
||||||
@@ -147,10 +156,7 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
|
|||||||
|
|
||||||
ChannelProcessLocal::~ChannelProcessLocal()
|
ChannelProcessLocal::~ChannelProcessLocal()
|
||||||
{
|
{
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
//cout << "~ChannelProcessLocal()\n";
|
||||||
if(pvr && pvr->getTraceLevel()>0) {
|
|
||||||
cout << "~ChannelProcessLocal() " << pvr->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel()
|
std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel()
|
||||||
@@ -295,10 +301,7 @@ ChannelGetLocalPtr ChannelGetLocal::create(
|
|||||||
|
|
||||||
ChannelGetLocal::~ChannelGetLocal()
|
ChannelGetLocal::~ChannelGetLocal()
|
||||||
{
|
{
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
//cout << "~ChannelGetLocal()\n";
|
||||||
if(pvr && pvr->getTraceLevel()>0) {
|
|
||||||
cout << "~ChannelGetLocal() " << pvr->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel()
|
std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel()
|
||||||
@@ -460,10 +463,7 @@ ChannelPutLocalPtr ChannelPutLocal::create(
|
|||||||
|
|
||||||
ChannelPutLocal::~ChannelPutLocal()
|
ChannelPutLocal::~ChannelPutLocal()
|
||||||
{
|
{
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
//cout << "~ChannelPutLocal()\n";
|
||||||
if(pvr && pvr->getTraceLevel()>0) {
|
|
||||||
cout << "~ChannelPutLocal() " << pvr->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel()
|
std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel()
|
||||||
@@ -653,10 +653,7 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
|
|||||||
|
|
||||||
ChannelPutGetLocal::~ChannelPutGetLocal()
|
ChannelPutGetLocal::~ChannelPutGetLocal()
|
||||||
{
|
{
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
//cout << "~ChannelPutGetLocal()\n";
|
||||||
if(pvr && pvr->getTraceLevel()>0) {
|
|
||||||
cout << "~ChannelPutGetLocal() " << pvr->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel()
|
std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel()
|
||||||
@@ -853,10 +850,7 @@ ChannelRPCLocalPtr ChannelRPCLocal::create(
|
|||||||
|
|
||||||
ChannelRPCLocal::~ChannelRPCLocal()
|
ChannelRPCLocal::~ChannelRPCLocal()
|
||||||
{
|
{
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
//cout << "~ChannelRPCLocal()\n";
|
||||||
if(pvr && pvr->getTraceLevel()>0) {
|
|
||||||
cout << "~ChannelRPCLocal() " << pvr->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel()
|
std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel()
|
||||||
@@ -1095,10 +1089,7 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
|
|||||||
|
|
||||||
ChannelArrayLocal::~ChannelArrayLocal()
|
ChannelArrayLocal::~ChannelArrayLocal()
|
||||||
{
|
{
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
//cout << "~ChannelArrayLocal()\n";
|
||||||
if(pvr && pvr->getTraceLevel()>0) {
|
|
||||||
cout << "~ChannelArrayLocal() " << pvr->getRecordName() << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel()
|
std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel()
|
||||||
@@ -1252,12 +1243,7 @@ ChannelLocal::ChannelLocal(
|
|||||||
|
|
||||||
ChannelLocal::~ChannelLocal()
|
ChannelLocal::~ChannelLocal()
|
||||||
{
|
{
|
||||||
PVRecordPtr pvr(pvRecord.lock());
|
// cout << "~ChannelLocal()" << endl;
|
||||||
if(!pvr) return;
|
|
||||||
if(pvr->getTraceLevel()>0)
|
|
||||||
{
|
|
||||||
cout << "~ChannelLocal()" << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelProvider::shared_pointer ChannelLocal::getProvider()
|
ChannelProvider::shared_pointer ChannelLocal::getProvider()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
/* channelChannelProviderLocal.cpp */
|
/* channelProviderLocal.cpp */
|
||||||
/**
|
/**
|
||||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||||
@@ -10,13 +10,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <epicsThread.h>
|
#include <epicsThread.h>
|
||||||
|
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
#include <pv/syncChannelFind.h>
|
#include <pv/syncChannelFind.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/timeStamp.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
#include <pv/channelProviderLocal.h>
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/channelProviderLocal.h"
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
|
|||||||
@@ -14,11 +14,17 @@
|
|||||||
#include <epicsGuard.h>
|
#include <epicsGuard.h>
|
||||||
#include <pv/thread.h>
|
#include <pv/thread.h>
|
||||||
#include <pv/bitSetUtil.h>
|
#include <pv/bitSetUtil.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
#include <pv/timeStamp.h>
|
#include <pv/timeStamp.h>
|
||||||
|
|
||||||
#define epicsExportSharedSymbols
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
#include <pv/channelProviderLocal.h>
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/channelProviderLocal.h"
|
||||||
|
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
using namespace epics::pvAccess;
|
using namespace epics::pvAccess;
|
||||||
@@ -185,10 +191,7 @@ MonitorLocal::MonitorLocal(
|
|||||||
|
|
||||||
MonitorLocal::~MonitorLocal()
|
MonitorLocal::~MonitorLocal()
|
||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>0)
|
//cout << "MonitorLocal::~MonitorLocal()" << endl;
|
||||||
{
|
|
||||||
cout << "MonitorLocal::~MonitorLocal()" << endl;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -288,7 +291,7 @@ void MonitorLocal::dataPut(PVRecordFieldPtr const & pvRecordField)
|
|||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl;
|
cout << "MonitorLocal::dataPut(pvRecordField)" << endl;
|
||||||
}
|
}
|
||||||
if(state!=active) return;
|
if(state!=active) return;
|
||||||
{
|
{
|
||||||
@@ -313,7 +316,7 @@ void MonitorLocal::dataPut(
|
|||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "PVCopyMonitor::dataPut(requested,pvRecordField)" << endl;
|
cout << "MonitorLocal::dataPut(requested,pvRecordField)" << endl;
|
||||||
}
|
}
|
||||||
if(state!=active) return;
|
if(state!=active) return;
|
||||||
{
|
{
|
||||||
@@ -340,7 +343,7 @@ void MonitorLocal::beginGroupPut(PVRecordPtr const & pvRecord)
|
|||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "PVCopyMonitor::beginGroupPut()" << endl;
|
cout << "MonitorLocal::beginGroupPut()" << endl;
|
||||||
}
|
}
|
||||||
if(state!=active) return;
|
if(state!=active) return;
|
||||||
{
|
{
|
||||||
@@ -354,7 +357,7 @@ void MonitorLocal::endGroupPut(PVRecordPtr const & pvRecord)
|
|||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "PVCopyMonitor::endGroupPut dataChanged " << dataChanged << endl;
|
cout << "MonitorLocal::endGroupPut dataChanged " << dataChanged << endl;
|
||||||
}
|
}
|
||||||
if(state!=active) return;
|
if(state!=active) return;
|
||||||
{
|
{
|
||||||
@@ -371,7 +374,7 @@ void MonitorLocal::unlisten(PVRecordPtr const & pvRecord)
|
|||||||
{
|
{
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "PVCopyMonitor::unlisten\n";
|
cout << "MonitorLocal::unlisten\n";
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
Lock xx(mutex);
|
Lock xx(mutex);
|
||||||
@@ -381,7 +384,7 @@ void MonitorLocal::unlisten(PVRecordPtr const & pvRecord)
|
|||||||
if(requester) {
|
if(requester) {
|
||||||
if(pvRecord->getTraceLevel()>1)
|
if(pvRecord->getTraceLevel()>1)
|
||||||
{
|
{
|
||||||
cout << "PVCopyMonitor::unlisten calling requester->unlisten\n";
|
cout << "MonitorLocal::unlisten calling requester->unlisten\n";
|
||||||
}
|
}
|
||||||
requester->unlisten(getPtrSelf());
|
requester->unlisten(getPtrSelf());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,30 +11,19 @@
|
|||||||
|
|
||||||
/* Author: Marty Kraimer */
|
/* Author: Marty Kraimer */
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cstddef>
|
|
||||||
#include <string>
|
|
||||||
#include <cstdio>
|
|
||||||
#include <memory>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <cantProceed.h>
|
|
||||||
#include <epicsStdio.h>
|
|
||||||
#include <epicsMutex.h>
|
|
||||||
#include <epicsEvent.h>
|
|
||||||
#include <epicsThread.h>
|
|
||||||
#include <iocsh.h>
|
#include <iocsh.h>
|
||||||
#include <shareLib.h>
|
|
||||||
#include <epicsExit.h>
|
|
||||||
|
|
||||||
#include <pv/pvAccess.h>
|
#include <pv/pvAccess.h>
|
||||||
#include <pv/serverContext.h>
|
#include <pv/serverContext.h>
|
||||||
|
#include <pv/syncChannelFind.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/timeStamp.h>
|
||||||
|
|
||||||
// this declared epicsExportSharedSymbols
|
// The following must be the last include for code pvDatabase uses
|
||||||
#include <epicsExport.h>
|
#include <epicsExport.h>
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
#include <pv/channelProviderLocal.h>
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/channelProviderLocal.h"
|
||||||
|
|
||||||
using std::cout;
|
using std::cout;
|
||||||
using std::endl;
|
using std::endl;
|
||||||
|
|||||||
@@ -4,3 +4,15 @@ SRC_DIRS += $(PVDATABASE_SRC)/special
|
|||||||
|
|
||||||
LIBSRCS += traceRecord.cpp
|
LIBSRCS += traceRecord.cpp
|
||||||
LIBSRCS += removeRecord.cpp
|
LIBSRCS += removeRecord.cpp
|
||||||
|
LIBSRCS += addRecord.cpp
|
||||||
|
LIBSRCS += processRecord.cpp
|
||||||
|
|
||||||
|
DBD += traceRecordRegister.dbd
|
||||||
|
DBD += removeRecordRegister.dbd
|
||||||
|
DBD += addRecordRegister.dbd
|
||||||
|
DBD += processRecordRegister.dbd
|
||||||
|
|
||||||
|
LIBSRCS += traceRecordRegister.cpp
|
||||||
|
LIBSRCS += removeRecordRegister.cpp
|
||||||
|
LIBSRCS += addRecordRegister.cpp
|
||||||
|
LIBSRCS += processRecordRegister.cpp
|
||||||
|
|||||||
117
src/special/addRecord.cpp
Normal file
117
src/special/addRecord.cpp
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
/* addRecord.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.04.18
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <pv/lock.h>
|
||||||
|
#include <pv/pvType.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/standardField.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/timeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/status.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/addRecord.h"
|
||||||
|
|
||||||
|
using std::tr1::static_pointer_cast;
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
AddRecordPtr AddRecord::create(
|
||||||
|
std::string const & recordName)
|
||||||
|
{
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
|
addNestedStructure("argument")->
|
||||||
|
add("recordName",pvString)->
|
||||||
|
addNestedUnion("union") ->
|
||||||
|
endNested()->
|
||||||
|
endNested()->
|
||||||
|
addNestedStructure("result") ->
|
||||||
|
add("status",pvString) ->
|
||||||
|
endNested()->
|
||||||
|
createStructure();
|
||||||
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
|
AddRecordPtr pvRecord(
|
||||||
|
new AddRecord(recordName,pvStructure));
|
||||||
|
if(!pvRecord->init()) pvRecord.reset();
|
||||||
|
return pvRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddRecord::AddRecord(
|
||||||
|
std::string const & recordName,
|
||||||
|
epics::pvData::PVStructurePtr const & pvStructure)
|
||||||
|
: PVRecord(recordName,pvStructure)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AddRecord::init()
|
||||||
|
{
|
||||||
|
initPVRecord();
|
||||||
|
PVStructurePtr pvStructure = getPVStructure();
|
||||||
|
pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
|
||||||
|
if(!pvRecordName) return false;
|
||||||
|
pvResult = pvStructure->getSubField<PVString>("result.status");
|
||||||
|
if(!pvResult) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddRecord::process()
|
||||||
|
{
|
||||||
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
|
string name = pvRecordName->get();
|
||||||
|
PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name);
|
||||||
|
if(pvRecord) {
|
||||||
|
pvResult->put(name + " already exists");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PVUnionPtr pvUnion = getPVStructure()->getSubField<PVUnion>("argument.union");
|
||||||
|
if(!pvUnion) {
|
||||||
|
pvResult->put(name + " argument.union is NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PVFieldPtr pvField(pvUnion->get());
|
||||||
|
if(!pvField) {
|
||||||
|
pvResult->put(name + " union has no value");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(pvField->getField()->getType()!=epics::pvData::structure) {
|
||||||
|
pvResult->put(name + " union most be a structure");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
StructureConstPtr st = static_pointer_cast<const Structure>(pvField->getField());
|
||||||
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(st);
|
||||||
|
PVRecordPtr pvRec = PVRecord::create(name,pvStructure);
|
||||||
|
bool result = PVDatabase::getMaster()->addRecord(pvRec);
|
||||||
|
if(result) {
|
||||||
|
pvResult->put("success");
|
||||||
|
} else {
|
||||||
|
pvResult->put("failure");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
62
src/special/addRecordRegister.cpp
Normal file
62
src/special/addRecordRegister.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright information and license terms for this software can be
|
||||||
|
* found in the file LICENSE that is included with the distribution
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mrk
|
||||||
|
* @date 2013.07.24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Author: Marty Kraimer */
|
||||||
|
#include <epicsThread.h>
|
||||||
|
#include <iocsh.h>
|
||||||
|
#include <pv/event.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
|
||||||
|
// The following must be the last include for code pvDatabase uses
|
||||||
|
#include <epicsExport.h>
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/addRecord.h"
|
||||||
|
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace epics::pvDatabase;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static const iocshArg testArg0 = { "recordName", iocshArgString };
|
||||||
|
static const iocshArg *testArgs[] = {
|
||||||
|
&testArg0};
|
||||||
|
|
||||||
|
static const iocshFuncDef addRecordFuncDef = {"addRecordCreate", 1,testArgs};
|
||||||
|
|
||||||
|
static void addRecordCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
char *recordName = args[0].sval;
|
||||||
|
if(!recordName) {
|
||||||
|
throw std::runtime_error("addRecordCreate invalid number of arguments");
|
||||||
|
}
|
||||||
|
AddRecordPtr record = AddRecord::create(recordName);
|
||||||
|
bool result = PVDatabase::getMaster()->addRecord(record);
|
||||||
|
if(!result) cout << "recordname" << " not added" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addRecordRegister(void)
|
||||||
|
{
|
||||||
|
static int firstTime = 1;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = 0;
|
||||||
|
iocshRegister(&addRecordFuncDef, addRecordCallFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
epicsExportRegistrar(addRecordRegister);
|
||||||
|
}
|
||||||
1
src/special/addRecordRegister.dbd
Normal file
1
src/special/addRecordRegister.dbd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
registrar("addRecordRegister")
|
||||||
166
src/special/processRecord.cpp
Normal file
166
src/special/processRecord.cpp
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/* processRecord.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.04.18
|
||||||
|
*/
|
||||||
|
#include <map>
|
||||||
|
#include <epicsThread.h>
|
||||||
|
#include <pv/event.h>
|
||||||
|
#include <shareLib.h>
|
||||||
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <pv/lock.h>
|
||||||
|
#include <pv/pvType.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/timeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/status.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/processRecord.h"
|
||||||
|
|
||||||
|
using std::tr1::static_pointer_cast;
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
ProcessRecordPtr ProcessRecord::create(
|
||||||
|
std::string const & recordName,double delay)
|
||||||
|
{
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
|
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||||
|
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||||
|
addNestedStructure("argument")->
|
||||||
|
add("command",pvString)->
|
||||||
|
add("recordName",pvString)->
|
||||||
|
endNested()->
|
||||||
|
addNestedStructure("result") ->
|
||||||
|
add("status",pvString) ->
|
||||||
|
endNested()->
|
||||||
|
createStructure();
|
||||||
|
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||||
|
ProcessRecordPtr pvRecord(
|
||||||
|
new ProcessRecord(recordName,pvStructure,delay));
|
||||||
|
if(!pvRecord->init()) pvRecord.reset();
|
||||||
|
return pvRecord;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRecord::startThread()
|
||||||
|
{
|
||||||
|
thread = EpicsThreadPtr(new epicsThread(
|
||||||
|
*this,
|
||||||
|
"processRecord",
|
||||||
|
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||||
|
epicsThreadPriorityLow));
|
||||||
|
thread->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRecord::stop()
|
||||||
|
{
|
||||||
|
runStop.signal();
|
||||||
|
runReturn.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ProcessRecord::ProcessRecord(
|
||||||
|
std::string const & recordName,
|
||||||
|
epics::pvData::PVStructurePtr const & pvStructure,double delay)
|
||||||
|
: PVRecord(recordName,pvStructure),
|
||||||
|
delay(delay),
|
||||||
|
pvDatabase(PVDatabase::getMaster())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessRecord::init()
|
||||||
|
{
|
||||||
|
initPVRecord();
|
||||||
|
PVStructurePtr pvStructure = getPVStructure();
|
||||||
|
pvCommand = pvStructure->getSubField<PVString>("argument.command");
|
||||||
|
pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
|
||||||
|
if(!pvRecordName) return false;
|
||||||
|
pvResult = pvStructure->getSubField<PVString>("result.status");
|
||||||
|
if(!pvResult) return false;
|
||||||
|
startThread();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRecord::process()
|
||||||
|
{
|
||||||
|
string recordName = pvRecordName->get();
|
||||||
|
string command = pvCommand->get();
|
||||||
|
if(command.compare("add")==0) {
|
||||||
|
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||||
|
std::map<std::string,PVRecordPtr>::iterator iter = pvRecordMap.find(recordName);
|
||||||
|
if(iter!=pvRecordMap.end()) {
|
||||||
|
pvResult->put(recordName + " already present");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PVRecordPtr pvRecord = pvDatabase->findRecord(recordName);
|
||||||
|
if(!pvRecord) {
|
||||||
|
pvResult->put(recordName + " not in pvDatabase");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pvRecordMap.insert(PVRecordMap::value_type(recordName,pvRecord));
|
||||||
|
pvResult->put("success");
|
||||||
|
return;
|
||||||
|
} else if(command.compare("remove")==0) {
|
||||||
|
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||||
|
std::map<std::string,PVRecordPtr>::iterator iter = pvRecordMap.find(recordName);
|
||||||
|
if(iter==pvRecordMap.end()) {
|
||||||
|
pvResult->put(recordName + " not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
pvRecordMap.erase(iter);
|
||||||
|
pvResult->put("success");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
pvResult->put(command + " not a valid command: only add and remove are valid");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessRecord::run()
|
||||||
|
{
|
||||||
|
while(true) {
|
||||||
|
if(runStop.tryWait()) {
|
||||||
|
runReturn.signal();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(delay>0.0) epicsThreadSleep(delay);
|
||||||
|
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||||
|
PVRecordMap::iterator iter;
|
||||||
|
for(iter = pvRecordMap.begin(); iter!=pvRecordMap.end(); ++iter) {
|
||||||
|
PVRecordPtr pvRecord = (*iter).second;
|
||||||
|
pvRecord->lock();
|
||||||
|
pvRecord->beginGroupPut();
|
||||||
|
try {
|
||||||
|
pvRecord->process();
|
||||||
|
} catch (std::exception& ex) {
|
||||||
|
std::cout << "record " << pvRecord->getRecordName() << "exception " << ex.what() << "\n";
|
||||||
|
} catch (...) {
|
||||||
|
std::cout<< "record " << pvRecord->getRecordName() << " process exception\n";
|
||||||
|
}
|
||||||
|
pvRecord->endGroupPut();
|
||||||
|
pvRecord->unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
67
src/special/processRecordRegister.cpp
Normal file
67
src/special/processRecordRegister.cpp
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright information and license terms for this software can be
|
||||||
|
* found in the file LICENSE that is included with the distribution
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mrk
|
||||||
|
* @date 2013.07.24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Author: Marty Kraimer */
|
||||||
|
|
||||||
|
#include <epicsThread.h>
|
||||||
|
#include <iocsh.h>
|
||||||
|
#include <pv/event.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
|
||||||
|
// The following must be the last include for code pvDatabase uses
|
||||||
|
#include <epicsExport.h>
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/processRecord.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace epics::pvDatabase;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static const iocshArg testArg0 = { "recordName", iocshArgString };
|
||||||
|
static const iocshArg testArg1 = { "delay", iocshArgDouble };
|
||||||
|
static const iocshArg *testArgs[] = {
|
||||||
|
&testArg0,&testArg1};
|
||||||
|
|
||||||
|
static const iocshFuncDef processRecordFuncDef = {"processRecordCreate", 2,testArgs};
|
||||||
|
|
||||||
|
static void processRecordCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
char *recordName = args[0].sval;
|
||||||
|
if(!recordName) {
|
||||||
|
throw std::runtime_error("processRecordCreate invalid number of arguments");
|
||||||
|
}
|
||||||
|
double delay = args[1].dval;
|
||||||
|
if(delay<0.0) delay = 1.0;
|
||||||
|
ProcessRecordPtr record = ProcessRecord::create(recordName,delay);
|
||||||
|
bool result = PVDatabase::getMaster()->addRecord(record);
|
||||||
|
if(!result) cout << "recordname" << " not added" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processRecordRegister(void)
|
||||||
|
{
|
||||||
|
static int firstTime = 1;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = 0;
|
||||||
|
iocshRegister(&processRecordFuncDef, processRecordCallFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
epicsExportRegistrar(processRecordRegister);
|
||||||
|
}
|
||||||
1
src/special/processRecordRegister.dbd
Normal file
1
src/special/processRecordRegister.dbd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
registrar("processRecordRegister")
|
||||||
@@ -8,9 +8,28 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2013.04.18
|
* @date 2013.04.18
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <pv/removeRecord.h>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <pv/lock.h>
|
||||||
|
#include <pv/pvType.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/timeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/status.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/removeRecord.h"
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -65,10 +84,9 @@ void RemoveRecord::process()
|
|||||||
pvResult->put(name + " not found");
|
pvResult->put(name + " not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pvRecord->destroy();
|
pvRecord->remove();
|
||||||
pvResult->put("success");
|
pvResult->put("success");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
62
src/special/removeRecordRegister.cpp
Normal file
62
src/special/removeRecordRegister.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright information and license terms for this software can be
|
||||||
|
* found in the file LICENSE that is included with the distribution
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mrk
|
||||||
|
* @date 2013.07.24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Author: Marty Kraimer */
|
||||||
|
#include <epicsThread.h>
|
||||||
|
#include <iocsh.h>
|
||||||
|
#include <pv/event.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
|
||||||
|
// The following must be the last include for code pvDatabase uses
|
||||||
|
#include <epicsExport.h>
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/removeRecord.h"
|
||||||
|
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace epics::pvDatabase;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static const iocshArg testArg0 = { "recordName", iocshArgString };
|
||||||
|
static const iocshArg *testArgs[] = {
|
||||||
|
&testArg0};
|
||||||
|
|
||||||
|
static const iocshFuncDef removeRecordFuncDef = {"removeRecordCreate", 1,testArgs};
|
||||||
|
|
||||||
|
static void removeRecordCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
char *recordName = args[0].sval;
|
||||||
|
if(!recordName) {
|
||||||
|
throw std::runtime_error("removeRecordCreate invalid number of arguments");
|
||||||
|
}
|
||||||
|
RemoveRecordPtr record = RemoveRecord::create(recordName);
|
||||||
|
bool result = PVDatabase::getMaster()->addRecord(record);
|
||||||
|
if(!result) cout << "recordname" << " not added" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void removeRecordRegister(void)
|
||||||
|
{
|
||||||
|
static int firstTime = 1;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = 0;
|
||||||
|
iocshRegister(&removeRecordFuncDef, removeRecordCallFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
epicsExportRegistrar(removeRecordRegister);
|
||||||
|
}
|
||||||
1
src/special/removeRecordRegister.dbd
Normal file
1
src/special/removeRecordRegister.dbd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
registrar("removeRecordRegister")
|
||||||
@@ -8,9 +8,27 @@
|
|||||||
* @author mrk
|
* @author mrk
|
||||||
* @date 2013.04.18
|
* @date 2013.04.18
|
||||||
*/
|
*/
|
||||||
#define epicsExportSharedSymbols
|
|
||||||
|
|
||||||
#include <pv/traceRecord.h>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <memory>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <pv/lock.h>
|
||||||
|
#include <pv/pvType.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/timeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/status.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/channelProviderLocal.h"
|
||||||
|
#include "pv/traceRecord.h"
|
||||||
|
|
||||||
using std::tr1::static_pointer_cast;
|
using std::tr1::static_pointer_cast;
|
||||||
using namespace epics::pvData;
|
using namespace epics::pvData;
|
||||||
@@ -75,4 +93,3 @@ void TraceRecord::process()
|
|||||||
|
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
|
|||||||
63
src/special/traceRecordRegister.cpp
Normal file
63
src/special/traceRecordRegister.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright information and license terms for this software can be
|
||||||
|
* found in the file LICENSE that is included with the distribution
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author mrk
|
||||||
|
* @date 2013.07.24
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Author: Marty Kraimer */
|
||||||
|
|
||||||
|
#include <epicsThread.h>
|
||||||
|
#include <iocsh.h>
|
||||||
|
#include <pv/event.h>
|
||||||
|
#include <pv/pvAccess.h>
|
||||||
|
#include <pv/serverContext.h>
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
|
||||||
|
// The following must be the last include for code pvDatabase uses
|
||||||
|
#include <epicsExport.h>
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/traceRecord.h"
|
||||||
|
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace epics::pvDatabase;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
static const iocshArg testArg0 = { "recordName", iocshArgString };
|
||||||
|
static const iocshArg *testArgs[] = {
|
||||||
|
&testArg0};
|
||||||
|
|
||||||
|
static const iocshFuncDef traceRecordFuncDef = {"traceRecordCreate", 1,testArgs};
|
||||||
|
|
||||||
|
static void traceRecordCallFunc(const iocshArgBuf *args)
|
||||||
|
{
|
||||||
|
char *recordName = args[0].sval;
|
||||||
|
if(!recordName) {
|
||||||
|
throw std::runtime_error("traceRecordCreate invalid number of arguments");
|
||||||
|
}
|
||||||
|
TraceRecordPtr record = TraceRecord::create(recordName);
|
||||||
|
bool result = PVDatabase::getMaster()->addRecord(record);
|
||||||
|
if(!result) cout << "recordname" << " not added" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void traceRecordRegister(void)
|
||||||
|
{
|
||||||
|
static int firstTime = 1;
|
||||||
|
if (firstTime) {
|
||||||
|
firstTime = 0;
|
||||||
|
iocshRegister(&traceRecordFuncDef, traceRecordCallFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
epicsExportRegistrar(traceRecordRegister);
|
||||||
|
}
|
||||||
1
src/special/traceRecordRegister.dbd
Normal file
1
src/special/traceRecordRegister.dbd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
registrar("traceRecordRegister")
|
||||||
6
src/support/Makefile
Normal file
6
src/support/Makefile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# This is a Makefile fragment, see ../Makefile
|
||||||
|
|
||||||
|
SRC_DIRS += $(PVDATABASE_SRC)/support
|
||||||
|
|
||||||
|
LIBSRCS += controlSupport.cpp
|
||||||
|
LIBSRCS += scalarAlarmSupport.cpp
|
||||||
137
src/support/controlSupport.cpp
Normal file
137
src/support/controlSupport.cpp
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
/* controlSupport.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 2019.06.01
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <pv/pvData.h>
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/convert.h>
|
||||||
|
#include <pv/standardField.h>
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include <pv/pvSupport.h>
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/controlSupport.h"
|
||||||
|
|
||||||
|
using std::tr1::static_pointer_cast;
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
ControlSupport::~ControlSupport()
|
||||||
|
{
|
||||||
|
//cout << "ControlSupport::~ControlSupport()\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
epics::pvData::StructureConstPtr ControlSupport::controlField(ScalarType scalarType)
|
||||||
|
{
|
||||||
|
return FieldBuilder::begin()
|
||||||
|
->setId("control_t")
|
||||||
|
->add("limitLow", pvDouble)
|
||||||
|
->add("limitHigh", pvDouble)
|
||||||
|
->add("minStep", pvDouble)
|
||||||
|
->add("outputValue", scalarType)
|
||||||
|
->createStructure();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ControlSupportPtr ControlSupport::create(PVRecordPtr const & pvRecord)
|
||||||
|
{
|
||||||
|
ControlSupportPtr support(new ControlSupport(pvRecord));
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
ControlSupport::ControlSupport(PVRecordPtr const & pvRecord)
|
||||||
|
: pvRecord(pvRecord)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool ControlSupport::init(PVFieldPtr const & pv,PVFieldPtr const & pvsup)
|
||||||
|
{
|
||||||
|
if(pv) {
|
||||||
|
if(pv->getField()->getType()==epics::pvData::scalar) {
|
||||||
|
ScalarConstPtr s = static_pointer_cast<const Scalar>(pv->getField());
|
||||||
|
if(ScalarTypeFunc::isNumeric(s->getScalarType())) {
|
||||||
|
pvValue = static_pointer_cast<PVScalar>(pv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!pvValue) {
|
||||||
|
cout << "ControlSupport for record " << pvRecord->getRecordName()
|
||||||
|
<< " failed because not numeric scalar\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pvControl = static_pointer_cast<PVStructure>(pvsup);
|
||||||
|
if(pvControl) {
|
||||||
|
pvLimitLow = pvControl->getSubField<PVDouble>("limitLow");
|
||||||
|
pvLimitHigh = pvControl->getSubField<PVDouble>("limitHigh");
|
||||||
|
pvMinStep = pvControl->getSubField<PVDouble>("minStep");
|
||||||
|
pvOutputValue = pvControl->getSubField<PVScalar>("outputValue");
|
||||||
|
}
|
||||||
|
if(!pvControl || !pvLimitLow || !pvLimitHigh || !pvMinStep || !pvOutputValue) {
|
||||||
|
cout << "ControlSupport for record " << pvRecord->getRecordName()
|
||||||
|
<< " failed because pvSupport not a valid control structure\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ConvertPtr convert = getConvert();
|
||||||
|
currentValue = convert->toDouble(pvValue);
|
||||||
|
isMinStep = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ControlSupport::process()
|
||||||
|
{
|
||||||
|
ConvertPtr convert = getConvert();
|
||||||
|
double value = convert->toDouble(pvValue);
|
||||||
|
if(!isMinStep && value==currentValue) return false;
|
||||||
|
double limitLow = pvLimitLow->get();
|
||||||
|
double limitHigh = pvLimitHigh->get();
|
||||||
|
double minStep = pvMinStep->get();
|
||||||
|
bool setValue = false;
|
||||||
|
if(limitHigh>limitLow) {
|
||||||
|
if(value>limitHigh) {value = limitHigh;setValue=true;}
|
||||||
|
if(value<limitLow) {value = limitLow;setValue=true;}
|
||||||
|
}
|
||||||
|
if(setValue) convert->fromDouble(pvValue,value);
|
||||||
|
double diff = value - currentValue;
|
||||||
|
double outputValue = value;
|
||||||
|
if(minStep>0.0) {
|
||||||
|
if(diff<0.0) {
|
||||||
|
outputValue = currentValue - minStep;
|
||||||
|
if(limitHigh>limitLow && outputValue<=limitLow) outputValue = limitLow;
|
||||||
|
isMinStep = true;
|
||||||
|
if(outputValue<value) {
|
||||||
|
outputValue = value;
|
||||||
|
isMinStep = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
outputValue = currentValue + minStep;
|
||||||
|
if(limitHigh>limitLow && outputValue>=limitHigh) outputValue = limitHigh;
|
||||||
|
isMinStep = true;
|
||||||
|
if(outputValue>value) {
|
||||||
|
outputValue = value;
|
||||||
|
isMinStep = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(outputValue==currentValue) return false;
|
||||||
|
currentValue = outputValue;
|
||||||
|
convert->fromDouble(pvOutputValue,outputValue);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ControlSupport::reset()
|
||||||
|
{
|
||||||
|
isMinStep = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
218
src/support/scalarAlarmSupport.cpp
Normal file
218
src/support/scalarAlarmSupport.cpp
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/* scalarAlarmSupport.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 2019.06.01
|
||||||
|
*/
|
||||||
|
#include <pv/pvTimeStamp.h>
|
||||||
|
#include <pv/rpcService.h>
|
||||||
|
#include <pv/convert.h>
|
||||||
|
#include <pv/standardField.h>
|
||||||
|
#include <pv/alarm.h>
|
||||||
|
#include <pv/pvAlarm.h>
|
||||||
|
|
||||||
|
#define epicsExportSharedSymbols
|
||||||
|
#include "pv/pvStructureCopy.h"
|
||||||
|
#include "pv/pvSupport.h"
|
||||||
|
#include "pv/pvDatabase.h"
|
||||||
|
#include "pv/scalarAlarmSupport.h"
|
||||||
|
|
||||||
|
using std::tr1::static_pointer_cast;
|
||||||
|
using namespace epics::pvData;
|
||||||
|
using namespace epics::pvAccess;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace epics { namespace pvDatabase {
|
||||||
|
|
||||||
|
ScalarAlarmSupport::~ScalarAlarmSupport()
|
||||||
|
{
|
||||||
|
//cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
epics::pvData::StructureConstPtr ScalarAlarmSupport::scalarAlarmField()
|
||||||
|
{
|
||||||
|
return FieldBuilder::begin()
|
||||||
|
->setId("scalarAlarm_t")
|
||||||
|
->add("lowAlarmLimit", pvDouble)
|
||||||
|
->add("lowWarningLimit", pvDouble)
|
||||||
|
->add("highWarningLimit", pvDouble)
|
||||||
|
->add("highAlarmLimit", pvDouble)
|
||||||
|
->add("hysteresis", pvDouble)
|
||||||
|
->createStructure();
|
||||||
|
}
|
||||||
|
|
||||||
|
ScalarAlarmSupportPtr ScalarAlarmSupport::create(PVRecordPtr const & pvRecord)
|
||||||
|
{
|
||||||
|
ScalarAlarmSupportPtr support(new ScalarAlarmSupport(pvRecord));
|
||||||
|
return support;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScalarAlarmSupport::ScalarAlarmSupport(PVRecordPtr const & pvRecord)
|
||||||
|
: pvRecord(pvRecord),
|
||||||
|
prevAlarmRange(range_Undefined)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
bool ScalarAlarmSupport::init(
|
||||||
|
PVFieldPtr const & pvval,
|
||||||
|
PVStructurePtr const & pvalarm,
|
||||||
|
PVFieldPtr const & pvsup)
|
||||||
|
{
|
||||||
|
if(pvval->getField()->getType()==epics::pvData::scalar) {
|
||||||
|
ScalarConstPtr s = static_pointer_cast<const Scalar>(pvval->getField());
|
||||||
|
if(ScalarTypeFunc::isNumeric(s->getScalarType())) {
|
||||||
|
pvValue = static_pointer_cast<PVScalar>(pvval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!pvValue) {
|
||||||
|
cout << "ScalarAlarmSupport for record " << pvRecord->getRecordName()
|
||||||
|
<< " failed because not numeric scalar\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pvScalarAlarm = static_pointer_cast<PVStructure>(pvsup);
|
||||||
|
if(pvScalarAlarm) {
|
||||||
|
pvLowAlarmLimit = pvScalarAlarm->getSubField<PVDouble>("lowAlarmLimit");
|
||||||
|
pvLowWarningLimit = pvScalarAlarm->getSubField<PVDouble>("lowWarningLimit");
|
||||||
|
pvHighWarningLimit = pvScalarAlarm->getSubField<PVDouble>("highWarningLimit");
|
||||||
|
pvHighAlarmLimit = pvScalarAlarm->getSubField<PVDouble>("highAlarmLimit");
|
||||||
|
pvHysteresis = pvScalarAlarm->getSubField<PVDouble>("hysteresis");
|
||||||
|
}
|
||||||
|
if(!pvScalarAlarm
|
||||||
|
|| !pvLowAlarmLimit || !pvLowWarningLimit
|
||||||
|
|| !pvLowWarningLimit || !pvHighAlarmLimit
|
||||||
|
|| !pvHysteresis)
|
||||||
|
{
|
||||||
|
cout << "ScalarAlarmSupport for record " << pvRecord->getRecordName()
|
||||||
|
<< " failed because pvSupport not a valid scalarAlarm structure\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pvAlarm = pvalarm;
|
||||||
|
ConvertPtr convert = getConvert();
|
||||||
|
requestedValue = convert->toDouble(pvValue);
|
||||||
|
currentValue = requestedValue;
|
||||||
|
isHystersis = false;
|
||||||
|
setAlarm(pvAlarm,range_Undefined);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ScalarAlarmSupport::process()
|
||||||
|
{
|
||||||
|
ConvertPtr convert = getConvert();
|
||||||
|
double value = convert->toDouble(pvValue);
|
||||||
|
double lowAlarmLimit = pvLowAlarmLimit->get();
|
||||||
|
double lowWarningLimit = pvLowWarningLimit->get();
|
||||||
|
double highWarningLimit = pvHighWarningLimit->get();
|
||||||
|
double highAlarmLimit = pvHighAlarmLimit->get();
|
||||||
|
double hysteresis = pvHysteresis->get();
|
||||||
|
int alarmRange = range_Normal;
|
||||||
|
if(highAlarmLimit>lowAlarmLimit) {
|
||||||
|
if(value>=highAlarmLimit
|
||||||
|
||(prevAlarmRange==range_Hihi && value>=highAlarmLimit-hysteresis)) {
|
||||||
|
alarmRange = range_Hihi;
|
||||||
|
} else if(value<=lowAlarmLimit
|
||||||
|
||(prevAlarmRange==range_Lolo && value<=lowAlarmLimit+hysteresis)) {
|
||||||
|
alarmRange = range_Lolo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(alarmRange==range_Normal && (highWarningLimit>lowWarningLimit)) {
|
||||||
|
if(value>=highWarningLimit
|
||||||
|
||(prevAlarmRange==range_High && value>=highWarningLimit-hysteresis)) {
|
||||||
|
alarmRange = range_High;
|
||||||
|
} else if(value<=lowWarningLimit
|
||||||
|
||(prevAlarmRange==range_Low && value<=lowWarningLimit+hysteresis)) {
|
||||||
|
alarmRange = range_Low;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool retValue = false;
|
||||||
|
if(alarmRange!=prevAlarmRange) {
|
||||||
|
setAlarm(pvAlarm,alarmRange);
|
||||||
|
retValue = true;
|
||||||
|
}
|
||||||
|
prevAlarmRange = alarmRange;
|
||||||
|
currentValue = value;
|
||||||
|
return retValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScalarAlarmSupport::reset()
|
||||||
|
{
|
||||||
|
isHystersis = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScalarAlarmSupport::setAlarm(
|
||||||
|
epics::pvData::PVStructurePtr const & pva,
|
||||||
|
int alarmRange)
|
||||||
|
{
|
||||||
|
Alarm alarm;
|
||||||
|
PVAlarm pvAlarm;
|
||||||
|
if(!pvAlarm.attach(pva)) throw std::logic_error("bad alarm field");
|
||||||
|
epics::pvData::AlarmStatus status(epics::pvData::noStatus);
|
||||||
|
epics::pvData::AlarmSeverity severity(epics::pvData::noAlarm);
|
||||||
|
string message;
|
||||||
|
switch (alarmRange) {
|
||||||
|
case range_Lolo :
|
||||||
|
{
|
||||||
|
severity = epics::pvData::majorAlarm;
|
||||||
|
status = epics::pvData::recordStatus;
|
||||||
|
message = "major low alarm";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case range_Low :
|
||||||
|
{
|
||||||
|
severity = epics::pvData::minorAlarm;
|
||||||
|
status = epics::pvData::recordStatus;
|
||||||
|
message = "minor low alarm";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case range_Normal :
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case range_High :
|
||||||
|
{
|
||||||
|
severity = epics::pvData::minorAlarm;
|
||||||
|
status = epics::pvData::recordStatus;
|
||||||
|
message = "minor high alarm";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case range_Hihi :
|
||||||
|
{
|
||||||
|
severity = epics::pvData::majorAlarm;
|
||||||
|
status = epics::pvData::recordStatus;
|
||||||
|
message = "major high alarm";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case range_Invalid :
|
||||||
|
{
|
||||||
|
severity = epics::pvData::invalidAlarm;
|
||||||
|
status = epics::pvData::recordStatus;
|
||||||
|
message = "invalid alarm";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case range_Undefined :
|
||||||
|
{
|
||||||
|
severity = epics::pvData::undefinedAlarm;
|
||||||
|
status = epics::pvData::recordStatus;
|
||||||
|
message = "undefined alarm";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
severity = epics::pvData::undefinedAlarm;
|
||||||
|
status = epics::pvData::recordStatus;
|
||||||
|
message = "bad alarm definition";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alarm.setStatus(status);
|
||||||
|
alarm.setSeverity(severity);
|
||||||
|
alarm.setMessage(message);
|
||||||
|
pvAlarm.set(alarm);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}}
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#ifdef listenerEpicsExportSharedSymbols
|
#ifdef listenerEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef listenerEpicsExportSharedSymbols
|
# undef listenerEpicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#ifdef powerSupplyEpicsExportSharedSymbols
|
#ifdef powerSupplyEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef powerSupplyEpicsExportSharedSymbols
|
# undef powerSupplyEpicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
#ifdef pvRecordClientEpicsExportSharedSymbols
|
#ifdef pvRecordClientEpicsExportSharedSymbols
|
||||||
# define epicsExportSharedSymbols
|
# define epicsExportSharedSymbols
|
||||||
# undef pvRecordClientEpicsExportSharedSymbols
|
# undef pvRecordClientEpicsExportSharedSymbols
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <shareLib.h>
|
#include <shareLib.h>
|
||||||
|
|||||||
@@ -134,4 +134,3 @@ MAIN(testExampleRecord)
|
|||||||
test();
|
test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,4 +79,3 @@ MAIN(testLocalProvider)
|
|||||||
test();
|
test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -75,4 +75,3 @@ MAIN(testPVAServer)
|
|||||||
test();
|
test();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -401,4 +401,3 @@ MAIN(testPVCopy)
|
|||||||
powerSupplyTest();
|
powerSupplyTest();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -103,4 +103,3 @@ MAIN(testPVRecord)
|
|||||||
powerSupplyTest();
|
powerSupplyTest();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -145,6 +145,73 @@ static void arrayTest()
|
|||||||
testOk1(nset==1);
|
testOk1(nset==1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void unionArrayTest()
|
||||||
|
{
|
||||||
|
if(debug) {cout << endl << endl << "****unionArrayTest****" << endl;}
|
||||||
|
bool result = false;
|
||||||
|
uint32 nset = 0;
|
||||||
|
size_t n = 10;
|
||||||
|
shared_vector<double> values(n);
|
||||||
|
for(size_t i=0; i<n; i++) values[i] = i + .06;
|
||||||
|
PVDoubleArrayPtr pvDoubleArray =
|
||||||
|
static_pointer_cast<PVDoubleArray>(PVDataCreate::getPVDataCreate()->createPVScalarArray(pvDouble));
|
||||||
|
const shared_vector<const double> yyy(freeze(values));
|
||||||
|
pvDoubleArray->putFrom(yyy);
|
||||||
|
|
||||||
|
StandardFieldPtr standardField = getStandardField();
|
||||||
|
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||||
|
StructureConstPtr top = fieldCreate->createFieldBuilder()->
|
||||||
|
add("value",fieldCreate->createVariantUnion()) ->
|
||||||
|
add("timeStamp", standardField->timeStamp()) ->
|
||||||
|
addNestedStructure("subfield") ->
|
||||||
|
add("value",fieldCreate->createVariantUnion()) ->
|
||||||
|
endNested()->
|
||||||
|
createStructure();
|
||||||
|
PVStructurePtr pvRecordStructure(PVDataCreate::getPVDataCreate()->createPVStructure(top));
|
||||||
|
PVRecordPtr pvRecord(PVRecord::create("unionArrayRecord",pvRecordStructure));
|
||||||
|
PVUnionPtr pvUnion = pvRecord->getPVStructure()->getSubField<PVUnion>("value");
|
||||||
|
pvUnion->set(pvDoubleArray);
|
||||||
|
pvUnion = pvRecord->getPVStructure()->getSubField<PVUnion>("subfield.value");
|
||||||
|
pvUnion->set(pvDoubleArray);
|
||||||
|
if(debug) { cout << "initial\n" << pvRecordStructure << "\n";}
|
||||||
|
|
||||||
|
PVStructurePtr pvRequest(CreateRequest::create()->createRequest("value[array=1:3]"));
|
||||||
|
PVCopyPtr pvCopy(PVCopy::create(pvRecordStructure,pvRequest,""));
|
||||||
|
PVStructurePtr pvStructureCopy(pvCopy->createPVStructure());
|
||||||
|
BitSetPtr bitSet(new BitSet(pvStructureCopy->getNumberFields()));
|
||||||
|
PVDoubleArrayPtr pvValue(pvRecordStructure->getSubField<PVDoubleArray>("value"));
|
||||||
|
result = pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
|
||||||
|
nset = bitSet->cardinality();
|
||||||
|
if(debug) {
|
||||||
|
cout << "after get value"
|
||||||
|
<< " result " << (result ? "true" : "false")
|
||||||
|
<< " nset " << nset
|
||||||
|
<< " bitSet " << *bitSet
|
||||||
|
<< " pvStructureCopy\n" << pvStructureCopy
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
testOk1(result==true);
|
||||||
|
testOk1(nset==1);
|
||||||
|
|
||||||
|
pvRequest = CreateRequest::create()->createRequest("subfield.value[array=1:3]");
|
||||||
|
pvCopy = PVCopy::create(pvRecordStructure,pvRequest,"");
|
||||||
|
pvStructureCopy = pvCopy->createPVStructure();
|
||||||
|
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
|
||||||
|
pvValue = pvRecordStructure->getSubField<PVDoubleArray>("subfield.value");
|
||||||
|
result = pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
|
||||||
|
nset = bitSet->cardinality();
|
||||||
|
if(debug) {
|
||||||
|
cout << "after get subfield.value"
|
||||||
|
<< " result " << (result ? "true" : "false")
|
||||||
|
<< " nset " << nset
|
||||||
|
<< " bitSet " << *bitSet
|
||||||
|
<< " pvStructureCopy\n" << pvStructureCopy
|
||||||
|
<< "\n";
|
||||||
|
}
|
||||||
|
testOk1(result==true);
|
||||||
|
testOk1(nset==1);
|
||||||
|
}
|
||||||
|
|
||||||
static void timeStampTest()
|
static void timeStampTest()
|
||||||
{
|
{
|
||||||
if(debug) {cout << endl << endl << "****timeStampTest****" << endl;}
|
if(debug) {cout << endl << endl << "****timeStampTest****" << endl;}
|
||||||
@@ -267,12 +334,12 @@ static void ignoreTest()
|
|||||||
|
|
||||||
MAIN(testPlugin)
|
MAIN(testPlugin)
|
||||||
{
|
{
|
||||||
testPlan(22);
|
testPlan(26);
|
||||||
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
|
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
|
||||||
deadbandTest();
|
deadbandTest();
|
||||||
arrayTest();
|
arrayTest();
|
||||||
|
unionArrayTest();
|
||||||
timeStampTest();
|
timeStampTest();
|
||||||
ignoreTest();
|
ignoreTest();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user