Compare commits
126 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8cac3975cc | ||
|
|
219e5eaf94 | ||
|
|
f345651b67 | ||
|
|
4895107854 | ||
|
|
1c121b3f1e | ||
|
|
d493e52dda | ||
|
|
91d4d2a423 | ||
|
|
d54031a2fb | ||
|
|
1e1d5455a8 | ||
|
|
426af714a1 | ||
|
|
68bbb55370 | ||
|
|
716ec9857c | ||
|
|
e91b4b1b66 | ||
|
|
2c4e98db8c | ||
|
|
d4a13397d7 | ||
|
|
a622f66a94 | ||
|
|
81abd5f413 | ||
|
|
4df01038c3 | ||
|
|
e648cba659 | ||
|
|
42747b167c | ||
|
|
0a893a331b | ||
|
|
e95c959cfd | ||
|
|
e51c29d147 | ||
|
|
fec903fb06 | ||
|
|
ca066bc088 | ||
|
|
0481a7bf5b | ||
|
|
17f43b4452 | ||
|
|
a1514e5206 | ||
|
|
72c2489921 | ||
|
|
895698c3cd | ||
|
|
9d10b039fb | ||
|
|
bf82de407e | ||
|
|
58a603556b | ||
|
|
22e849c6f7 | ||
|
|
2a4d3a15f8 | ||
|
|
7143a8585f | ||
|
|
2d61b4c0f3 | ||
|
|
120fa22558 | ||
|
|
4ed8e6d625 | ||
|
|
4718021e39 | ||
|
|
b1822f5fbd | ||
|
|
333cd44da0 | ||
|
|
a514ab7b51 | ||
|
|
dafc37b585 | ||
|
|
2432f85784 | ||
|
|
bd1054f247 | ||
|
|
bc70b5f449 | ||
|
|
93a259cbde | ||
|
|
09423edeab | ||
|
|
ac1de6770e | ||
|
|
5427311390 | ||
|
|
b62b047f63 | ||
|
|
3bc89bfe0e | ||
|
|
cb5d9f976a | ||
|
|
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=3.16
|
||||
- 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
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_NUMBER = 4.6.0
|
||||
|
||||
# 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
|
||||
@@ -765,7 +765,7 @@ WARN_LOGFILE =
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# 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
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
@@ -1035,7 +1035,7 @@ GENERATE_HTML = YES
|
||||
# The default directory is: html.
|
||||
# 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
|
||||
# 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 = 6
|
||||
EPICS_PVDATABASE_MAINTENANCE_VERSION = 0
|
||||
|
||||
# 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
|
||||
|
||||
CFG += CONFIG_PVDATABASE_VERSION
|
||||
|
||||
TARGETS = $(CONFIG_TARGETS)
|
||||
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
|
||||
|
||||
|
||||
@@ -2,6 +2,36 @@
|
||||
|
||||
This document summarizes the changes to the module between releases.
|
||||
|
||||
## Release 4.6.0 (EPICS 7.0.6, Jul 2021)
|
||||
|
||||
* Access Security is now supported.
|
||||
* <b>special</b> has been revised and extended.
|
||||
* addRecord, removeRecord, processRecord, and traceRecord are replaced by pvdbcr versions.
|
||||
* <b>support</b> is DEPRECATED
|
||||
|
||||
## Release 4.5.3 (EPICS 7.0.5, Feb 2021)
|
||||
|
||||
* The previously deprecated destroy methods have been removed.
|
||||
Any application code that was previously calling these can just remove
|
||||
those calls.
|
||||
|
||||
## 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)
|
||||
|
||||
Formerly if a client makes a request for a subfield of a non structure field
|
||||
@@ -15,6 +45,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
|
||||
c) if type is not the same an exception is thrown
|
||||
|
||||
|
||||
## Release 4.4.1 (EPICS 7.0.2.1, Mar 2019)
|
||||
|
||||
* Cleaned up some build warnings.
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
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
|
||||
----------------
|
||||
|
||||
Currently only some simple tests exist. Most of the testing has been via the examples
|
||||
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>
|
||||
@@ -4,69 +4,62 @@
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
|
||||
<title>pvDatabaseCPP</title>
|
||||
<title>EPICS pvDatabaseCPP</title>
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/base.css" />
|
||||
href="https://mrkraimer.github.io/website/css/base.css" />
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
|
||||
href="https://mrkraimer.github.io/website/css/epicsv4.css" />
|
||||
<style type="text/css">
|
||||
/*<![CDATA[*/
|
||||
/*<![CDATA[*/
|
||||
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
|
||||
table { margin-left: auto; margin-right: auto }
|
||||
.diagram { text-align: center; margin: 2.5em 0 }
|
||||
span.opt { color: grey }
|
||||
span.nterm { font-style:italic }
|
||||
span.term { font-family:courier }
|
||||
span.user { font-family:courier }
|
||||
span.user:before { content:"<" }
|
||||
span.user:after { content:">" }
|
||||
.nonnorm { font-style:italic }
|
||||
p.ed { color: #AA0000 }
|
||||
span.ed { color: #AA0000 }
|
||||
p.ed.priv { display: inline; }
|
||||
span.ed.priv { display: inline; }
|
||||
/*]]>*/</style>
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript"
|
||||
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
|
||||
</script>
|
||||
body { margin-right: 10% }
|
||||
/*]]>*/</style>
|
||||
|
||||
<!-- Script that generates the Table of Contents -->
|
||||
<script type="text/javascript" src="https://mrkraimer.github.io/website/css/tocgen.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="head">
|
||||
<h1>pvDatabaseCPP</h1>
|
||||
<h2 class="nocount">Release 4.4 - December 2018</h2>
|
||||
|
||||
<h1>EPICS pvDatabaseCPP</h1>
|
||||
<h2 class="nocount">Release 4.6.0 - March 2021</h2>
|
||||
|
||||
<h2 class="nocount">Abstract</h2>
|
||||
|
||||
<p>This document describes pvDatabaseCPP,
|
||||
which is a framework for implementing a network accessible database of smart memory resident
|
||||
<p><b>pvDatabase</b> is a framework for implementing a network accessible database of smart memory resident
|
||||
records. Network access is via pvAccess. The data in each record is a top level PVStructure as defined by
|
||||
pvData. The framework includes a complete implementation of ChannelProvider as defined by pvAccess.
|
||||
The framework can be extended in order to create record instances that implements services.
|
||||
The minimum that an extension must provide is a top level PVStructure and a process method.
|
||||
</p>
|
||||
|
||||
<!-- last para of Abstract is boilerplate reference to EPICS -->
|
||||
<p>For more information about EPICS generally, please refer to the home page of the <a
|
||||
href="http://www.aps.anl.gov/epics/">Experimental Physics and Industrial
|
||||
Control System</a>.</p>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div id="toc">
|
||||
<h2 class="nocount">Table of Contents</h2>
|
||||
</div>
|
||||
</div> <!-- head -->
|
||||
|
||||
<div id="contents" class="contents">
|
||||
<hr />
|
||||
|
||||
<h2>Overview</h2>
|
||||
<p>
|
||||
Documentation for pvDatabaseCPP is available at:
|
||||
<a
|
||||
href="https://mrkraimer.github.io/website/developerGuide/pvDatabase/pvDatabaseCPP.html">
|
||||
pvDatabase
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
pvDatabaseCPP is one of the components of
|
||||
EPICS Version 7
|
||||
<a href="https://epics-controls.org/resources-and-support/base/epics-7/">
|
||||
EPICS-7
|
||||
</a>
|
||||
</p>
|
||||
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP
|
||||
</p>
|
||||
@@ -80,122 +73,28 @@ href="https://mrkraimer.github.io/website/developerGuide/developerGuide.html">
|
||||
developerGuide
|
||||
</a>
|
||||
</p>
|
||||
<p>This guide discusses all the components that are part of an <b>EPICS V4</b> release.
|
||||
<p>This guide provides an overview of the components that are part of an <b>EPICS V4</b> release.
|
||||
Some understanding of the components and how they are related is necessary in order to
|
||||
develop code that uses pvDatabaseCPP.
|
||||
In particular read everything related to pvDatabase.
|
||||
</p>
|
||||
<p>pvDatabase has plugin support, which is implemented in <b>pvCopy</b>.
|
||||
<b>pvCopy</b> was originally implemented in <b>pvDataCPP</b>,
|
||||
but pvDatabaseCPP now implemnents its own version and adds plugin support.
|
||||
</p>
|
||||
<p>
|
||||
See
|
||||
<a
|
||||
href="https://mrkraimer.github.io/website/pvRequest/pvRequest.html">
|
||||
pvRequest
|
||||
</a>
|
||||
for details.
|
||||
</p>
|
||||
<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.
|
||||
In particular read everything related to pvaClient.
|
||||
</p>
|
||||
|
||||
<h2>doxygen</h2>
|
||||
<p>doxygen documentation is available at
|
||||
<a
|
||||
href="./html/index.html">doxgen</a>
|
||||
href="./html/index.html">doxygen</a>
|
||||
</p>
|
||||
|
||||
<h2>pvDatabaseCPP</h2>
|
||||
<p>pvDatabaseCPP itself has the following implementations of a <b>PVRecord</b></p>
|
||||
<dl>
|
||||
<dt>RemoveRecord.cpp</dt>
|
||||
<dd>
|
||||
This is the code that is used to delete another record in the same <b>IOC</b>.
|
||||
</dd>
|
||||
<dt>TraceRecord.cpp</dt>
|
||||
<dd>
|
||||
This is the code that is used to set the trace level
|
||||
in another record in the same <b>IOC</b>.
|
||||
</dd>
|
||||
</dl>
|
||||
<h2>exampleCPP</h2>
|
||||
<p>Example code is available as part of this release.
|
||||
<p>Example code is available at
|
||||
<a
|
||||
href="http://epics-pvdata.sourceforge.net/docbuild/exampleCPP/tip/documentation/exampleCPP.html">
|
||||
href="https://github.com/epics-base/exampleCPP">
|
||||
exampleCPP
|
||||
</a>
|
||||
</p>
|
||||
<p>In particular look at the example code mentioned in the following sub-sections.
|
||||
<p>In particular look at database, exampleLink, and helloPutGet.
|
||||
</p>
|
||||
|
||||
<h3>database</h3>
|
||||
<p>This has many examples of how to create both soft records and records that implement
|
||||
other functionality.</p>
|
||||
<dl>
|
||||
<dt>exampleDatabase.cpp</dt>
|
||||
<dd>
|
||||
This shows how to create soft records of each pvData type.<br />
|
||||
In addition shows how to create instances of the following two records.
|
||||
</dd>
|
||||
<dt>exampleHelloRecord.cpp</dt>
|
||||
<dd>
|
||||
This is a simple "hello world" that is intentended to be used via a channelPutGet request.
|
||||
</dd>
|
||||
<dt>exampleHelloRPC.cpp</dt>
|
||||
<dd>
|
||||
This is a simple "hello world" that is intentended to be used via a channelRPC request.
|
||||
</dd>
|
||||
<dt>exampleDatabaseMain.cpp</dt>
|
||||
<dd>
|
||||
This shows how to create a standalone IOC.
|
||||
</dd>
|
||||
<dt>ioc and iocBoot</dt>
|
||||
<dd>
|
||||
This has code and examples to create a V3 IOC which also has a PVDatabase.
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>exampleLink</h3>
|
||||
<p>This shows how to implement a record that has a link to another record</p>
|
||||
<dl>
|
||||
<dt>exampleMonitorLinkRecord</dt>
|
||||
<dd>
|
||||
This creates a monitor link to another record.
|
||||
</dd>
|
||||
<dt>exampleGetLinkRecord</dt>
|
||||
<dd>
|
||||
This creates a get link to another record.
|
||||
</dd>
|
||||
<dt>examplePutLinkRecord</dt>
|
||||
<dd>
|
||||
This creates a put link to another record.
|
||||
</dd>
|
||||
</dl>
|
||||
|
||||
<h2>iocshell commands</h2>
|
||||
<p>Shell commands are made available via the standard DBD include mechanism
|
||||
provided by iocCore.
|
||||
The following provide EPICS V4 shell commands:</p>
|
||||
<pre>
|
||||
pvAccessCPP
|
||||
qsrv
|
||||
pvDatabaseCPP
|
||||
</pre>
|
||||
|
||||
<p>pvDatabaseCPP provides the following iocshell command.</p>
|
||||
<dl>
|
||||
<dt>registerChannelProviderLocal</dt>
|
||||
<dd>Including <b>registerChannelProviderLocal.dbd</b> as a dbd file automatically starts provider local
|
||||
and also creates the pvdbl shell command.
|
||||
</dd>
|
||||
<dt>pvdbl</dt>
|
||||
<dd>Provides a list of all the pvRecords in database <b>master</b>
|
||||
</dd>
|
||||
</dl>
|
||||
<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>
|
||||
|
||||
</div>
|
||||
</div> <!-- class="contents" -->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
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);
|
||||
}
|
||||
37
src/Makefile
37
src/Makefile
@@ -5,22 +5,43 @@ include $(TOP)/configure/CONFIG
|
||||
|
||||
PVDATABASE_SRC = $(TOP)/src
|
||||
|
||||
LIBRARY += pvDatabase
|
||||
|
||||
# shared library ABI version.
|
||||
SHRLIB_VERSION ?= 4.4.2
|
||||
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/pvDatabase.h
|
||||
INC += pv/traceRecord.h
|
||||
INC += pv/removeRecord.h
|
||||
|
||||
INC += pv/pvSupport.h
|
||||
INC += pv/controlSupport.h
|
||||
INC += pv/scalarAlarmSupport.h
|
||||
|
||||
INC += pv/pvdbcrScalarRecord.h
|
||||
INC += pv/pvdbcrScalarArrayRecord.h
|
||||
INC += pv/pvdbcrAddRecord.h
|
||||
INC += pv/pvdbcrRemoveRecord.h
|
||||
INC += pv/pvdbcrProcessRecord.h
|
||||
INC += pv/pvdbcrTraceRecord.h
|
||||
|
||||
include $(PVDATABASE_SRC)/copy/Makefile
|
||||
include $(PVDATABASE_SRC)/database/Makefile
|
||||
include $(PVDATABASE_SRC)/pvAccess/Makefile
|
||||
include $(PVDATABASE_SRC)/support/Makefile
|
||||
include $(PVDATABASE_SRC)/special/Makefile
|
||||
|
||||
pvDatabase_LIBS += $(EPICS_BASE_PVA_CORE_LIBS)
|
||||
pvDatabase_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
LIBRARY += pvDatabase
|
||||
pvDatabase_LIBS += pvData
|
||||
pvDatabase_LIBS += pvAccess
|
||||
LIB_LIBS += Com
|
||||
|
||||
# shared library ABI version.
|
||||
SHRLIB_VERSION ?= $(EPICS_PVDATABASE_MAJOR_VERSION).$(EPICS_PVDATABASE_MINOR_VERSION).$(EPICS_PVDATABASE_MAINTENANCE_VERSION)
|
||||
|
||||
# needed for Windows
|
||||
LIB_SYS_LIBS_WIN32 += netapi32 ws2_32
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
|
||||
# This is a Makefile fragment, see ../Makefile
|
||||
|
||||
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 += pvCopy.cpp
|
||||
LIBSRCS += pvArrayPlugin.cpp
|
||||
LIBSRCS += pvDeadbandPlugin.cpp
|
||||
LIBSRCS += pvTimestampPlugin.cpp
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <pv/convert.h>
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvArrayPlugin.h>
|
||||
#include "pv/pvArrayPlugin.h"
|
||||
|
||||
using std::string;
|
||||
using std::size_t;
|
||||
@@ -76,9 +76,19 @@ static vector<string> split(string const & colonSeparatedList) {
|
||||
|
||||
PVArrayFilterPtr PVArrayFilter::create(
|
||||
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) {
|
||||
PVArrayFilterPtr filter = PVArrayFilterPtr();
|
||||
return filter;
|
||||
@@ -112,60 +122,82 @@ PVArrayFilterPtr PVArrayFilter::create(
|
||||
PVArrayFilterPtr filter = PVArrayFilterPtr();
|
||||
return filter;
|
||||
}
|
||||
PVScalarArrayPtr masterArray;
|
||||
if(masterIsUnion) {
|
||||
masterArray = static_pointer_cast<PVScalarArray>(pvUnion->get());
|
||||
} else {
|
||||
masterArray = static_pointer_cast<PVScalarArray>(masterField);
|
||||
}
|
||||
PVArrayFilterPtr filter =
|
||||
PVArrayFilterPtr(
|
||||
new PVArrayFilter(
|
||||
start,increment,end,static_pointer_cast<PVScalarArray>(master)));
|
||||
new PVArrayFilter(start,increment,end,masterField,masterArray));
|
||||
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),
|
||||
increment(increment),
|
||||
end(end),
|
||||
masterField(masterField),
|
||||
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 start = this->start;
|
||||
long end = this->end;
|
||||
long no_elements = masterArray->getLength();
|
||||
if(start<0) {
|
||||
start = no_elements+start;
|
||||
if(start<0) start = 0;
|
||||
start = no_elements+start;
|
||||
if(start<0) start = 0;
|
||||
}
|
||||
if (end < 0) {
|
||||
end = no_elements + end;
|
||||
if (end < 0) end = 0;
|
||||
end = no_elements + end;
|
||||
if (end < 0) end = 0;
|
||||
|
||||
}
|
||||
if(toCopy) {
|
||||
if (end >= no_elements) end = no_elements - 1;
|
||||
if (end - start >= 0) len = 1 + (end - start) / increment;
|
||||
if(len<=0 || start>=no_elements) {
|
||||
copyArray->setLength(0);
|
||||
return true;
|
||||
}
|
||||
long indfrom = start;
|
||||
long indto = 0;
|
||||
copyArray->setCapacity(len);
|
||||
if(increment==1) {
|
||||
if(toCopy) {
|
||||
if (end >= no_elements) end = no_elements - 1;
|
||||
if (end - start >= 0) len = 1 + (end - start) / increment;
|
||||
if(len<=0 || start>=no_elements) {
|
||||
copyArray->setLength(0);
|
||||
return true;
|
||||
}
|
||||
long indfrom = start;
|
||||
long indto = 0;
|
||||
copyArray->setCapacity(len);
|
||||
if(increment==1) {
|
||||
copy(*masterArray,indfrom,1,*copyArray,indto,1,len);
|
||||
} else {
|
||||
for(long i=0; i<len; ++i) {
|
||||
copy(*masterArray,indfrom,1,*copyArray,indto,1,1);
|
||||
indfrom += increment;
|
||||
indto += 1;
|
||||
}
|
||||
}
|
||||
copyArray->setLength(len);
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
return true;
|
||||
} else {
|
||||
for(long i=0; i<len; ++i) {
|
||||
copy(*masterArray,indfrom,1,*copyArray,indto,1,1);
|
||||
indfrom += increment;
|
||||
indto += 1;
|
||||
}
|
||||
}
|
||||
copyArray->setLength(len);
|
||||
bitSet->set(pvField->getFieldOffset());
|
||||
return true;
|
||||
}
|
||||
if (end - start >= 0) len = 1 + (end - start) / increment;
|
||||
if(len<=0) return true;
|
||||
@@ -173,21 +205,21 @@ bool PVArrayFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet,bo
|
||||
long indfrom = 0;
|
||||
long indto = start;
|
||||
if(increment==1) {
|
||||
copy(*copyArray,indfrom,1,*masterArray,indto,1,len);
|
||||
copy(*copyArray,indfrom,1,*masterArray,indto,1,len);
|
||||
} else {
|
||||
for(long i=0; i<len; ++i) {
|
||||
copy(*copyArray,indfrom,1,*masterArray,indto,1,1);
|
||||
indfrom += increment;
|
||||
indto += 1;
|
||||
}
|
||||
for(long i=0; i<len; ++i) {
|
||||
copy(*copyArray,indfrom,1,*masterArray,indto,1,1);
|
||||
indfrom += 1;
|
||||
indto += increment;
|
||||
}
|
||||
}
|
||||
if(isUnion) masterField->postPut();
|
||||
return true;
|
||||
}
|
||||
|
||||
string PVArrayFilter::getName()
|
||||
{
|
||||
return name;
|
||||
return name;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
#include <pv/thread.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvPlugin.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
#include "pv/pvPlugin.h"
|
||||
#include "pv/pvStructureCopy.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
@@ -29,7 +29,7 @@ using std::endl;
|
||||
using std::vector;
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvCopy {
|
||||
namespace epics { namespace pvCopy {
|
||||
|
||||
/**
|
||||
* Convenience method for implementing dump.
|
||||
@@ -60,19 +60,19 @@ struct CopyNode {
|
||||
PVStructurePtr options;
|
||||
vector<PVFilterPtr> pvFilters;
|
||||
};
|
||||
|
||||
|
||||
static CopyNodePtr NULLCopyNode;
|
||||
|
||||
typedef std::vector<CopyNodePtr> CopyNodePtrArray;
|
||||
typedef std::tr1::shared_ptr<CopyNodePtrArray> CopyNodePtrArrayPtr;
|
||||
|
||||
|
||||
struct CopyStructureNode : public CopyNode {
|
||||
CopyNodePtrArrayPtr nodes;
|
||||
};
|
||||
|
||||
PVCopyPtr PVCopy::create(
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
PVStructurePtr const &pvMaster,
|
||||
PVStructurePtr const &pvRequest,
|
||||
string const & structureName)
|
||||
{
|
||||
PVStructurePtr pvStructure(pvRequest);
|
||||
@@ -114,7 +114,7 @@ PVStructurePtr PVCopy::createPVStructure()
|
||||
cacheInitStructure.reset();
|
||||
return save;
|
||||
}
|
||||
PVStructurePtr pvStructure =
|
||||
PVStructurePtr pvStructure =
|
||||
getPVDataCreate()->createPVStructure(structure);
|
||||
return pvStructure;
|
||||
}
|
||||
@@ -212,19 +212,91 @@ bool PVCopy::updateCopyFromBitSet(
|
||||
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(
|
||||
PVStructurePtr const ©PVStructure,
|
||||
BitSetPtr const &bitSet)
|
||||
{
|
||||
if(bitSet->get(0)) {
|
||||
for(size_t i=0; i< copyPVStructure->getNumberFields(); ++i) {
|
||||
bitSet->set(i,true);
|
||||
updateMasterCheckBitSet(copyPVStructure,bitSet,0);
|
||||
size_t nextSet =0;
|
||||
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)
|
||||
{
|
||||
if(fieldOffset==0) return headNode->options;
|
||||
@@ -248,7 +320,7 @@ PVStructurePtr PVCopy::getOptions(std::size_t fieldOffset)
|
||||
}
|
||||
}
|
||||
if(okToContinue) continue;
|
||||
throw std::logic_error("PVCopy logic error: fieldOffset not valid");
|
||||
throw std::logic_error("PVCopy::getOptions logic error: fieldOffset not valid");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,43 +414,13 @@ void PVCopy::updateCopyFromBitSet(
|
||||
size_t offset = structureNode->structureOffset;
|
||||
size_t nextSet = bitSet->nextSetBit(offset);
|
||||
if(nextSet==string::npos) return;
|
||||
if(offset>=pvCopy->getNextFieldOffset()) 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) {
|
||||
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(
|
||||
PVStructurePtr const &pvMaster)
|
||||
@@ -386,11 +428,6 @@ PVCopy::PVCopy(
|
||||
{
|
||||
}
|
||||
|
||||
void PVCopy::destroy()
|
||||
{
|
||||
headNode.reset();
|
||||
}
|
||||
|
||||
bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
|
||||
{
|
||||
PVStructurePtr pvMasterStructure = pvMaster;
|
||||
@@ -487,13 +524,13 @@ CopyNodePtr PVCopy::createStructureNodes(
|
||||
for(size_t i=0; i<number; i++) {
|
||||
PVFieldPtr copyPVField = copyPVFields[i];
|
||||
string fieldName = copyPVField->getFieldName();
|
||||
PVStructurePtr requestPVStructure =
|
||||
PVStructurePtr requestPVStructure =
|
||||
pvFromRequest->getSubField<PVStructure>(fieldName);
|
||||
PVStructurePtr pvSubFieldOptions =
|
||||
PVStructurePtr pvSubFieldOptions =
|
||||
requestPVStructure->getSubField<PVStructure>("_options");
|
||||
PVFieldPtr pvMasterField = pvMasterStructure->getSubField(fieldName);
|
||||
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();
|
||||
bool haveOptions = false;
|
||||
@@ -599,14 +636,14 @@ void PVCopy::initPlugin(
|
||||
|
||||
void PVCopy::traverseMasterInitPlugin()
|
||||
{
|
||||
traverseMasterInitPlugin(headNode);
|
||||
traverseMasterInitPlugin(headNode);
|
||||
}
|
||||
|
||||
void PVCopy::traverseMasterInitPlugin(CopyNodePtr const & node)
|
||||
{
|
||||
PVFieldPtr pvField = node->masterPVField;
|
||||
PVStructurePtr pvOptions = node->options;
|
||||
if(pvOptions) initPlugin(node,pvOptions,pvField);
|
||||
if(pvOptions) initPlugin(node,pvOptions,pvField);
|
||||
if(!node->isStructure) return;
|
||||
CopyStructureNodePtr structureNode = static_pointer_cast<CopyStructureNode>(node);
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
@@ -625,7 +662,7 @@ CopyNodePtr PVCopy::getCopyOffset(
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
if(!node->isStructure) {
|
||||
size_t off = node->masterPVField->getFieldOffset();
|
||||
size_t nextOffset = node->masterPVField->getNextFieldOffset();
|
||||
size_t nextOffset = node->masterPVField->getNextFieldOffset();
|
||||
if(offset>= off && offset<nextOffset) return node;
|
||||
} else {
|
||||
CopyStructureNodePtr subNode =
|
||||
@@ -668,7 +705,7 @@ void PVCopy::setIgnore(CopyNodePtr const &node) {
|
||||
CopyNodePtrArrayPtr nodes = structureNode->nodes;
|
||||
for(size_t i=0; i<nodes->size(); ++i) {
|
||||
CopyNodePtr node = (*nodes)[i];
|
||||
setIgnore(node); }
|
||||
setIgnore(node); }
|
||||
} else {
|
||||
size_t num = node->masterPVField->getNumberFields();
|
||||
if(num>1) {
|
||||
|
||||
@@ -4,12 +4,15 @@
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/bitSet.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvDeadbandPlugin.h>
|
||||
#include "pv/pvDeadbandPlugin.h"
|
||||
|
||||
using std::string;
|
||||
using std::size_t;
|
||||
@@ -64,9 +67,9 @@ PVDeadbandFilterPtr PVDeadbandFilter::create(
|
||||
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
|
||||
if(!ScalarTypeFunc::isNumeric(scalar->getScalarType())) return PVDeadbandFilterPtr();
|
||||
bool absolute = false;
|
||||
if(requestValue.find("abs")>=0) {
|
||||
if(requestValue.find("abs")==0) {
|
||||
absolute = true;
|
||||
} else if(requestValue.find("rel")>=0) {
|
||||
} else if(requestValue.find("rel")==0) {
|
||||
absolute = false;
|
||||
} else {
|
||||
return PVDeadbandFilterPtr();
|
||||
@@ -79,7 +82,7 @@ PVDeadbandFilterPtr PVDeadbandFilter::create(
|
||||
PVDeadbandFilterPtr filter =
|
||||
PVDeadbandFilterPtr(
|
||||
new PVDeadbandFilter(
|
||||
absolute,deadband,static_pointer_cast<PVScalar>(master)));
|
||||
absolute,deadband,static_pointer_cast<PVScalar>(master)));
|
||||
return filter;
|
||||
}
|
||||
|
||||
@@ -88,7 +91,7 @@ PVDeadbandFilter::PVDeadbandFilter(bool absolute,double deadband,PVScalarPtr con
|
||||
deadband(deadband),
|
||||
master(master),
|
||||
firstTime(true),
|
||||
lastReportedValue(0.0)
|
||||
lastReportedValue(0.0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -125,8 +128,7 @@ bool PVDeadbandFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet
|
||||
|
||||
string PVDeadbandFilter::getName()
|
||||
{
|
||||
return name;
|
||||
return name;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
*/
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvStructureCopy.h>
|
||||
#include <pv/pvPlugin.h>
|
||||
#include "pv/pvPlugin.h"
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvCopy{
|
||||
namespace epics { namespace pvCopy{
|
||||
|
||||
typedef std::map<std::string,PVPluginPtr> PVPluginMap;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/bitSet.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvTimestampPlugin.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
#include "pv/pvPlugin.h"
|
||||
#include "pv/pvTimestampPlugin.h"
|
||||
|
||||
|
||||
using std::string;
|
||||
using std::size_t;
|
||||
@@ -86,7 +89,7 @@ PVTimestampFilter::PVTimestampFilter(bool current,bool copy,PVFieldPtr const & m
|
||||
|
||||
bool PVTimestampFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet,bool toCopy)
|
||||
{
|
||||
if(current) {
|
||||
if(current) {
|
||||
timeStamp.getCurrent();
|
||||
if(toCopy) {
|
||||
if(!pvTimeStamp.attach(pvCopy)) return false;
|
||||
@@ -97,7 +100,7 @@ bool PVTimestampFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSe
|
||||
bitSet->set(pvCopy->getFieldOffset());
|
||||
return true;
|
||||
}
|
||||
if(copy) {
|
||||
if(copy) {
|
||||
if(toCopy) {
|
||||
if(!pvTimeStamp.attach(master)) return false;
|
||||
pvTimeStamp.get(timeStamp);
|
||||
@@ -117,8 +120,7 @@ bool PVTimestampFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSe
|
||||
|
||||
string PVTimestampFilter::getName()
|
||||
{
|
||||
return name;
|
||||
return name;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -10,13 +10,19 @@
|
||||
*/
|
||||
|
||||
#include <epicsGuard.h>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
#include <pv/pvPlugin.h>
|
||||
#include <pv/pvArrayPlugin.h>
|
||||
#include <pv/pvTimestampPlugin.h>
|
||||
#include <pv/pvDeadbandPlugin.h>
|
||||
#include "pv/pvStructureCopy.h"
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/pvPlugin.h"
|
||||
#include "pv/pvArrayPlugin.h"
|
||||
#include "pv/pvTimestampPlugin.h"
|
||||
#include "pv/pvDeadbandPlugin.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
@@ -38,7 +44,7 @@ PVDatabasePtr PVDatabase::getMaster()
|
||||
PVArrayPlugin::create();
|
||||
PVTimestampPlugin::create();
|
||||
PVDeadbandPlugin::create();
|
||||
}
|
||||
}
|
||||
return pvDatabaseMaster;
|
||||
}
|
||||
|
||||
@@ -50,14 +56,6 @@ PVDatabase::PVDatabase()
|
||||
PVDatabase::~PVDatabase()
|
||||
{
|
||||
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() {
|
||||
@@ -94,17 +92,28 @@ bool PVDatabase::addRecord(PVRecordPtr const & record)
|
||||
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);
|
||||
string recordName = record->getRecordName();
|
||||
PVRecordMap::iterator iter = recordMap.find(recordName);
|
||||
if(iter!=recordMap.end()) {
|
||||
PVRecordPtr pvRecord = (*iter).second;
|
||||
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 false;
|
||||
|
||||
@@ -8,13 +8,25 @@
|
||||
* @author mrk
|
||||
* @date 2012.11.21
|
||||
*/
|
||||
#include <list>
|
||||
#include <epicsGuard.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
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
#include "pv/pvStructureCopy.h"
|
||||
#include "pv/pvDatabase.h"
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
@@ -25,9 +37,11 @@ namespace epics { namespace pvDatabase {
|
||||
|
||||
PVRecordPtr PVRecord::create(
|
||||
string const &recordName,
|
||||
PVStructurePtr const & pvStructure)
|
||||
PVStructurePtr const & pvStructure,
|
||||
int asLevel,
|
||||
const std::string& asGroup)
|
||||
{
|
||||
PVRecordPtr pvRecord(new PVRecord(recordName,pvStructure));
|
||||
PVRecordPtr pvRecord(new PVRecord(recordName,pvStructure,asLevel,asGroup));
|
||||
if(!pvRecord->init()) {
|
||||
pvRecord.reset();
|
||||
}
|
||||
@@ -37,25 +51,29 @@ PVRecordPtr PVRecord::create(
|
||||
|
||||
PVRecord::PVRecord(
|
||||
string const & recordName,
|
||||
PVStructurePtr const & pvStructure)
|
||||
PVStructurePtr const & pvStructure,
|
||||
int asLevel_,
|
||||
const std::string& asGroup_)
|
||||
: recordName(recordName),
|
||||
pvStructure(pvStructure),
|
||||
depthGroupPut(0),
|
||||
traceLevel(0),
|
||||
isAddListener(false)
|
||||
isAddListener(false),
|
||||
asLevel(asLevel_),
|
||||
asGroup(asGroup_)
|
||||
{
|
||||
}
|
||||
|
||||
void PVRecord::notifyClients()
|
||||
PVRecord::~PVRecord()
|
||||
{
|
||||
{
|
||||
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||
if(traceLevel>0) {
|
||||
cout << "PVRecord::notifyClients() " << recordName
|
||||
<< endl;
|
||||
}
|
||||
if(traceLevel>0) {
|
||||
cout << "~PVRecord() " << recordName << endl;
|
||||
}
|
||||
pvTimeStamp.detach();
|
||||
}
|
||||
|
||||
void PVRecord::unlistenClients()
|
||||
{
|
||||
epicsGuard<epics::pvData::Mutex> guard(mutex);
|
||||
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
|
||||
iter!=pvListenerList.end();
|
||||
iter++ )
|
||||
@@ -63,8 +81,7 @@ void PVRecord::notifyClients()
|
||||
PVListenerPtr listener = iter->lock();
|
||||
if(!listener) continue;
|
||||
if(traceLevel>0) {
|
||||
cout << "PVRecord::notifyClients() calling listener->unlisten "
|
||||
<< recordName << endl;
|
||||
cout << "PVRecord::remove() calling listener->unlisten " << recordName << endl;
|
||||
}
|
||||
listener->unlisten(shared_from_this());
|
||||
}
|
||||
@@ -76,27 +93,24 @@ void PVRecord::notifyClients()
|
||||
PVRecordClientPtr client = iter->lock();
|
||||
if(!client) continue;
|
||||
if(traceLevel>0) {
|
||||
cout << "PVRecord::notifyClients() calling client->detach "
|
||||
<< recordName << endl;
|
||||
cout << "PVRecord::remove() calling client->detach " << recordName << endl;
|
||||
}
|
||||
client->detach(shared_from_this());
|
||||
}
|
||||
if(traceLevel>0) {
|
||||
cout << "PVRecord::notifyClients() calling clientList.clear() "
|
||||
<< recordName << endl;
|
||||
}
|
||||
clientList.clear();
|
||||
if(traceLevel>0) {
|
||||
cout << "PVRecord::notifyClients() returning " << recordName << endl;
|
||||
}
|
||||
}
|
||||
|
||||
PVRecord::~PVRecord()
|
||||
|
||||
void PVRecord::remove()
|
||||
{
|
||||
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()
|
||||
@@ -240,7 +254,7 @@ void PVRecord::nextMasterPVField(PVFieldPtr const & pvField)
|
||||
PVRecordFieldPtr pvRecordField = findPVRecordField(pvField);
|
||||
PVListenerPtr listener = pvListener.lock();
|
||||
if(!listener.get()) return;
|
||||
if(isAddListener) {
|
||||
if(isAddListener) {
|
||||
pvRecordField->addListener(listener);
|
||||
} else {
|
||||
pvRecordField->removeListener(listener);
|
||||
@@ -369,7 +383,7 @@ bool PVRecordField::addListener(PVListenerPtr const & pvListener)
|
||||
|
||||
void PVRecordField::removeListener(PVListenerPtr const & pvListener)
|
||||
{
|
||||
PVRecordPtr pvRecord(this->pvRecord.lock());
|
||||
PVRecordPtr pvRecord(this->pvRecord.lock());
|
||||
if(pvRecord && pvRecord->getTraceLevel()>1) {
|
||||
cout << "PVRecordField::removeListener() " << getFullName() << endl;
|
||||
}
|
||||
@@ -411,7 +425,7 @@ void PVRecordField::postSubField()
|
||||
{
|
||||
callListener();
|
||||
if(isStructure) {
|
||||
PVRecordStructurePtr pvrs =
|
||||
PVRecordStructurePtr pvrs =
|
||||
static_pointer_cast<PVRecordStructure>(shared_from_this());
|
||||
PVRecordFieldPtrArrayPtr pvRecordFields = pvrs->getPVRecordFields();
|
||||
PVRecordFieldPtrArray::iterator iter;
|
||||
@@ -451,7 +465,7 @@ void PVRecordStructure::init()
|
||||
PVRecordStructurePtr self =
|
||||
static_pointer_cast<PVRecordStructure>(shared_from_this());
|
||||
PVRecordPtr pvRecord = getPVRecord();
|
||||
for(size_t i=0; i<numFields; i++) {
|
||||
for(size_t i=0; i<numFields; i++) {
|
||||
PVFieldPtr pvField = pvFields[i];
|
||||
if(pvField->getField()->getType()==structure) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
|
||||
|
||||
@@ -11,11 +11,6 @@
|
||||
#ifndef CHANNELPROVIDERLOCAL_H
|
||||
#define CHANNELPROVIDERLOCAL_H
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define channelProviderLocalEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
@@ -28,18 +23,13 @@
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/status.h>
|
||||
#include <pv/serverContext.h>
|
||||
|
||||
|
||||
#ifdef channelProviderLocalEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef channelProviderLocalEpicsExportSharedSymbols
|
||||
#endif
|
||||
#include <pv/pvStructureCopy.h>
|
||||
#include <pv/pvDatabase.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
#include <asLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class ChannelProviderLocal;
|
||||
typedef std::tr1::shared_ptr<ChannelProviderLocal> ChannelProviderLocalPtr;
|
||||
@@ -69,6 +59,19 @@ class epicsShareClass ChannelProviderLocal :
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelProviderLocal);
|
||||
/**
|
||||
* @brief Initialize access security configuration
|
||||
* @param filePath AS definition file path
|
||||
* @param substitutions macro substitutions
|
||||
* @throws std::runtime_error in case of configuration problem
|
||||
*/
|
||||
static void initAs(const std::string& filePath, const std::string& substitutions="");
|
||||
/**
|
||||
* @brief Is access security active?
|
||||
* @return true is AS is active
|
||||
*/
|
||||
static bool isAsActive();
|
||||
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
@@ -77,11 +80,6 @@ public:
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~ChannelProviderLocal();
|
||||
/**
|
||||
* @brief DEPRECATED
|
||||
*
|
||||
*/
|
||||
virtual void destroy(){};
|
||||
/**
|
||||
* @brief Returns the channel provider name.
|
||||
*
|
||||
@@ -104,7 +102,7 @@ public:
|
||||
virtual epics::pvAccess::ChannelFind::shared_pointer channelFind(
|
||||
std::string const &channelName,
|
||||
epics::pvAccess::ChannelFindRequester::shared_pointer const & channelFindRequester);
|
||||
/**
|
||||
/**
|
||||
* @brief Calls method channelListRequester::channelListResult.
|
||||
*
|
||||
* This provides the caller with a list of the record names on the PVDatabase.
|
||||
@@ -112,7 +110,7 @@ public:
|
||||
* @param channelListRequester The client callback.
|
||||
* @return shared pointer to ChannelFind.
|
||||
* The interface for SyncChannelFind is defined by pvAccessCPP.
|
||||
*/
|
||||
*/
|
||||
virtual epics::pvAccess::ChannelFind::shared_pointer channelList(
|
||||
epics::pvAccess::ChannelListRequester::shared_pointer const & channelListRequester);
|
||||
/**
|
||||
@@ -174,6 +172,7 @@ private:
|
||||
friend class ChannelProviderLocalRun;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief Channel for accessing a PVRecord.
|
||||
*
|
||||
@@ -197,28 +196,23 @@ public:
|
||||
epics::pvAccess::ChannelRequester::shared_pointer const & requester,
|
||||
PVRecordPtr const & pvRecord
|
||||
);
|
||||
/**
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~ChannelLocal();
|
||||
/**
|
||||
* @brief DEPRECATED
|
||||
*
|
||||
*/
|
||||
virtual void destroy() {};
|
||||
/**
|
||||
/**
|
||||
* @brief Detach from the record.
|
||||
*
|
||||
* This is called when a record is being removed from the database.
|
||||
* @param pvRecord The record being removed.
|
||||
*/
|
||||
virtual void detach(PVRecordPtr const &pvRecord);
|
||||
/**
|
||||
/**
|
||||
* @brief Get the requester name.
|
||||
* @return returns the name of the channel requester.
|
||||
*/
|
||||
virtual std::string getRequesterName();
|
||||
/**
|
||||
/**
|
||||
* @brief Passes the message to the channel requester.
|
||||
* @param message The message.
|
||||
* @param messageType The message type.
|
||||
@@ -226,37 +220,37 @@ public:
|
||||
virtual void message(
|
||||
std::string const & message,
|
||||
epics::pvData::MessageType messageType);
|
||||
/**
|
||||
/**
|
||||
* @brief Get the channel provider
|
||||
* @return The provider.
|
||||
*/
|
||||
virtual epics::pvAccess::ChannelProvider::shared_pointer getProvider();
|
||||
/**
|
||||
/**
|
||||
* @brief Get the remote address
|
||||
* @return <b>local</b>
|
||||
*/
|
||||
virtual std::string getRemoteAddress();
|
||||
/**
|
||||
/**
|
||||
* Get the connection state.
|
||||
* @return Channel::CONNECTED.
|
||||
*/
|
||||
virtual epics::pvAccess::Channel::ConnectionState getConnectionState();
|
||||
/**
|
||||
/**
|
||||
* @brief Get the channel name.
|
||||
* @return the record name.
|
||||
*/
|
||||
virtual std::string getChannelName();
|
||||
/**
|
||||
/**
|
||||
* @brief Get the channel requester
|
||||
* @return The channel requester.
|
||||
*/
|
||||
virtual epics::pvAccess::ChannelRequester::shared_pointer getChannelRequester();
|
||||
/**
|
||||
/**
|
||||
* @brief Is the channel connected?
|
||||
* @return true.
|
||||
*/
|
||||
virtual bool isConnected();
|
||||
/**
|
||||
/**
|
||||
* @brief Get the introspection interface for subField.
|
||||
*
|
||||
* The introspection interface is given via GetFieldRequester::getDone.
|
||||
@@ -268,14 +262,14 @@ public:
|
||||
virtual void getField(
|
||||
epics::pvAccess::GetFieldRequester::shared_pointer const &requester,
|
||||
std::string const & subField);
|
||||
/**
|
||||
/**
|
||||
* Get the access rights for the record.
|
||||
* This throws an exception because it is assumed that access rights are
|
||||
* handled by a higher level.
|
||||
*/
|
||||
virtual epics::pvAccess::AccessRights getAccessRights(
|
||||
epics::pvData::PVField::shared_pointer const &pvField);
|
||||
/**
|
||||
/**
|
||||
* @brief Create a channelProcess.
|
||||
*
|
||||
* @param requester The client callback.
|
||||
@@ -286,9 +280,9 @@ public:
|
||||
virtual epics::pvAccess::ChannelProcess::shared_pointer createChannelProcess(
|
||||
epics::pvAccess::ChannelProcessRequester::shared_pointer const &requester,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
/**
|
||||
/**
|
||||
* @brief Create a channelGet.
|
||||
*
|
||||
*
|
||||
* @param requester The client callback.
|
||||
* @param pvRequest The options specified by the client.
|
||||
* @return A shared pointer to the newly created implementation.
|
||||
@@ -297,7 +291,7 @@ public:
|
||||
virtual epics::pvAccess::ChannelGet::shared_pointer createChannelGet(
|
||||
epics::pvAccess::ChannelGetRequester::shared_pointer const &requester,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
/**
|
||||
/**
|
||||
* @brief Create a channelPut.
|
||||
*
|
||||
* @param requester The client callback.
|
||||
@@ -308,9 +302,9 @@ public:
|
||||
virtual epics::pvAccess::ChannelPut::shared_pointer createChannelPut(
|
||||
epics::pvAccess::ChannelPutRequester::shared_pointer const &requester,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
/**
|
||||
/**
|
||||
* @brief Create a channelPutGet.
|
||||
*
|
||||
*
|
||||
* @param requester The client callback.
|
||||
* @param pvRequest The options specified by the client.
|
||||
* @return A shared pointer to the newly created implementation.
|
||||
@@ -319,7 +313,7 @@ public:
|
||||
virtual epics::pvAccess::ChannelPutGet::shared_pointer createChannelPutGet(
|
||||
epics::pvAccess::ChannelPutGetRequester::shared_pointer const &requester,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
/**
|
||||
/**
|
||||
* @brief Create a channelRPC.
|
||||
*
|
||||
* The PVRecord must implement <b>getService</b> or an empty shared pointer is returned.
|
||||
@@ -330,9 +324,9 @@ public:
|
||||
virtual epics::pvAccess::ChannelRPC::shared_pointer createChannelRPC(
|
||||
epics::pvAccess::ChannelRPCRequester::shared_pointer const &requester,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
/**
|
||||
/**
|
||||
* @brief Create a monitor.
|
||||
*
|
||||
*
|
||||
* @param requester The client callback.
|
||||
* @param pvRequest The options specified by the client.
|
||||
* @return A shared pointer to the newly created implementation.
|
||||
@@ -341,9 +335,9 @@ public:
|
||||
virtual epics::pvData::Monitor::shared_pointer createMonitor(
|
||||
epics::pvData::MonitorRequester::shared_pointer const &requester,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
/**
|
||||
/**
|
||||
* @brief Create a channelArray.
|
||||
*
|
||||
*
|
||||
* @param requester The client callback.
|
||||
* @param pvRequest The options specified by the client.
|
||||
* @return A shared pointer to the newly created implementation.
|
||||
@@ -352,16 +346,28 @@ public:
|
||||
virtual epics::pvAccess::ChannelArray::shared_pointer createChannelArray(
|
||||
epics::pvAccess::ChannelArrayRequester::shared_pointer const &requester,
|
||||
epics::pvData::PVStructurePtr const &pvRequest);
|
||||
/**
|
||||
/**
|
||||
* @brief calls printInfo(std::cout);
|
||||
*/
|
||||
virtual void printInfo();
|
||||
/**
|
||||
/**
|
||||
* @brief displays a message
|
||||
*
|
||||
*
|
||||
* @param out the stream on which the message is displayed.
|
||||
*/
|
||||
virtual void printInfo(std::ostream& out);
|
||||
/**
|
||||
* @brief determines if client can write
|
||||
*
|
||||
* @return true if client can write
|
||||
*/
|
||||
virtual bool canWrite();
|
||||
/**
|
||||
* @brief determines if client can read
|
||||
*
|
||||
* @return true if client can read
|
||||
*/
|
||||
virtual bool canRead();
|
||||
protected:
|
||||
shared_pointer getPtrSelf()
|
||||
{
|
||||
@@ -372,6 +378,19 @@ private:
|
||||
ChannelProviderLocalWPtr provider;
|
||||
PVRecordWPtr pvRecord;
|
||||
epics::pvData::Mutex mutex;
|
||||
|
||||
// AS-specific variables/methods
|
||||
std::vector<char> toCharArray(const std::string& s);
|
||||
std::vector<char> getAsGroup(const PVRecordPtr& pvRecord);
|
||||
std::vector<char> getAsUser(const epics::pvAccess::ChannelRequester::shared_pointer& requester);
|
||||
std::vector<char> getAsHost(const epics::pvAccess::ChannelRequester::shared_pointer& requester);
|
||||
|
||||
int asLevel;
|
||||
std::vector<char> asGroup;
|
||||
std::vector<char> asUser;
|
||||
std::vector<char> asHost;
|
||||
ASMEMBERPVT asMemberPvt;
|
||||
ASCLIENTPVT asClientPvt;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
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 */
|
||||
@@ -6,10 +6,6 @@
|
||||
#ifndef PVARRAYPLUGIN_H
|
||||
#define PVARRAYPLUGIN_H
|
||||
|
||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <pv/lock.h>
|
||||
@@ -67,9 +63,13 @@ private:
|
||||
long start;
|
||||
long increment;
|
||||
long end;
|
||||
epics::pvData::PVFieldPtr masterField;
|
||||
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:
|
||||
POINTER_DEFINITIONS(PVArrayFilter);
|
||||
virtual ~PVArrayFilter();
|
||||
@@ -99,4 +99,3 @@ public:
|
||||
|
||||
}}
|
||||
#endif /* PVARRAYPLUGIN_H */
|
||||
|
||||
@@ -6,28 +6,17 @@
|
||||
#ifndef PVDATABASE_H
|
||||
#define PVDATABASE_H
|
||||
|
||||
#ifdef epicsExportSharedSymbols
|
||||
# define pvdatabaseEpicsExportSharedSymbols
|
||||
# undef epicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
|
||||
#ifdef pvdatabaseEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef pvdatabaseEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PVRecord;
|
||||
typedef std::tr1::shared_ptr<PVRecord> PVRecordPtr;
|
||||
@@ -70,6 +59,7 @@ class epicsShareClass PVRecord :
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVRecord);
|
||||
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
@@ -98,14 +88,19 @@ public:
|
||||
*/
|
||||
virtual void process();
|
||||
/**
|
||||
* @brief DEPRECATED
|
||||
* @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 destroy() {}
|
||||
virtual void remove();
|
||||
/**
|
||||
* @brief Optional method for derived class.
|
||||
*
|
||||
* Return a service corresponding to the specified request PVStructure.
|
||||
* @param pvRequest The request PVStructure
|
||||
* @param pvRequest The request PVStructure
|
||||
* @return The corresponding service
|
||||
*/
|
||||
virtual epics::pvAccess::RPCServiceAsync::shared_pointer getService(
|
||||
@@ -114,15 +109,18 @@ public:
|
||||
return epics::pvAccess::RPCServiceAsync::shared_pointer();
|
||||
}
|
||||
/**
|
||||
* @brief Creates a <b>soft</b> record.
|
||||
* @brief Creates a <b>soft</b> record.
|
||||
*
|
||||
* @param recordName The name of the record, which is also the channelName.
|
||||
* @param pvStructure The top level structure.
|
||||
* @param asLevel AS level (default: ASL0)
|
||||
* @param asGroup AS group (default: DEFAULT)
|
||||
* @return A shared pointer to the newly created record.
|
||||
*/
|
||||
static PVRecordPtr create(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel = 0, const std::string& asGroup = "DEFAULT");
|
||||
/**
|
||||
* @brief Get the name of the record.
|
||||
*
|
||||
@@ -238,26 +236,53 @@ public:
|
||||
* @param level The level
|
||||
*/
|
||||
void setTraceLevel(int level) {traceLevel = level;}
|
||||
/**
|
||||
* @brief Get the ASlevel
|
||||
*
|
||||
* @return The level.
|
||||
*/
|
||||
int getAsLevel() const {return asLevel;}
|
||||
/**
|
||||
* @brief Get the AS group name
|
||||
*
|
||||
* @return The name.
|
||||
*/
|
||||
std::string getAsGroup() const {return asGroup;}
|
||||
/**
|
||||
* @brief set access security level.
|
||||
* @param level The level
|
||||
*/
|
||||
void setAsLevel(int level) {asLevel=level;}
|
||||
/**
|
||||
* @brief set access security group
|
||||
* @param group The group name
|
||||
*/
|
||||
void setAsGroup(const std::string& group) {asGroup = group;}
|
||||
protected:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param recordName The name of the record
|
||||
* @param pvStructure The top level PVStructutre
|
||||
* @param asLevel AS level (default: ASL0)
|
||||
* @param asGroup AS group (default: DEFAULT)
|
||||
*/
|
||||
PVRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel = 0, const std::string& asGroup = "DEFAULT");
|
||||
/**
|
||||
* @brief Initializes the base class.
|
||||
*
|
||||
*
|
||||
* Must be called by derived classes.
|
||||
*/
|
||||
void initPVRecord();
|
||||
private:
|
||||
friend class PVDatabase;
|
||||
void unlistenClients();
|
||||
|
||||
PVRecordFieldPtr findPVRecordField(
|
||||
PVRecordStructurePtr const & pvrs,
|
||||
epics::pvData::PVFieldPtr const & pvField);
|
||||
void notifyClients();
|
||||
|
||||
std::string recordName;
|
||||
epics::pvData::PVStructurePtr pvStructure;
|
||||
@@ -273,6 +298,9 @@ private:
|
||||
|
||||
epics::pvData::PVTimeStamp pvTimeStamp;
|
||||
epics::pvData::TimeStamp timeStamp;
|
||||
|
||||
int asLevel;
|
||||
std::string asGroup;
|
||||
};
|
||||
|
||||
epicsShareFunc std::ostream& operator<<(std::ostream& o, const PVRecord& record);
|
||||
@@ -501,6 +529,7 @@ public:
|
||||
/**
|
||||
* @brief Remove a record.
|
||||
* @param record The record to remove.
|
||||
*
|
||||
* @return <b>true</b> if record was removed.
|
||||
*/
|
||||
bool removeRecord(PVRecordPtr const & record);
|
||||
@@ -510,6 +539,9 @@ public:
|
||||
*/
|
||||
epics::pvData::PVStringArrayPtr getRecordNames();
|
||||
private:
|
||||
friend class PVRecord;
|
||||
|
||||
PVRecordWPtr removeFromMap(PVRecordPtr const & record);
|
||||
PVDatabase();
|
||||
void lock();
|
||||
void unlock();
|
||||
@@ -521,4 +553,3 @@ private:
|
||||
}}
|
||||
|
||||
#endif /* PVDATABASE_H */
|
||||
|
||||
|
||||
@@ -6,9 +6,6 @@
|
||||
#ifndef PVDEADBANDPLUGIN_H
|
||||
#define PVDEADBANDPLUGIN_H
|
||||
|
||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
@@ -69,7 +66,7 @@ private:
|
||||
epics::pvData::PVScalarPtr master;
|
||||
bool firstTime;
|
||||
double lastReportedValue;
|
||||
|
||||
|
||||
|
||||
PVDeadbandFilter(bool absolute,double deadband,epics::pvData::PVScalarPtr const & master);
|
||||
public:
|
||||
@@ -103,4 +100,3 @@ public:
|
||||
|
||||
}}
|
||||
#endif /* PVDEADBANDPLUGIN_H */
|
||||
|
||||
@@ -9,23 +9,22 @@
|
||||
#ifndef PVPLUGIN_H
|
||||
#define PVPLUGIN_H
|
||||
|
||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <pv/lock.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
#include <pv/bitSet.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvCopy{
|
||||
namespace epics { namespace pvCopy{
|
||||
|
||||
class PVPlugin;
|
||||
class PVFilter;
|
||||
class PVPluginRegistry;
|
||||
|
||||
class PVCopy;
|
||||
typedef std::tr1::shared_ptr<PVCopy> PVCopyPtr;
|
||||
|
||||
typedef std::tr1::shared_ptr<PVPlugin> PVPluginPtr;
|
||||
typedef std::tr1::shared_ptr<PVFilter> PVFilterPtr;
|
||||
typedef std::map<std::string,PVPluginPtr> PVPluginMap;
|
||||
@@ -37,7 +36,7 @@ typedef std::map<std::string,PVPluginPtr> PVPluginMap;
|
||||
* PVCopy looks for plugins defined in pvRequest and calls the filter when a pvCopy is updated.
|
||||
* @author mrk
|
||||
* @since 2017.03.17
|
||||
*
|
||||
*
|
||||
* Interface for a filter plugin for PVCopy.
|
||||
*
|
||||
*/
|
||||
@@ -10,10 +10,6 @@
|
||||
#ifndef PVSTRUCTURECOPY_H
|
||||
#define PVSTRUCTURECOPY_H
|
||||
|
||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
@@ -22,7 +18,7 @@
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvCopy{
|
||||
namespace epics { namespace pvCopy{
|
||||
|
||||
class PVCopyTraverseMasterCallback;
|
||||
typedef std::tr1::shared_ptr<PVCopyTraverseMasterCallback> PVCopyTraverseMasterCallbackPtr;
|
||||
@@ -66,7 +62,7 @@ typedef std::tr1::shared_ptr<CopyStructureNode> CopyStructureNodePtr;
|
||||
* Class that manages one or more PVStructures that holds an arbitrary subset of the fields
|
||||
* in another PVStructure called master.
|
||||
*/
|
||||
class epicsShareClass PVCopy :
|
||||
class epicsShareClass PVCopy :
|
||||
public std::tr1::enable_shared_from_this<PVCopy>
|
||||
{
|
||||
public:
|
||||
@@ -83,7 +79,6 @@ public:
|
||||
epics::pvData::PVStructurePtr const &pvRequest,
|
||||
std::string const & structureName);
|
||||
virtual ~PVCopy(){}
|
||||
virtual void destroy();
|
||||
/**
|
||||
* Get the top-level structure of master
|
||||
* @returns The master top-level structure.
|
||||
@@ -177,12 +172,12 @@ public:
|
||||
*/
|
||||
std::string dump();
|
||||
private:
|
||||
|
||||
|
||||
PVCopyPtr getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
|
||||
epics::pvData::PVStructurePtr pvMaster;
|
||||
epics::pvData::StructureConstPtr structure;
|
||||
CopyNodePtr headNode;
|
||||
@@ -204,10 +199,16 @@ private:
|
||||
epics::pvData::PVFieldPtr const &pvCopy,
|
||||
CopyNodePtr const &node,
|
||||
epics::pvData::BitSetPtr const &bitSet);
|
||||
void updateMaster(
|
||||
epics::pvData::PVFieldPtr const &pvCopy,
|
||||
CopyNodePtr const &node,
|
||||
void updateMasterField(
|
||||
CopyNodePtr const & node,
|
||||
epics::pvData::PVFieldPtr const & pvCopy,
|
||||
epics::pvData::PVFieldPtr const &pvMaster,
|
||||
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);
|
||||
bool init(epics::pvData::PVStructurePtr const &pvRequest);
|
||||
@@ -239,7 +240,6 @@ private:
|
||||
std::string *builder,
|
||||
CopyNodePtr const &node,
|
||||
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
|
||||
#define PVTIMESTAMPPLUGIN_H
|
||||
|
||||
#if defined(_WIN32) && !defined(NOMINMAX)
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#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
|
||||
{
|
||||
@@ -70,7 +66,7 @@ private:
|
||||
bool current;
|
||||
bool copy;
|
||||
epics::pvData::PVFieldPtr master;
|
||||
|
||||
|
||||
|
||||
PVTimestampFilter(bool current,bool copy,epics::pvData::PVFieldPtr const & pvField);
|
||||
public:
|
||||
@@ -102,4 +98,3 @@ public:
|
||||
|
||||
}}
|
||||
#endif /* PVTIMESTAMPPLUGIN_H */
|
||||
|
||||
67
src/pv/pvdbcrAddRecord.h
Normal file
67
src/pv/pvdbcrAddRecord.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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 2021.04.11
|
||||
*/
|
||||
#ifndef PVDBCRADDARRAY_H
|
||||
#define PVDBCRADDARRAY_H
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvSupport.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PvdbcrAddRecord;
|
||||
typedef std::tr1::shared_ptr<PvdbcrAddRecord> PvdbcrAddRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief PvdbcrAddRecord A record that adds a record to the master database.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvdbcrAddRecord :
|
||||
public PVRecord
|
||||
{
|
||||
private:
|
||||
PvdbcrAddRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup);
|
||||
epics::pvData::PVStringPtr pvRecordName;
|
||||
epics::pvData::PVStringPtr pvResult;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvdbcrAddRecord);
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
virtual ~PvdbcrAddRecord() {}
|
||||
/**
|
||||
* @brief Create a record.
|
||||
*
|
||||
* @param recordName The record name.
|
||||
* @param asLevel The access security level.
|
||||
* @param asGroup The access security group.
|
||||
* @return The PVRecord
|
||||
*/
|
||||
static PvdbcrAddRecordPtr create(
|
||||
std::string const & recordName,
|
||||
int asLevel=0,std::string const & asGroup = std::string("DEFAULT"));
|
||||
/**
|
||||
* @brief a PVRecord method
|
||||
* @return success or failure
|
||||
*/
|
||||
virtual bool init();
|
||||
/**
|
||||
* @brief process method that adds a record to the master database.
|
||||
*/
|
||||
virtual void process();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVDBCRADDARRAY_H */
|
||||
105
src/pv/pvdbcrProcessRecord.h
Normal file
105
src/pv/pvdbcrProcessRecord.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* 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 2021.04.11
|
||||
*/
|
||||
#ifndef PVDBCRPROCESSARRAY_H
|
||||
#define PVDBCRPROCESSARRAY_H
|
||||
#include <epicsThread.h>
|
||||
#include <epicsGuard.h>
|
||||
#include <pv/event.h>
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvSupport.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
typedef std::tr1::shared_ptr<epicsThread> EpicsThreadPtr;
|
||||
class PvdbcrProcessRecord;
|
||||
typedef std::tr1::shared_ptr<PvdbcrProcessRecord> PvdbcrProcessRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief PvdbcrProcessRecord A record that processes other records in the master database.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvdbcrProcessRecord :
|
||||
public PVRecord,
|
||||
public epicsThreadRunable
|
||||
{
|
||||
private:
|
||||
PvdbcrProcessRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
double delay,
|
||||
int asLevel,std::string const & asGroup);
|
||||
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;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvdbcrProcessRecord);
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
virtual ~PvdbcrProcessRecord() {}
|
||||
/**
|
||||
* @brief Create a record.
|
||||
*
|
||||
* @param recordName The record name.
|
||||
* @param asLevel The access security level.
|
||||
* @param asGroup The access security group.
|
||||
* @return The PVRecord
|
||||
*/
|
||||
static PvdbcrProcessRecordPtr create(
|
||||
std::string const & recordName,
|
||||
double delay= 1.0,
|
||||
int asLevel=0,std::string const & asGroup = std::string("DEFAULT"));
|
||||
/**
|
||||
* @brief set the delay between prcocessing.
|
||||
*
|
||||
* @param delay in seconds
|
||||
*/
|
||||
void setDelay(double delay);
|
||||
/**
|
||||
* @brief get the delay between prcocessing.
|
||||
*
|
||||
* @return delay in seconds
|
||||
*/
|
||||
double getDelay();
|
||||
/**
|
||||
* @brief a PVRecord method
|
||||
* @return success or failure
|
||||
*/
|
||||
virtual bool init();
|
||||
/**
|
||||
* @brief method that processes other records in the master database.
|
||||
*/
|
||||
virtual void process();
|
||||
/**
|
||||
* @brief thread method
|
||||
*/
|
||||
virtual void run();
|
||||
/**
|
||||
* @brief thread method
|
||||
*/
|
||||
void startThread();
|
||||
/**
|
||||
* @brief thread method
|
||||
*/
|
||||
void stop();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVDBCRPROCESSARRAY_H */
|
||||
67
src/pv/pvdbcrRemoveRecord.h
Normal file
67
src/pv/pvdbcrRemoveRecord.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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 2021.04.11
|
||||
*/
|
||||
#ifndef PVDBCRREMOVEARRAY_H
|
||||
#define PVDBCRREMOVEARRAY_H
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvSupport.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PvdbcrRemoveRecord;
|
||||
typedef std::tr1::shared_ptr<PvdbcrRemoveRecord> PvdbcrRemoveRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief PvdbcrRemoveRecord A record that removes a record from the master database.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvdbcrRemoveRecord :
|
||||
public PVRecord
|
||||
{
|
||||
private:
|
||||
PvdbcrRemoveRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup);
|
||||
epics::pvData::PVStringPtr pvRecordName;
|
||||
epics::pvData::PVStringPtr pvResult;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvdbcrRemoveRecord);
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
virtual ~PvdbcrRemoveRecord() {}
|
||||
/**
|
||||
* @brief Create a record.
|
||||
*
|
||||
* @param recordName The record name.
|
||||
* @param asLevel The access security level.
|
||||
* @param asGroup The access security group.
|
||||
* @return The PVRecord
|
||||
*/
|
||||
static PvdbcrRemoveRecordPtr create(
|
||||
std::string const & recordName,
|
||||
int asLevel=0,std::string const & asGroup = std::string("DEFAULT"));
|
||||
/**
|
||||
* @brief a PVRecord method
|
||||
* @return success or failure
|
||||
*/
|
||||
virtual bool init();
|
||||
/**
|
||||
* @brief process method that removes a record from the master database.
|
||||
*/
|
||||
virtual void process();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVDBCRREMOVEARRAY_H */
|
||||
57
src/pv/pvdbcrScalarArrayRecord.h
Normal file
57
src/pv/pvdbcrScalarArrayRecord.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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 2021.04.11
|
||||
*/
|
||||
#ifndef PVDBCRSCALARARRAYRECORD_H
|
||||
#define PVDBCRSCALARARRAYRECORD_H
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvSupport.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PvdbcrScalarArrayRecord;
|
||||
typedef std::tr1::shared_ptr<PvdbcrScalarArrayRecord> PvdbcrScalarArrayRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief PvdbcrScalarArrayRecord creates a record with a scalar array value, alarm, and timeStamp.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvdbcrScalarArrayRecord :
|
||||
public PVRecord
|
||||
{
|
||||
private:
|
||||
PvdbcrScalarArrayRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup);
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvdbcrScalarArrayRecord);
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
virtual ~PvdbcrScalarArrayRecord() {}
|
||||
/**
|
||||
* @brief Create a record.
|
||||
*
|
||||
* @param recordName The record name.
|
||||
* @param scalarType The type for the value field
|
||||
* @param asLevel The access security level.
|
||||
* @param asGroup The access security group.
|
||||
* @return The PVRecord
|
||||
*/
|
||||
static PvdbcrScalarArrayRecordPtr create(
|
||||
std::string const & recordName,std::string const & scalarType,
|
||||
int asLevel=0,std::string const & asGroup = std::string("DEFAULT"));
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVDBCRSCALARARRAYRECORD_H */
|
||||
57
src/pv/pvdbcrScalarRecord.h
Normal file
57
src/pv/pvdbcrScalarRecord.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* 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 2021.04.11
|
||||
*/
|
||||
#ifndef PVDBCRSCALARRECORD_H
|
||||
#define PVDBCRSCALARRECORD_H
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvSupport.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PvdbcrScalarRecord;
|
||||
typedef std::tr1::shared_ptr<PvdbcrScalarRecord> PvdbcrScalarRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief PvdbcrScalarRecord creates a record with a scalar value, alarm, and timeStamp.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvdbcrScalarRecord :
|
||||
public PVRecord
|
||||
{
|
||||
private:
|
||||
PvdbcrScalarRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup);
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvdbcrScalarRecord);
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
virtual ~PvdbcrScalarRecord() {}
|
||||
/**
|
||||
* @brief Create a record.
|
||||
*
|
||||
* @param recordName The record name.
|
||||
* @param scalarType The type for the value field
|
||||
* @param asLevel The access security level.
|
||||
* @param asGroup The access security group.
|
||||
* @return The PVRecord
|
||||
*/
|
||||
static PvdbcrScalarRecordPtr create(
|
||||
std::string const & recordName,std::string const & scalarType,
|
||||
int asLevel=0,std::string const & asGroup = std::string("DEFAULT"));
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVDBCRSCALARRECORD_H */
|
||||
68
src/pv/pvdbcrTraceRecord.h
Normal file
68
src/pv/pvdbcrTraceRecord.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* 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 2021.04.11
|
||||
*/
|
||||
#ifndef PVDBCRTRACEARRAY_H
|
||||
#define PVDBCRTRACEARRAY_H
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/pvSupport.h>
|
||||
#include <pv/pvStructureCopy.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PvdbcrTraceRecord;
|
||||
typedef std::tr1::shared_ptr<PvdbcrTraceRecord> PvdbcrTraceRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief PvdbcrTraceRecord A record sets trace level for a record in the master database.
|
||||
*
|
||||
*/
|
||||
class epicsShareClass PvdbcrTraceRecord :
|
||||
public PVRecord
|
||||
{
|
||||
private:
|
||||
PvdbcrTraceRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup);
|
||||
epics::pvData::PVStringPtr pvRecordName;
|
||||
epics::pvData::PVIntPtr pvLevel;
|
||||
epics::pvData::PVStringPtr pvResult;
|
||||
public:
|
||||
POINTER_DEFINITIONS(PvdbcrTraceRecord);
|
||||
/**
|
||||
* The Destructor.
|
||||
*/
|
||||
virtual ~PvdbcrTraceRecord() {}
|
||||
/**
|
||||
* @brief Create a record.
|
||||
*
|
||||
* @param recordName The record name.
|
||||
* @param asLevel The access security level.
|
||||
* @param asGroup The access security group.
|
||||
* @return The PVRecord
|
||||
*/
|
||||
static PvdbcrTraceRecordPtr create(
|
||||
std::string const & recordName,
|
||||
int asLevel=0,std::string const & asGroup = std::string("DEFAULT"));
|
||||
/**
|
||||
* @brief a PVRecord method
|
||||
* @return success or failure
|
||||
*/
|
||||
virtual bool init();
|
||||
/**
|
||||
* @brief process method that sets trace level for a record in the master database.
|
||||
*/
|
||||
virtual void process();
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVDBCRTRACEARRAY_H */
|
||||
@@ -1,63 +0,0 @@
|
||||
/* removeRecord.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 REMOVERECORD_H
|
||||
#define REMOVERECORD_H
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
|
||||
class RemoveRecord;
|
||||
typedef std::tr1::shared_ptr<RemoveRecord> RemoveRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief Remove another record in the same database.
|
||||
*
|
||||
* A record to remove 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 RemoveRecord :
|
||||
public PVRecord
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(RemoveRecord);
|
||||
/**
|
||||
* Factory methods to create RemoveRecord.
|
||||
* @param recordName The name for the RemoveRecord.
|
||||
* @return A shared pointer to RemoveRecord..
|
||||
*/
|
||||
static RemoveRecordPtr create(
|
||||
std::string const & recordName);
|
||||
/**
|
||||
* standard init method required by PVRecord
|
||||
* @return true unless record name already exists.
|
||||
*/
|
||||
virtual bool init();
|
||||
/**
|
||||
* @brief Remove the record specified by recordName.
|
||||
*/
|
||||
virtual void process();
|
||||
private:
|
||||
RemoveRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
epics::pvData::PVStringPtr pvRecordName;
|
||||
epics::pvData::PVStringPtr pvResult;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* REMOVERECORD_H */
|
||||
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 */
|
||||
@@ -1,65 +0,0 @@
|
||||
/* traceRecord.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 TRACERECORD_H
|
||||
#define TRACERECORD_H
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
|
||||
class TraceRecord;
|
||||
typedef std::tr1::shared_ptr<TraceRecord> TraceRecordPtr;
|
||||
|
||||
/**
|
||||
* @brief Trace activity of PVRecord.
|
||||
*
|
||||
* A record to set the trace value for another record
|
||||
* It is meant to be used via a channelPutGet request.
|
||||
* The argument has two fields: recordName and level.
|
||||
* The result has a field named status.
|
||||
*/
|
||||
class epicsShareClass TraceRecord :
|
||||
public PVRecord
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(TraceRecord);
|
||||
/**
|
||||
* @brief Factory method to create TraceRecord.
|
||||
*
|
||||
* @param recordName The name for the TraceRecord.
|
||||
* @return A shared pointer to TraceRecord..
|
||||
*/
|
||||
static TraceRecordPtr create(
|
||||
std::string const & recordName);
|
||||
/**
|
||||
* standard init method required by PVRecord
|
||||
* @return true unless record name already exists.
|
||||
*/
|
||||
virtual bool init();
|
||||
/**
|
||||
* @brief Set the trace level for record specified by recordName.
|
||||
*/
|
||||
virtual void process();
|
||||
private:
|
||||
TraceRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
epics::pvData::PVStringPtr pvRecordName;
|
||||
epics::pvData::PVIntPtr pvLevel;
|
||||
epics::pvData::PVStringPtr pvResult;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* TRACERECORD_H */
|
||||
@@ -10,15 +10,27 @@
|
||||
*/
|
||||
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include <asLib.h>
|
||||
#include <epicsGuard.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/createRequest.h>
|
||||
#include <pv/pvaVersion.h>
|
||||
#include <pv/pvaVersionNum.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
#include <pv/security.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include "pv/pvStructureCopy.h"
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/channelProviderLocal.h"
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
@@ -29,7 +41,7 @@ using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
static StructureConstPtr nullStructure;
|
||||
|
||||
@@ -59,19 +71,18 @@ static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
|
||||
return pvString->get().compare("true")==0 ? true : false;
|
||||
} else if(scalar->getScalarType()==pvBoolean) {
|
||||
PVBooleanPtr pvBoolean = static_pointer_cast<PVBoolean>(pvField);
|
||||
return pvBoolean->get();
|
||||
return pvBoolean->get();
|
||||
}
|
||||
return processDefault;
|
||||
}
|
||||
|
||||
class ChannelProcessLocal :
|
||||
public ChannelProcess,
|
||||
public epics::pvAccess::ChannelProcess,
|
||||
public std::tr1::enable_shared_from_this<ChannelProcessLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelProcessLocal);
|
||||
virtual ~ChannelProcessLocal();
|
||||
virtual void destroy() {} // DEPRECATED
|
||||
static ChannelProcessLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
@@ -93,7 +104,7 @@ private:
|
||||
ChannelProcessRequester::shared_pointer const & channelProcessRequester,
|
||||
PVRecordPtr const &pvRecord,
|
||||
int nProcess)
|
||||
:
|
||||
:
|
||||
channelLocal(channelLocal),
|
||||
channelProcessRequester(channelProcessRequester),
|
||||
pvRecord(pvRecord),
|
||||
@@ -123,7 +134,7 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
|
||||
if(pvField) {
|
||||
PVStringPtr pvString = pvOptions->getSubField<PVString>("nProcess");
|
||||
if(pvString) {
|
||||
int size;
|
||||
int size=0;
|
||||
std::stringstream ss;
|
||||
ss << pvString->get();
|
||||
ss >> size;
|
||||
@@ -147,10 +158,7 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
|
||||
|
||||
ChannelProcessLocal::~ChannelProcessLocal()
|
||||
{
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(pvr && pvr->getTraceLevel()>0) {
|
||||
cout << "~ChannelProcessLocal() " << pvr->getRecordName() << endl;
|
||||
}
|
||||
//cout << "~ChannelProcessLocal()\n";
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel()
|
||||
@@ -198,13 +206,12 @@ void ChannelProcessLocal::process()
|
||||
}
|
||||
|
||||
class ChannelGetLocal :
|
||||
public ChannelGet,
|
||||
public epics::pvAccess::ChannelGet,
|
||||
public std::tr1::enable_shared_from_this<ChannelGetLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelGetLocal);
|
||||
virtual ~ChannelGetLocal();
|
||||
virtual void destroy() {} // DEPRECATED
|
||||
static ChannelGetLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelGetRequester::shared_pointer const & channelGetRequester,
|
||||
@@ -229,7 +236,7 @@ private:
|
||||
PVStructurePtr const&pvStructure,
|
||||
BitSetPtr const & bitSet,
|
||||
PVRecordPtr const &pvRecord)
|
||||
:
|
||||
:
|
||||
firstTime(true),
|
||||
callProcess(callProcess),
|
||||
channelLocal(channelLocal),
|
||||
@@ -295,10 +302,7 @@ ChannelGetLocalPtr ChannelGetLocal::create(
|
||||
|
||||
ChannelGetLocal::~ChannelGetLocal()
|
||||
{
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(pvr && pvr->getTraceLevel()>0) {
|
||||
cout << "~ChannelGetLocal() " << pvr->getRecordName() << endl;
|
||||
}
|
||||
//cout << "~ChannelGetLocal()\n";
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel()
|
||||
@@ -325,6 +329,13 @@ void ChannelGetLocal::get()
|
||||
{
|
||||
ChannelGetRequester::shared_pointer requester = channelGetRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelGet::get is not allowed");
|
||||
requester->getDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@@ -372,13 +383,12 @@ void ChannelGetLocal::get()
|
||||
}
|
||||
|
||||
class ChannelPutLocal :
|
||||
public ChannelPut,
|
||||
public epics::pvAccess::ChannelPut,
|
||||
public std::tr1::enable_shared_from_this<ChannelPutLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPutLocal);
|
||||
virtual ~ChannelPutLocal();
|
||||
virtual void destroy() {} // DEPRECATED
|
||||
static ChannelPutLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutRequester::shared_pointer const & channelPutRequester,
|
||||
@@ -460,10 +470,7 @@ ChannelPutLocalPtr ChannelPutLocal::create(
|
||||
|
||||
ChannelPutLocal::~ChannelPutLocal()
|
||||
{
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(pvr && pvr->getTraceLevel()>0) {
|
||||
cout << "~ChannelPutLocal() " << pvr->getRecordName() << endl;
|
||||
}
|
||||
//cout << "~ChannelPutLocal()\n";
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel()
|
||||
@@ -490,6 +497,13 @@ void ChannelPutLocal::get()
|
||||
{
|
||||
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelPut::get is not allowed");
|
||||
requester->getDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@@ -520,10 +534,18 @@ void ChannelPutLocal::put(
|
||||
{
|
||||
ChannelPutRequester::shared_pointer requester = channelPutRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canWrite()) {
|
||||
Status status = Status::error("ChannelPut::put is not allowed");
|
||||
requester->putDone(status,getPtrSelf());
|
||||
return;
|
||||
}
|
||||
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
{
|
||||
{
|
||||
epicsGuard <PVRecord> guard(*pvr);
|
||||
pvr->beginGroupPut();
|
||||
pvCopy->updateMaster(pvStructure, bitSet);
|
||||
@@ -534,7 +556,7 @@ void ChannelPutLocal::put(
|
||||
}
|
||||
requester->putDone(Status::Ok,getPtrSelf());
|
||||
if(pvr->getTraceLevel()>1)
|
||||
{
|
||||
{
|
||||
cout << "ChannelPutLocal::put" << endl;
|
||||
}
|
||||
} catch(std::exception& ex) {
|
||||
@@ -545,13 +567,12 @@ void ChannelPutLocal::put(
|
||||
|
||||
|
||||
class ChannelPutGetLocal :
|
||||
public ChannelPutGet,
|
||||
public epics::pvAccess::ChannelPutGet,
|
||||
public std::tr1::enable_shared_from_this<ChannelPutGetLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPutGetLocal);
|
||||
virtual ~ChannelPutGetLocal();
|
||||
virtual void destroy() {} // DEPRECATED
|
||||
static ChannelPutGetLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelPutGetRequester::shared_pointer const & channelPutGetRequester,
|
||||
@@ -581,7 +602,7 @@ private:
|
||||
PVStructurePtr const&pvGetStructure,
|
||||
BitSetPtr const & getBitSet,
|
||||
PVRecordPtr const &pvRecord)
|
||||
:
|
||||
:
|
||||
callProcess(callProcess),
|
||||
channelLocal(channelLocal),
|
||||
channelPutGetRequester(channelPutGetRequester),
|
||||
@@ -653,10 +674,7 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
|
||||
|
||||
ChannelPutGetLocal::~ChannelPutGetLocal()
|
||||
{
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(pvr && pvr->getTraceLevel()>0) {
|
||||
cout << "~ChannelPutGetLocal() " << pvr->getRecordName() << endl;
|
||||
}
|
||||
//cout << "~ChannelPutGetLocal()\n";
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel()
|
||||
@@ -684,6 +702,13 @@ void ChannelPutGetLocal::putGet(
|
||||
{
|
||||
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canWrite()||!channel->canRead() ) {
|
||||
Status status = Status::error("ChannelPutGet::putGet is not allowed");
|
||||
requester->putGetDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@@ -712,6 +737,13 @@ void ChannelPutGetLocal::getPut()
|
||||
{
|
||||
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelPutGet::getPut is not allowed");
|
||||
requester->getPutDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@@ -739,6 +771,13 @@ void ChannelPutGetLocal::getGet()
|
||||
{
|
||||
ChannelPutGetRequester::shared_pointer requester = channelPutGetRequester.lock();
|
||||
if(!requester) return;
|
||||
ChannelLocalPtr channel(channelLocal.lock());
|
||||
if(!channel) throw std::logic_error("channel is deleted");
|
||||
if(!channel->canRead()) {
|
||||
Status status = Status::error("ChannelPutGet::getGet is not allowed");
|
||||
requester->getPutDone(status,getPtrSelf(),PVStructurePtr(),BitSetPtr());
|
||||
return;
|
||||
}
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) throw std::logic_error("pvRecord is deleted");
|
||||
try {
|
||||
@@ -763,13 +802,12 @@ void ChannelPutGetLocal::getGet()
|
||||
|
||||
|
||||
class ChannelRPCLocal :
|
||||
public ChannelRPC,
|
||||
public RPCResponseCallback,
|
||||
public epics::pvAccess::ChannelRPC,
|
||||
public epics::pvAccess::RPCResponseCallback,
|
||||
public std::tr1::enable_shared_from_this<ChannelRPCLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelRPCLocal);
|
||||
virtual void destroy() {} // DEPRECATED
|
||||
static ChannelRPCLocalPtr create(
|
||||
ChannelLocalPtr const & channelLocal,
|
||||
ChannelRPCRequester::shared_pointer const & channelRPCRequester,
|
||||
@@ -853,10 +891,7 @@ ChannelRPCLocalPtr ChannelRPCLocal::create(
|
||||
|
||||
ChannelRPCLocal::~ChannelRPCLocal()
|
||||
{
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(pvr && pvr->getTraceLevel()>0) {
|
||||
cout << "~ChannelRPCLocal() " << pvr->getRecordName() << endl;
|
||||
}
|
||||
//cout << "~ChannelRPCLocal()\n";
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel()
|
||||
@@ -877,7 +912,7 @@ void ChannelRPCLocal::processRequest(
|
||||
{
|
||||
result = service->request(pvArgument);
|
||||
}
|
||||
catch (RPCRequestException& rre)
|
||||
catch (epics::pvAccess::RPCRequestException& rre)
|
||||
{
|
||||
status = Status(rre.getStatus(), rre.what());
|
||||
ok = false;
|
||||
@@ -893,7 +928,7 @@ void ChannelRPCLocal::processRequest(
|
||||
status = Status(Status::STATUSTYPE_FATAL, "Unexpected exception caught while calling RPCService.request(PVStructure).");
|
||||
ok = false;
|
||||
}
|
||||
|
||||
|
||||
// check null result
|
||||
if (ok && !result)
|
||||
{
|
||||
@@ -958,13 +993,12 @@ void ChannelRPCLocal::request(PVStructurePtr const & pvArgument)
|
||||
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
|
||||
|
||||
class ChannelArrayLocal :
|
||||
public ChannelArray,
|
||||
public epics::pvAccess::ChannelArray,
|
||||
public std::tr1::enable_shared_from_this<ChannelArrayLocal>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelArrayLocal);
|
||||
virtual ~ChannelArrayLocal();
|
||||
virtual void destroy() {} // DEPRECATED
|
||||
static ChannelArrayLocalPtr create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelArrayRequester::shared_pointer const & channelArrayRequester,
|
||||
@@ -992,7 +1026,7 @@ private:
|
||||
PVArrayPtr const &pvArray,
|
||||
PVArrayPtr const &pvCopy,
|
||||
PVRecordPtr const &pvRecord)
|
||||
:
|
||||
:
|
||||
channelLocal(channelLocal),
|
||||
channelArrayRequester(channelArrayRequester),
|
||||
pvArray(pvArray),
|
||||
@@ -1095,10 +1129,7 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
|
||||
|
||||
ChannelArrayLocal::~ChannelArrayLocal()
|
||||
{
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(pvr && pvr->getTraceLevel()>0) {
|
||||
cout << "~ChannelArrayLocal() " << pvr->getRecordName() << endl;
|
||||
}
|
||||
//cout << "~ChannelArrayLocal()\n";
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel()
|
||||
@@ -1237,10 +1268,16 @@ ChannelLocal::ChannelLocal(
|
||||
ChannelProviderLocalPtr const & provider,
|
||||
ChannelRequester::shared_pointer const & requester,
|
||||
PVRecordPtr const & pvRecord)
|
||||
:
|
||||
:
|
||||
requester(requester),
|
||||
provider(provider),
|
||||
pvRecord(pvRecord)
|
||||
pvRecord(pvRecord),
|
||||
asLevel(pvRecord->getAsLevel()),
|
||||
asGroup(getAsGroup(pvRecord)),
|
||||
asUser(getAsUser(requester)),
|
||||
asHost(getAsHost(requester)),
|
||||
asMemberPvt(0),
|
||||
asClientPvt(0)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0) {
|
||||
cout << "ChannelLocal::ChannelLocal()"
|
||||
@@ -1248,15 +1285,91 @@ ChannelLocal::ChannelLocal(
|
||||
<< " requester exists " << (requester ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
if (pvRecord->getAsGroup().empty() || asAddMember(&asMemberPvt, &asGroup[0]) != 0) {
|
||||
asMemberPvt = 0;
|
||||
}
|
||||
if (asMemberPvt) {
|
||||
asAddClient(&asClientPvt, asMemberPvt, asLevel, &asUser[0], &asHost[0]);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<char> ChannelLocal::toCharArray(const std::string& s)
|
||||
{
|
||||
std::vector<char> v(s.begin(), s.end());
|
||||
v.push_back('\0');
|
||||
return v;
|
||||
}
|
||||
|
||||
std::vector<char> ChannelLocal::getAsGroup(const PVRecordPtr& pvRecord)
|
||||
{
|
||||
return toCharArray(pvRecord->getAsGroup());
|
||||
}
|
||||
|
||||
std::vector<char> ChannelLocal::getAsUser(const ChannelRequester::shared_pointer& requester)
|
||||
{
|
||||
PeerInfo::const_shared_pointer info(requester->getPeerInfo());
|
||||
std::string user;
|
||||
if(info && info->identified) {
|
||||
if(info->authority=="ca") {
|
||||
user = info->account;
|
||||
size_t first = user.find_last_of('/');
|
||||
if(first != std::string::npos) {
|
||||
// prevent CA accounts like "<authority>/<user>"
|
||||
user = user.substr(first+1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
user = info->authority + "/" + info->account;
|
||||
}
|
||||
}
|
||||
return toCharArray(user);
|
||||
}
|
||||
|
||||
std::vector<char> ChannelLocal::getAsHost(const epics::pvAccess::ChannelRequester::shared_pointer& requester)
|
||||
{
|
||||
PeerInfo::const_shared_pointer info(requester->getPeerInfo());
|
||||
std::string host;
|
||||
if(info && info->identified) {
|
||||
host= info->peer;
|
||||
}
|
||||
else {
|
||||
// anonymous
|
||||
host = requester->getRequesterName();
|
||||
}
|
||||
|
||||
// handle form "ip:port"
|
||||
size_t last = host.find_first_of(':');
|
||||
if(last == std::string::npos) {
|
||||
last = host.size();
|
||||
}
|
||||
host.resize(last);
|
||||
return toCharArray(host);
|
||||
}
|
||||
|
||||
bool ChannelLocal::canWrite()
|
||||
{
|
||||
if(!asActive || (asClientPvt && asCheckPut(asClientPvt))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ChannelLocal::canRead()
|
||||
{
|
||||
if(!asActive || (asClientPvt && asCheckGet(asClientPvt))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
ChannelLocal::~ChannelLocal()
|
||||
{
|
||||
PVRecordPtr pvr(pvRecord.lock());
|
||||
if(!pvr) return;
|
||||
if(pvr->getTraceLevel()>0)
|
||||
{
|
||||
cout << "~ChannelLocal()" << endl;
|
||||
if(asMemberPvt) {
|
||||
asRemoveMember(&asMemberPvt);
|
||||
asMemberPvt = 0;
|
||||
}
|
||||
if(asClientPvt) {
|
||||
asRemoveClient(&asClientPvt);
|
||||
asClientPvt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1287,7 +1400,7 @@ string ChannelLocal::getRequesterName()
|
||||
<< " requester exists " << (requester ? "true" : "false")
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
if(!requester) return string();
|
||||
return requester->getRequesterName();
|
||||
}
|
||||
@@ -1310,7 +1423,7 @@ void ChannelLocal::message(
|
||||
string recordName("record deleted");
|
||||
if(pvr) recordName = pvr->getRecordName();
|
||||
cout << recordName
|
||||
<< " message " << message
|
||||
<< " message " << message
|
||||
<< " messageType " << getMessageTypeName(messageType)
|
||||
<< endl;
|
||||
}
|
||||
@@ -1353,8 +1466,8 @@ void ChannelLocal::getField(GetFieldRequester::shared_pointer const &requester,
|
||||
pvr->getPVRecordStructure()->getPVStructure()->getStructure();
|
||||
requester->getDone(Status::Ok,structure);
|
||||
return;
|
||||
}
|
||||
PVFieldPtr pvField =
|
||||
}
|
||||
PVFieldPtr pvField =
|
||||
pvr->getPVRecordStructure()->getPVStructure()->getSubField(subField);
|
||||
if(pvField) {
|
||||
requester->getDone(Status::Ok,pvField->getField());
|
||||
@@ -1470,7 +1583,7 @@ ChannelRPC::shared_pointer ChannelLocal::createChannelRPC(
|
||||
<< endl;
|
||||
}
|
||||
|
||||
ChannelRPCLocalPtr channelRPC =
|
||||
ChannelRPCLocalPtr channelRPC =
|
||||
ChannelRPCLocal::create(
|
||||
getPtrSelf(),
|
||||
channelRPCRequester,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* channelChannelProviderLocal.cpp */
|
||||
/* channelProviderLocal.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
@@ -10,13 +10,17 @@
|
||||
*/
|
||||
|
||||
#include <epicsThread.h>
|
||||
|
||||
#include <asLib.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/syncChannelFind.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/rpcService.h>
|
||||
#include <pv/timeStamp.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include "pv/pvStructureCopy.h"
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/channelProviderLocal.h"
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
@@ -27,13 +31,13 @@ using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
static string providerName("local");
|
||||
static ChannelProviderLocalPtr channelProvider;
|
||||
|
||||
class LocalChannelProviderFactory : public ChannelProviderFactory
|
||||
{
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(LocalChannelProviderFactory);
|
||||
virtual string getFactoryName() { return providerName;}
|
||||
@@ -111,7 +115,7 @@ ChannelFind::shared_pointer ChannelProviderLocal::channelFind(
|
||||
Status::Ok,
|
||||
shared_from_this(),
|
||||
true);
|
||||
|
||||
|
||||
} else {
|
||||
Status notFoundStatus(Status::STATUSTYPE_ERROR,"pv not found");
|
||||
channelFindRequester->channelFindResult(
|
||||
@@ -173,4 +177,18 @@ Channel::shared_pointer ChannelProviderLocal::createChannel(
|
||||
return createChannel(channelName, channelRequester, priority);
|
||||
}
|
||||
|
||||
void ChannelProviderLocal::initAs(const std::string& filePath, const std::string& substitutions)
|
||||
{
|
||||
int status = asInitFile(filePath.c_str(), substitutions.c_str());
|
||||
if(status) {
|
||||
throw std::runtime_error("Invalid AS configuration.");
|
||||
}
|
||||
}
|
||||
|
||||
bool ChannelProviderLocal::isAsActive()
|
||||
{
|
||||
return asActive;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -14,11 +14,17 @@
|
||||
#include <epicsGuard.h>
|
||||
#include <pv/thread.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>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include "pv/pvStructureCopy.h"
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/channelProviderLocal.h"
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
@@ -28,7 +34,7 @@ using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class MonitorLocal;
|
||||
typedef std::tr1::shared_ptr<MonitorLocal> MonitorLocalPtr;
|
||||
@@ -82,7 +88,7 @@ public:
|
||||
nextGetUsed = 0;
|
||||
nextReleaseUsed = 0;
|
||||
}
|
||||
|
||||
|
||||
MonitorElementPtr getFree()
|
||||
{
|
||||
if(numberFree==0) return MonitorElementPtr();
|
||||
@@ -92,7 +98,7 @@ public:
|
||||
if(nextGetFree>=size) nextGetFree = 0;
|
||||
return elements[ind];
|
||||
}
|
||||
|
||||
|
||||
void setUsed(MonitorElementPtr const &element)
|
||||
{
|
||||
if(element!=elements[nextSetUsed++]) {
|
||||
@@ -101,7 +107,7 @@ public:
|
||||
numberUsed++;
|
||||
if(nextSetUsed>=size) nextSetUsed = 0;
|
||||
}
|
||||
|
||||
|
||||
MonitorElementPtr getUsed()
|
||||
{
|
||||
if(numberUsed==0) return MonitorElementPtr();
|
||||
@@ -125,7 +131,7 @@ public:
|
||||
|
||||
typedef std::tr1::shared_ptr<MonitorRequester> MonitorRequesterPtr;
|
||||
|
||||
|
||||
|
||||
class MonitorLocal :
|
||||
public Monitor,
|
||||
public PVListener,
|
||||
@@ -135,7 +141,6 @@ class MonitorLocal :
|
||||
public:
|
||||
POINTER_DEFINITIONS(MonitorLocal);
|
||||
virtual ~MonitorLocal();
|
||||
virtual void destroy() {} // DEPRECATED
|
||||
virtual Status start();
|
||||
virtual Status stop();
|
||||
virtual MonitorElementPtr poll();
|
||||
@@ -185,10 +190,7 @@ MonitorLocal::MonitorLocal(
|
||||
|
||||
MonitorLocal::~MonitorLocal()
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>0)
|
||||
{
|
||||
cout << "MonitorLocal::~MonitorLocal()" << endl;
|
||||
}
|
||||
//cout << "MonitorLocal::~MonitorLocal()" << endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -288,7 +290,7 @@ void MonitorLocal::dataPut(PVRecordFieldPtr const & pvRecordField)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>1)
|
||||
{
|
||||
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl;
|
||||
cout << "MonitorLocal::dataPut(pvRecordField)" << endl;
|
||||
}
|
||||
if(state!=active) return;
|
||||
{
|
||||
@@ -313,7 +315,7 @@ void MonitorLocal::dataPut(
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>1)
|
||||
{
|
||||
cout << "PVCopyMonitor::dataPut(requested,pvRecordField)" << endl;
|
||||
cout << "MonitorLocal::dataPut(requested,pvRecordField)" << endl;
|
||||
}
|
||||
if(state!=active) return;
|
||||
{
|
||||
@@ -340,7 +342,7 @@ void MonitorLocal::beginGroupPut(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>1)
|
||||
{
|
||||
cout << "PVCopyMonitor::beginGroupPut()" << endl;
|
||||
cout << "MonitorLocal::beginGroupPut()" << endl;
|
||||
}
|
||||
if(state!=active) return;
|
||||
{
|
||||
@@ -354,7 +356,7 @@ void MonitorLocal::endGroupPut(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>1)
|
||||
{
|
||||
cout << "PVCopyMonitor::endGroupPut dataChanged " << dataChanged << endl;
|
||||
cout << "MonitorLocal::endGroupPut dataChanged " << dataChanged << endl;
|
||||
}
|
||||
if(state!=active) return;
|
||||
{
|
||||
@@ -371,7 +373,7 @@ void MonitorLocal::unlisten(PVRecordPtr const & pvRecord)
|
||||
{
|
||||
if(pvRecord->getTraceLevel()>1)
|
||||
{
|
||||
cout << "PVCopyMonitor::unlisten\n";
|
||||
cout << "MonitorLocal::unlisten\n";
|
||||
}
|
||||
{
|
||||
Lock xx(mutex);
|
||||
@@ -381,7 +383,7 @@ void MonitorLocal::unlisten(PVRecordPtr const & pvRecord)
|
||||
if(requester) {
|
||||
if(pvRecord->getTraceLevel()>1)
|
||||
{
|
||||
cout << "PVCopyMonitor::unlisten calling requester->unlisten\n";
|
||||
cout << "MonitorLocal::unlisten calling requester->unlisten\n";
|
||||
}
|
||||
requester->unlisten(getPtrSelf());
|
||||
}
|
||||
|
||||
@@ -11,30 +11,19 @@
|
||||
|
||||
/* 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 <shareLib.h>
|
||||
#include <epicsExit.h>
|
||||
|
||||
#include <pv/pvAccess.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 <pv/channelProviderLocal.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/channelProviderLocal.h"
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
@@ -57,7 +46,6 @@ extern "C" void pvdbl(const iocshArgBuf *args)
|
||||
static void registerChannelProviderLocal(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
cout << "registerChannelProviderLocal firstTime " << (firstTime ? "true" : "false") << endl;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdblFuncDef, pvdbl);
|
||||
|
||||
@@ -2,5 +2,17 @@
|
||||
|
||||
SRC_DIRS += $(PVDATABASE_SRC)/special
|
||||
|
||||
LIBSRCS += traceRecord.cpp
|
||||
LIBSRCS += removeRecord.cpp
|
||||
DBD += pvdbcrScalarRecord.dbd
|
||||
DBD += pvdbcrScalarArrayRecord.dbd
|
||||
DBD += pvdbcrAddRecord.dbd
|
||||
DBD += pvdbcrRemoveRecord.dbd
|
||||
DBD += pvdbcrProcessRecord.dbd
|
||||
DBD += pvdbcrTraceRecord.dbd
|
||||
DBD += pvdbcrAllRecords.dbd
|
||||
|
||||
LIBSRCS += pvdbcrScalarRecord.cpp
|
||||
LIBSRCS += pvdbcrScalarArrayRecord.cpp
|
||||
LIBSRCS += pvdbcrAddRecord.cpp
|
||||
LIBSRCS += pvdbcrRemoveRecord.cpp
|
||||
LIBSRCS += pvdbcrProcessRecord.cpp
|
||||
LIBSRCS += pvdbcrTraceRecord.cpp
|
||||
|
||||
147
src/special/pvdbcrAddRecord.cpp
Normal file
147
src/special/pvdbcrAddRecord.cpp
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2021.04.07
|
||||
*/
|
||||
#include <iocsh.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
// The following must be the last include for code exampleLink uses
|
||||
#include <epicsExport.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/pvdbcrAddRecord.h"
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PvdbcrAddRecordPtr PvdbcrAddRecord::create(
|
||||
std::string const & recordName,
|
||||
int asLevel,std::string const & asGroup)
|
||||
{
|
||||
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);
|
||||
PvdbcrAddRecordPtr pvRecord(
|
||||
new PvdbcrAddRecord(recordName,pvStructure,asLevel,asGroup));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
PvdbcrAddRecord::PvdbcrAddRecord(
|
||||
std::string const & recordName,
|
||||
PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup)
|
||||
: PVRecord(recordName,pvStructure,asLevel,asGroup)
|
||||
{
|
||||
}
|
||||
|
||||
bool PvdbcrAddRecord::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 PvdbcrAddRecord::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 = std::tr1::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");
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
static const iocshArg arg0 = { "recordName", iocshArgString };
|
||||
static const iocshArg arg1 = { "asLevel", iocshArgInt };
|
||||
static const iocshArg arg2 = { "asGroup", iocshArgString };
|
||||
static const iocshArg *args[] = {&arg0,&arg1,&arg2};
|
||||
|
||||
static const iocshFuncDef pvdbcrAddRecordFuncDef = {"pvdbcrAddRecord", 3,args};
|
||||
|
||||
static void pvdbcrAddRecordCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *sval = args[0].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrAddRecord recordName not specified");
|
||||
}
|
||||
string recordName = string(sval);
|
||||
int asLevel = args[1].ival;
|
||||
string asGroup("DEFAULT");
|
||||
sval = args[2].sval;
|
||||
if(sval) {
|
||||
asGroup = string(sval);
|
||||
}
|
||||
epics::pvDatabase::PvdbcrAddRecordPtr record = epics::pvDatabase::PvdbcrAddRecord::create(recordName);
|
||||
record->setAsLevel(asLevel);
|
||||
record->setAsGroup(asGroup);
|
||||
epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
|
||||
bool result = master->addRecord(record);
|
||||
if(!result) cout << "recordname " << recordName << " not added" << endl;
|
||||
}
|
||||
|
||||
static void pvdbcrAddRecord(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdbcrAddRecordFuncDef, pvdbcrAddRecordCallFunc);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(pvdbcrAddRecord);
|
||||
}
|
||||
1
src/special/pvdbcrAddRecord.dbd
Normal file
1
src/special/pvdbcrAddRecord.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("pvdbcrAddRecord")
|
||||
6
src/special/pvdbcrAllRecords.dbd
Normal file
6
src/special/pvdbcrAllRecords.dbd
Normal file
@@ -0,0 +1,6 @@
|
||||
include "pvdbcrAddRecord.dbd"
|
||||
include "pvdbcrRemoveRecord.dbd"
|
||||
include "pvdbcrProcessRecord.dbd"
|
||||
include "pvdbcrTraceRecord.dbd"
|
||||
include "pvdbcrScalarRecord.dbd"
|
||||
include "pvdbcrScalarArrayRecord.dbd"
|
||||
206
src/special/pvdbcrProcessRecord.cpp
Normal file
206
src/special/pvdbcrProcessRecord.cpp
Normal file
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2021.04.07
|
||||
*/
|
||||
#include <epicsThread.h>
|
||||
#include <epicsGuard.h>
|
||||
#include <pv/event.h>
|
||||
#include <pv/lock.h>
|
||||
#include <iocsh.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/pvdbcrProcessRecord.h"
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PvdbcrProcessRecordPtr PvdbcrProcessRecord::create(
|
||||
std::string const & recordName,double delay,
|
||||
int asLevel,std::string const & asGroup)
|
||||
{
|
||||
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);
|
||||
PvdbcrProcessRecordPtr pvRecord(
|
||||
new PvdbcrProcessRecord(recordName,pvStructure,delay,asLevel,asGroup));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
|
||||
PvdbcrProcessRecord::PvdbcrProcessRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure,double delay,
|
||||
int asLevel,std::string const & asGroup)
|
||||
: PVRecord(recordName,pvStructure,asLevel,asGroup),
|
||||
delay(delay),
|
||||
pvDatabase(PVDatabase::getMaster())
|
||||
{
|
||||
}
|
||||
|
||||
bool PvdbcrProcessRecord::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 PvdbcrProcessRecord::setDelay(double delay) {this->delay = delay;}
|
||||
|
||||
double PvdbcrProcessRecord::getDelay() {return delay;}
|
||||
|
||||
void PvdbcrProcessRecord::startThread()
|
||||
{
|
||||
thread = EpicsThreadPtr(new epicsThread(
|
||||
*this,
|
||||
"processRecord",
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
epicsThreadPriorityLow));
|
||||
thread->start();
|
||||
}
|
||||
|
||||
void PvdbcrProcessRecord::stop()
|
||||
{
|
||||
runStop.signal();
|
||||
runReturn.wait();
|
||||
}
|
||||
|
||||
void PvdbcrProcessRecord::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 PvdbcrProcessRecord::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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
static const iocshArg arg0 = { "recordName", iocshArgString };
|
||||
static const iocshArg arg1 = { "delay", iocshArgDouble };
|
||||
static const iocshArg arg2 = { "asLevel", iocshArgInt };
|
||||
static const iocshArg arg3 = { "asGroup", iocshArgString };
|
||||
static const iocshArg *args[] = {&arg0,&arg1,&arg2,&arg3};
|
||||
|
||||
static const iocshFuncDef pvdbcrProcessRecordFuncDef = {"pvdbcrProcessRecord", 4,args};
|
||||
|
||||
static void pvdbcrProcessRecordCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *sval = args[0].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrProcessRecord recordName not specified");
|
||||
}
|
||||
string recordName = string(sval);
|
||||
double delay = args[1].dval;
|
||||
if(delay<0.0) delay = 1.0;
|
||||
int asLevel = args[2].ival;
|
||||
string asGroup("DEFAULT");
|
||||
sval = args[3].sval;
|
||||
if(sval) {
|
||||
asGroup = string(sval);
|
||||
}
|
||||
epics::pvDatabase::PvdbcrProcessRecordPtr record
|
||||
= epics::pvDatabase::PvdbcrProcessRecord::create(recordName,delay);
|
||||
record->setAsLevel(asLevel);
|
||||
record->setAsGroup(asGroup);
|
||||
epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
|
||||
bool result = master->addRecord(record);
|
||||
if(!result) cout << "recordname " << recordName << " not added" << endl;
|
||||
}
|
||||
|
||||
static void pvdbcrProcessRecord(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdbcrProcessRecordFuncDef, pvdbcrProcessRecordCallFunc);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(pvdbcrProcessRecord);
|
||||
}
|
||||
1
src/special/pvdbcrProcessRecord.dbd
Normal file
1
src/special/pvdbcrProcessRecord.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("pvdbcrProcessRecord")
|
||||
123
src/special/pvdbcrRemoveRecord.cpp
Normal file
123
src/special/pvdbcrRemoveRecord.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2021.04.07
|
||||
*/
|
||||
#include <iocsh.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/pvdbcrRemoveRecord.h"
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PvdbcrRemoveRecordPtr PvdbcrRemoveRecord::create(
|
||||
std::string const & recordName,
|
||||
int asLevel,std::string const & asGroup)
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||
addNestedStructure("argument")->
|
||||
add("recordName",pvString)->
|
||||
endNested()->
|
||||
addNestedStructure("result") ->
|
||||
add("status",pvString) ->
|
||||
endNested()->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
PvdbcrRemoveRecordPtr pvRecord(
|
||||
new PvdbcrRemoveRecord(recordName,pvStructure,
|
||||
asLevel,asGroup));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
PvdbcrRemoveRecord::PvdbcrRemoveRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup)
|
||||
: PVRecord(recordName,pvStructure,asLevel,asGroup)
|
||||
{
|
||||
}
|
||||
|
||||
bool PvdbcrRemoveRecord::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 PvdbcrRemoveRecord::process()
|
||||
{
|
||||
string name = pvRecordName->get();
|
||||
PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name);
|
||||
if(!pvRecord) {
|
||||
pvResult->put(name + " not found");
|
||||
return;
|
||||
}
|
||||
pvRecord->remove();
|
||||
pvResult->put("success");
|
||||
}
|
||||
}}
|
||||
|
||||
static const iocshArg arg0 = { "recordName", iocshArgString };
|
||||
static const iocshArg arg1 = { "asLevel", iocshArgInt };
|
||||
static const iocshArg arg2 = { "asGroup", iocshArgString };
|
||||
static const iocshArg *args[] = {&arg0,&arg1,&arg2};
|
||||
|
||||
static const iocshFuncDef pvdbcrRemoveRecordFuncDef = {"pvdbcrRemoveRecord", 3,args};
|
||||
|
||||
static void pvdbcrRemoveRecordCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *sval = args[0].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrRemoveRecord recordName not specified");
|
||||
}
|
||||
string recordName = string(sval);
|
||||
int asLevel = args[1].ival;
|
||||
string asGroup("DEFAULT");
|
||||
sval = args[2].sval;
|
||||
if(sval) {
|
||||
asGroup = string(sval);
|
||||
}
|
||||
epics::pvDatabase::PvdbcrRemoveRecordPtr record = epics::pvDatabase::PvdbcrRemoveRecord::create(recordName);
|
||||
record->setAsLevel(asLevel);
|
||||
record->setAsGroup(asGroup);
|
||||
epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
|
||||
bool result = master->addRecord(record);
|
||||
if(!result) cout << "recordname " << recordName << " not added" << endl;
|
||||
}
|
||||
|
||||
static void pvdbcrRemoveRecord(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdbcrRemoveRecordFuncDef, pvdbcrRemoveRecordCallFunc);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(pvdbcrRemoveRecord);
|
||||
}
|
||||
1
src/special/pvdbcrRemoveRecord.dbd
Normal file
1
src/special/pvdbcrRemoveRecord.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("pvdbcrRemoveRecord")
|
||||
103
src/special/pvdbcrScalarArrayRecord.cpp
Normal file
103
src/special/pvdbcrScalarArrayRecord.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2021.04.07
|
||||
*/
|
||||
#include <iocsh.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
// The following must be the last include for code pvDatabase implements
|
||||
#include <epicsExport.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/pvdbcrScalarArrayRecord.h"
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PvdbcrScalarArrayRecord::PvdbcrScalarArrayRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup)
|
||||
: PVRecord(recordName,pvStructure,asLevel,asGroup)
|
||||
{}
|
||||
|
||||
PvdbcrScalarArrayRecordPtr PvdbcrScalarArrayRecord::create(
|
||||
std::string const & recordName,std::string const & scalarType,
|
||||
int asLevel,std::string const & asGroup)
|
||||
{
|
||||
ScalarType st = epics::pvData::ScalarTypeFunc::getScalarType(scalarType);
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
StandardFieldPtr standardField = getStandardField();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
StructureConstPtr top = fieldCreate->createFieldBuilder()->
|
||||
addArray("value",st) ->
|
||||
add("timeStamp",standardField->timeStamp()) ->
|
||||
add("alarm",standardField->alarm()) ->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(top);
|
||||
PvdbcrScalarArrayRecordPtr pvRecord(new PvdbcrScalarArrayRecord(recordName,pvStructure,asLevel,asGroup));
|
||||
pvRecord->initPVRecord();
|
||||
return pvRecord;
|
||||
};
|
||||
}}
|
||||
|
||||
static const iocshArg arg0 = { "recordName", iocshArgString };
|
||||
static const iocshArg arg1 = { "scalarType", iocshArgString };
|
||||
static const iocshArg arg2 = { "asLevel", iocshArgInt };
|
||||
static const iocshArg arg3 = { "asGroup", iocshArgString };
|
||||
static const iocshArg *args[] = {&arg0,&arg1,&arg2,&arg3};
|
||||
|
||||
static const iocshFuncDef pvdbcrScalarArrayFuncDef = {"pvdbcrScalarArrayRecord", 4,args};
|
||||
|
||||
static void pvdbcrScalarArrayCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *sval = args[0].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrScalarArrayRecord recordName not specified");
|
||||
}
|
||||
string recordName = string(sval);
|
||||
sval = args[1].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrScalarArrayRecord scalarType not specified");
|
||||
}
|
||||
string scalarType = string(sval);
|
||||
int asLevel = args[2].ival;
|
||||
string asGroup("DEFAULT");
|
||||
sval = args[3].sval;
|
||||
if(sval) {
|
||||
asGroup = string(sval);
|
||||
}
|
||||
epics::pvDatabase::PvdbcrScalarArrayRecordPtr record
|
||||
= epics::pvDatabase::PvdbcrScalarArrayRecord::create(recordName,scalarType);
|
||||
epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
|
||||
record->setAsLevel(asLevel);
|
||||
record->setAsGroup(asGroup);
|
||||
bool result = master->addRecord(record);
|
||||
if(!result) cout << "recordname " << recordName << " not added" << endl;
|
||||
}
|
||||
|
||||
static void pvdbcrScalarArrayRecord(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdbcrScalarArrayFuncDef, pvdbcrScalarArrayCallFunc);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(pvdbcrScalarArrayRecord);
|
||||
}
|
||||
1
src/special/pvdbcrScalarArrayRecord.dbd
Normal file
1
src/special/pvdbcrScalarArrayRecord.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("pvdbcrScalarArrayRecord")
|
||||
103
src/special/pvdbcrScalarRecord.cpp
Normal file
103
src/special/pvdbcrScalarRecord.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2021.04.07
|
||||
*/
|
||||
#include <iocsh.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
// The following must be the last include for code pvDatabase implements
|
||||
#include <epicsExport.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/pvdbcrScalarRecord.h"
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PvdbcrScalarRecord::PvdbcrScalarRecord(
|
||||
std::string const & recordName,epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup)
|
||||
: PVRecord(recordName,pvStructure,asLevel,asGroup)
|
||||
{}
|
||||
|
||||
PvdbcrScalarRecordPtr PvdbcrScalarRecord::create(
|
||||
std::string const & recordName,std::string const & scalarType,
|
||||
int asLevel,std::string const & asGroup)
|
||||
{
|
||||
ScalarType st = epics::pvData::ScalarTypeFunc::getScalarType(scalarType);
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
StandardFieldPtr standardField = getStandardField();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
StructureConstPtr top = fieldCreate->createFieldBuilder()->
|
||||
add("value",st) ->
|
||||
add("timeStamp",standardField->timeStamp()) ->
|
||||
add("alarm",standardField->alarm()) ->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(top);
|
||||
PvdbcrScalarRecordPtr pvRecord(new PvdbcrScalarRecord(recordName,pvStructure,asLevel,asGroup));
|
||||
pvRecord->initPVRecord();
|
||||
return pvRecord;
|
||||
};
|
||||
}}
|
||||
|
||||
static const iocshArg arg0 = { "recordName", iocshArgString };
|
||||
static const iocshArg arg1 = { "scalarType", iocshArgString };
|
||||
static const iocshArg arg2 = { "asLevel", iocshArgInt };
|
||||
static const iocshArg arg3 = { "asGroup", iocshArgString };
|
||||
static const iocshArg *args[] = {&arg0,&arg1,&arg2,&arg3};
|
||||
|
||||
static const iocshFuncDef pvdbcrScalarFuncDef = {"pvdbcrScalarRecord", 4,args};
|
||||
|
||||
static void pvdbcrScalarCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *sval = args[0].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrScalarRecord recordName not specified");
|
||||
}
|
||||
string recordName = string(sval);
|
||||
sval = args[1].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrScalarRecord scalarType not specified");
|
||||
}
|
||||
string scalarType = string(sval);
|
||||
int asLevel = args[2].ival;
|
||||
string asGroup("DEFAULT");
|
||||
sval = args[3].sval;
|
||||
if(sval) {
|
||||
asGroup = string(sval);
|
||||
}
|
||||
epics::pvDatabase::PvdbcrScalarRecordPtr record
|
||||
= epics::pvDatabase::PvdbcrScalarRecord::create(recordName,scalarType);
|
||||
epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
|
||||
record->setAsLevel(asLevel);
|
||||
record->setAsGroup(asGroup);
|
||||
bool result = master->addRecord(record);
|
||||
if(!result) cout << "recordname " << recordName << " not added" << endl;
|
||||
}
|
||||
|
||||
static void pvdbcrScalarRecord(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdbcrScalarFuncDef, pvdbcrScalarCallFunc);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(pvdbcrScalarRecord);
|
||||
}
|
||||
1
src/special/pvdbcrScalarRecord.dbd
Normal file
1
src/special/pvdbcrScalarRecord.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("pvdbcrScalarRecord")
|
||||
128
src/special/pvdbcrTraceRecord.cpp
Normal file
128
src/special/pvdbcrTraceRecord.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright information and license terms for this software can be
|
||||
* found in the file LICENSE that is included with the distribution
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2021.04.07
|
||||
*/
|
||||
#include <iocsh.h>
|
||||
#include <pv/standardField.h>
|
||||
#include <pv/standardPVField.h>
|
||||
#include <pv/timeStamp.h>
|
||||
#include <pv/pvTimeStamp.h>
|
||||
#include <pv/alarm.h>
|
||||
#include <pv/pvAlarm.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/rpcService.h>
|
||||
|
||||
// The following must be the last include
|
||||
#include <epicsExport.h>
|
||||
#define epicsExportSharedSymbols
|
||||
#include "pv/pvDatabase.h"
|
||||
#include "pv/pvdbcrTraceRecord.h"
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
PvdbcrTraceRecordPtr PvdbcrTraceRecord::create(
|
||||
std::string const & recordName,
|
||||
int asLevel,std::string const & asGroup)
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||
addNestedStructure("argument")->
|
||||
add("recordName",pvString)->
|
||||
add("level",pvInt)->
|
||||
endNested()->
|
||||
addNestedStructure("result") ->
|
||||
add("status",pvString) ->
|
||||
endNested()->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
PvdbcrTraceRecordPtr pvRecord(
|
||||
new PvdbcrTraceRecord(recordName,pvStructure,asLevel,asGroup));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
PvdbcrTraceRecord::PvdbcrTraceRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure,
|
||||
int asLevel,std::string const & asGroup)
|
||||
: PVRecord(recordName,pvStructure,asLevel,asGroup)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool PvdbcrTraceRecord::init()
|
||||
{
|
||||
initPVRecord();
|
||||
PVStructurePtr pvStructure = getPVStructure();
|
||||
pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
|
||||
if(!pvRecordName) return false;
|
||||
pvLevel = pvStructure->getSubField<PVInt>("argument.level");
|
||||
if(!pvLevel) return false;
|
||||
pvResult = pvStructure->getSubField<PVString>("result.status");
|
||||
if(!pvResult) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PvdbcrTraceRecord::process()
|
||||
{
|
||||
string name = pvRecordName->get();
|
||||
PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name);
|
||||
if(!pvRecord) {
|
||||
pvResult->put(name + " not found");
|
||||
return;
|
||||
}
|
||||
pvRecord->setTraceLevel(pvLevel->get());
|
||||
pvResult->put("success");
|
||||
}
|
||||
}}
|
||||
|
||||
static const iocshArg arg0 = { "recordName", iocshArgString };
|
||||
static const iocshArg arg1 = { "asLevel", iocshArgInt };
|
||||
static const iocshArg arg2 = { "asGroup", iocshArgString };
|
||||
static const iocshArg *args[] = {&arg0,&arg1,&arg2};
|
||||
|
||||
static const iocshFuncDef pvdbcrTraceRecordFuncDef = {"pvdbcrTraceRecord", 3,args};
|
||||
|
||||
static void pvdbcrTraceRecordCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *sval = args[0].sval;
|
||||
if(!sval) {
|
||||
throw std::runtime_error("pvdbcrTraceRecord recordName not specified");
|
||||
}
|
||||
string recordName = string(sval);
|
||||
int asLevel = args[1].ival;
|
||||
string asGroup("DEFAULT");
|
||||
sval = args[2].sval;
|
||||
if(sval) {
|
||||
asGroup = string(sval);
|
||||
}
|
||||
epics::pvDatabase::PvdbcrTraceRecordPtr record
|
||||
= epics::pvDatabase::PvdbcrTraceRecord::create(recordName);
|
||||
record->setAsLevel(asLevel);
|
||||
record->setAsGroup(asGroup);
|
||||
epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
|
||||
bool result = master->addRecord(record);
|
||||
if(!result) cout << "recordname " << recordName << " not added" << endl;
|
||||
}
|
||||
|
||||
static void pvdbcrTraceRecord(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdbcrTraceRecordFuncDef, pvdbcrTraceRecordCallFunc);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
epicsExportRegistrar(pvdbcrTraceRecord);
|
||||
}
|
||||
1
src/special/pvdbcrTraceRecord.dbd
Normal file
1
src/special/pvdbcrTraceRecord.dbd
Normal file
@@ -0,0 +1 @@
|
||||
registrar("pvdbcrTraceRecord")
|
||||
@@ -1,74 +0,0 @@
|
||||
/* removeRecord.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
|
||||
*/
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/removeRecord.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
RemoveRecordPtr RemoveRecord::create(
|
||||
std::string const & recordName)
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||
addNestedStructure("argument")->
|
||||
add("recordName",pvString)->
|
||||
endNested()->
|
||||
addNestedStructure("result") ->
|
||||
add("status",pvString) ->
|
||||
endNested()->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
RemoveRecordPtr pvRecord(
|
||||
new RemoveRecord(recordName,pvStructure));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
RemoveRecord::RemoveRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure)
|
||||
: PVRecord(recordName,pvStructure)
|
||||
{
|
||||
}
|
||||
|
||||
bool RemoveRecord::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 RemoveRecord::process()
|
||||
{
|
||||
string name = pvRecordName->get();
|
||||
PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name);
|
||||
if(!pvRecord) {
|
||||
pvResult->put(name + " not found");
|
||||
return;
|
||||
}
|
||||
pvRecord->destroy();
|
||||
pvResult->put("success");
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
/* traceRecord.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
|
||||
*/
|
||||
#define epicsExportSharedSymbols
|
||||
|
||||
#include <pv/traceRecord.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
TraceRecordPtr TraceRecord::create(
|
||||
std::string const & recordName)
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
|
||||
addNestedStructure("argument")->
|
||||
add("recordName",pvString)->
|
||||
add("level",pvInt)->
|
||||
endNested()->
|
||||
addNestedStructure("result") ->
|
||||
add("status",pvString) ->
|
||||
endNested()->
|
||||
createStructure();
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
|
||||
TraceRecordPtr pvRecord(
|
||||
new TraceRecord(recordName,pvStructure));
|
||||
if(!pvRecord->init()) pvRecord.reset();
|
||||
return pvRecord;
|
||||
}
|
||||
|
||||
TraceRecord::TraceRecord(
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure)
|
||||
: PVRecord(recordName,pvStructure)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool TraceRecord::init()
|
||||
{
|
||||
initPVRecord();
|
||||
PVStructurePtr pvStructure = getPVStructure();
|
||||
pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
|
||||
if(!pvRecordName) return false;
|
||||
pvLevel = pvStructure->getSubField<PVInt>("argument.level");
|
||||
if(!pvLevel) return false;
|
||||
pvResult = pvStructure->getSubField<PVString>("result.status");
|
||||
if(!pvResult) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void TraceRecord::process()
|
||||
{
|
||||
string name = pvRecordName->get();
|
||||
PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name);
|
||||
if(!pvRecord) {
|
||||
pvResult->put(name + " not found");
|
||||
return;
|
||||
}
|
||||
pvRecord->setTraceLevel(pvLevel->get());
|
||||
pvResult->put("success");
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
|
||||
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
|
||||
138
src/support/controlSupport.cpp
Normal file
138
src/support/controlSupport.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
/* 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)
|
||||
{
|
||||
cerr << "ControlSupport IS DEPRECATED\n";
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}}
|
||||
219
src/support/scalarAlarmSupport.cpp
Normal file
219
src/support/scalarAlarmSupport.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
/* 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)
|
||||
{
|
||||
cerr << "ScalarAlarmSupport IS DEPRECATED\n";
|
||||
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,14 +26,14 @@
|
||||
|
||||
#ifdef listenerEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef listenerEpicsExportSharedSymbols
|
||||
# undef listenerEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
//epicsShareFunc epics::pvData::PVStructurePtr createListener();
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
namespace epics { namespace pvDatabase {
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
}
|
||||
virtual void dataPut(PVRecordFieldPtr const & pvRecordField)
|
||||
{
|
||||
cout << "Listener::dataPut record " << recordName
|
||||
cout << "Listener::dataPut record " << recordName
|
||||
<< " pvRecordField " << pvRecordField->getPVField()->getFullName()
|
||||
<< endl;
|
||||
}
|
||||
@@ -67,7 +67,7 @@ public:
|
||||
PVRecordStructurePtr const & requested,
|
||||
PVRecordFieldPtr const & pvRecordField)
|
||||
{
|
||||
cout << "Listener::dataPut record " << recordName
|
||||
cout << "Listener::dataPut record " << recordName
|
||||
<< " requested " << requested->getPVStructure()->getFullName()
|
||||
<< " pvRecordField " << pvRecordField->getPVField()->getFullName()
|
||||
<< endl;
|
||||
@@ -84,7 +84,7 @@ public:
|
||||
{
|
||||
cout << "Listener::unlisten record " << recordName << endl;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
Listener(PVRecordPtr const & pvRecord)
|
||||
: pvCopy(
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
|
||||
#ifdef powerSupplyEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef powerSupplyEpicsExportSharedSymbols
|
||||
# undef powerSupplyEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
//epicsShareFunc epics::pvData::PVStructurePtr createPowerSupply();
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class PowerSupply;
|
||||
typedef std::tr1::shared_ptr<PowerSupply> PowerSupplyPtr;
|
||||
@@ -46,7 +46,6 @@ public:
|
||||
std::string const & recordName,
|
||||
epics::pvData::PVStructurePtr const & pvStructure);
|
||||
virtual ~PowerSupply();
|
||||
virtual void destroy();
|
||||
virtual bool init();
|
||||
virtual void process();
|
||||
void put(double power,double voltage);
|
||||
@@ -111,11 +110,6 @@ inline PowerSupply::~PowerSupply()
|
||||
{
|
||||
}
|
||||
|
||||
inline void PowerSupply::destroy()
|
||||
{
|
||||
PVRecord::destroy();
|
||||
}
|
||||
|
||||
inline bool PowerSupply::init()
|
||||
{
|
||||
initPVRecord();
|
||||
|
||||
@@ -25,12 +25,12 @@
|
||||
|
||||
#ifdef pvRecordClientEpicsExportSharedSymbols
|
||||
# define epicsExportSharedSymbols
|
||||
# undef pvRecordClientEpicsExportSharedSymbols
|
||||
# undef pvRecordClientEpicsExportSharedSymbols
|
||||
#endif
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class RecordClient;
|
||||
typedef std::tr1::shared_ptr<RecordClient> RecordClientPtr;
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
std::cout << "RecordClient::detach record " << pvRecord->getRecordName() << std::endl;
|
||||
this->pvRecord.reset();
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
RecordClient(PVRecordPtr const & pvRecord)
|
||||
: pvRecord(pvRecord)
|
||||
|
||||
@@ -134,4 +134,3 @@ MAIN(testExampleRecord)
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,4 +79,3 @@ MAIN(testLocalProvider)
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,4 +75,3 @@ MAIN(testPVAServer)
|
||||
test();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ static void testPVScalarArray(
|
||||
cout << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void scalarTest()
|
||||
{
|
||||
if(debug) {cout << endl << endl << "****scalarTest****" << endl;}
|
||||
@@ -401,4 +401,3 @@ MAIN(testPVCopy)
|
||||
powerSupplyTest();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -103,4 +103,3 @@ MAIN(testPVRecord)
|
||||
powerSupplyTest();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ static void arrayTest()
|
||||
uint32 nset = 0;
|
||||
size_t n = 10;
|
||||
shared_vector<double> values(n);
|
||||
|
||||
|
||||
PVStructurePtr pvRecordStructure(getStandardPVField()->scalarArray(pvDouble,""));
|
||||
PVRecordPtr pvRecord(PVRecord::create("doubleArrayRecord",pvRecordStructure));
|
||||
PVStructurePtr pvRequest(CreateRequest::create()->createRequest("value[array=1:3]"));
|
||||
@@ -145,6 +145,73 @@ static void arrayTest()
|
||||
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()
|
||||
{
|
||||
if(debug) {cout << endl << endl << "****timeStampTest****" << endl;}
|
||||
@@ -267,12 +334,12 @@ static void ignoreTest()
|
||||
|
||||
MAIN(testPlugin)
|
||||
{
|
||||
testPlan(22);
|
||||
testPlan(26);
|
||||
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
|
||||
deadbandTest();
|
||||
arrayTest();
|
||||
unionArrayTest();
|
||||
timeStampTest();
|
||||
ignoreTest();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user