50 Commits

Author SHA1 Message Date
Andrew Johnson 65d2cce753 Final commit for 4.8.1 2025-12-15 14:50:45 -06:00
Andrew Johnson 7535e469e9 Updates to Release Notes 2025-12-15 14:49:21 -06:00
Ralph Lange b3f64a1392 Merge pull request #77 from ralphlange/remove-ci
Remove dysfunctional Travis-CI configuration
2025-02-22 15:33:12 +01:00
Ralph Lange 6ca99ebb92 Merge pull request #76 from anjohnson/master
Fix 10-year old typo in message generation
2025-02-22 15:32:54 +01:00
Ralph Lange 2dbae03028 Remove dysfunctional Travis-CI configuration 2025-02-21 09:46:00 +01:00
Andrew Johnson 09cf317521 Fix 10-year old typo in message generation 2025-02-20 13:14:40 -06:00
Andrew Johnson 8ed07fef96 Set next development version 2021-07-02 15:42:23 -05:00
Andrew Johnson a34876e36a Update version numbers for release 2021-07-02 15:37:45 -05:00
mrkraimer 7105261c90 change location of css scripts 2021-04-08 08:07:59 -04:00
Marty Kraimer a6f5d86162 Merge pull request #73 from epics-base/multichannelmultiprovider
multiChannel now allows an array of provider names
2021-03-30 10:11:32 -04:00
mrkraimer 9e8cc341ea multiChannel now allows an array of provider names 2021-03-23 12:42:58 -04:00
mrkraimer 6eb977ae66 The following changes were made:
1) pvaClientChannel no longer issues an error message on disconnect.
   This should never have been done.
   When pvaClient is used within a database, it caused error mesaage when database exits.
2) pvaClientGet,Monitor,Process,Put,PutGet now let pvaClientChannel handle getRequesterName and message.
   This leads to better error messages.
2021-03-15 06:48:38 -04:00
mrkraimer 3fb934a30b replace boolean by epics::pvData::boolean 2021-03-06 11:17:18 -05:00
Marty Kraimer 2d6f0f1821 Merge pull request #71 from epics-base/pvaClientMultiChannel_changes
Pva client multi channel changes
2021-03-06 09:18:52 -05:00
mrkraimer 8a661bb591 The following changes were made:
1) update documentation.
2) remove some output messages from pvaClientMonitor and pvaClientMultiChannel
3) performance improvement to pvaClientNTMultiPut.
2021-03-01 10:14:05 -05:00
Andrew Johnson efb2631905 Undo random typing... 2021-02-28 21:36:14 -06:00
mrkraimer 1211d01800 The changes:
1) Fix issues #66 and #70
2) All tests in exampleCPP/testMultiplePutGet now work successfully.

I still want to do more testing, especially on connection management.
Also relese notes and documentation needs work.
2021-02-26 12:32:15 -05:00
mrkraimer b665dac669 The following changes were made:
1) PvaClientChannel::channelCreated no longer declares channel connected.
   PvaClientChannel::channelStateChange does this.
2) PvaClientNTMultiData::endDeltaTime no longer calls unionValue[i] = PVUnionPtr()
2021-02-23 09:25:19 -05:00
mrkraimer 65a69a8901 Changes include:
1) Added method PvaClientNTMultiData::getChannelChangeFlags.
2) In pvaClientMultiChannel made methods not intended for client protected.
3) Fixed many connection related problems.
4) Cleaned up doxygen.
2021-02-17 11:10:41 -05:00
Andrew Johnson 7722fdf353 Set next development version 2020-05-28 16:26:01 -05:00
Andrew Johnson bc9ac8422c Update version numbers for release 2020-05-28 15:49:41 -05:00
mrkraimer c3aec4e27b get ready for next epics7 release 2020-05-20 14:01:16 -04:00
Marty Kraimer 0abfeef5ed Merge pull request #65 from dirk-zimoch/CleanupWhitespace
Cleanup whitespace
2020-05-20 08:50:14 -04:00
zimoch 745119cf77 removed empty lines at end of file 2020-04-15 17:51:17 +02:00
zimoch 9f794721ab removed spaces at end of line 2020-04-15 17:49:54 +02:00
zimoch 8f21ac8b9d replaced tabs with spaces 2020-04-15 17:45:02 +02:00
Marty Kraimer 9add9daf85 Merge pull request #64 from epics-base/issue#63
fix issue 63; add PvaClientData::getSinglePVField; simplify getDouble…
2019-12-04 05:46:44 -05:00
mrkraimer aaacadb42d fix issue 63; add PvaClientData::getSinglePVField; simplify getDouble, putDouble, etc 2019-12-02 10:32:48 -05:00
Andrew Johnson 5961c83477 Incr version and set development flag after release 2019-11-01 12:28:27 -05:00
Andrew Johnson b724b72624 Clear development flag for 4.7.0 release 2019-11-01 12:20:59 -05:00
Andrew Johnson fc42cf798e Release notes for 4.7.0 2019-11-01 11:09:28 -05:00
Marty Kraimer 71181afc93 Update .travis.yml 2019-09-13 09:15:35 -04:00
Ralph Lange b92a3ddaa4 rtd-ci: add read-the-docs integration 2019-09-06 14:18:19 +02:00
Andrew Johnson 246cceae3e Update version number to 4.7.0 DEVELOPMENT 2019-08-13 10:46:37 -05:00
mrkraimer 3f4df39ee0 fix issue #62 PvaClientData::parse bug 2019-08-12 06:03:55 -04:00
Marty Kraimer 837924af2e Update RELEASE_NOTES.md 2019-08-02 08:45:10 -04:00
Marty Kraimer 7b0e2b5986 Merge pull request #61 from mrkraimer/master
add JSON support
2019-08-02 08:42:29 -04:00
mrkraimer c84b24bb30 Merge https://github.com/epics-base/pvaClientCPP
merge to get latest hanges from epics-base
2019-08-02 05:44:42 -04:00
Andrew Johnson aba40922e6 Release notes for 4.6.0 2019-07-29 11:47:36 -05:00
Andrew Johnson 2c1cb03cd0 Use new CONFIG_PVACLIENT_VERSION file for SHRLIB_VERSION 2019-07-29 11:46:54 -05:00
mrkraimer f58c5159fc add streamJSON 2019-07-19 09:49:40 -04:00
mrkraimer a91ba8ef9e fixed a bug 2019-07-17 10:43:13 -04:00
mrkraimer ddb36536fe add zeroArrayLength 2019-07-16 10:33:39 -04:00
mrkraimer 9153036ccc added JSON support 2019-07-16 09:42:08 -04:00
Marty Kraimer 4c56116827 Merge pull request #60 from mrkraimer/master
working on issue #56; still problems with monitor
2019-04-26 12:51:02 -04:00
mrkraimer 81f5e25276 working on issue #56; still problems with monitor 2019-04-26 10:09:56 -04:00
Marty Kraimer 703b2224ce Merge pull request #59 from mrkraimer/master
fix issue #57
2019-04-25 05:07:20 -04:00
mrkraimer ed0b1cbf08 fix issue #57 2019-04-24 14:53:18 -04:00
Marty Kraimer 914e382dea Merge pull request #58 from mrkraimer/master
address issue #54
2019-04-24 05:18:19 -04:00
mrkraimer fd77d35b20 address issue #54 2019-04-23 14:04:13 -04:00
52 changed files with 865 additions and 2364 deletions
-10
View File
@@ -1,10 +0,0 @@
#!/bin/sh
set -e -x
make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make -j2 tapfiles
make -j2 -s test-results
fi
-111
View File
@@ -1,111 +0,0 @@
#!/bin/sh
set -e -x
CURDIR="$PWD"
cat << EOF > $CURDIR/configure/RELEASE.local
EPICS_BASE=$HOME/.source/epics-base
EOF
install -d "$HOME/.source"
cd "$HOME/.source"
add_gh_flat() {
MODULE=$1
REPOOWNER=$2
REPONAME=$3
BRANCH=$4
MODULE_UC=$(echo $MODULE | tr 'a-z' 'A-Z')
( git clone --quiet --depth 5 --branch $BRANCH https://github.com/$REPOOWNER/$REPONAME.git $MODULE && \
cd $MODULE && git log -n1 )
cat < $CURDIR/configure/RELEASE.local > $MODULE/configure/RELEASE.local
cat << EOF >> $CURDIR/configure/RELEASE.local
${MODULE_UC}=$HOME/.source/$MODULE
EOF
}
# not recursive
git clone --quiet --depth 5 --branch "$BRBASE" https://github.com/${REPOBASE:-epics-base}/epics-base.git epics-base
(cd epics-base && git log -n1 )
add_gh_flat pvData ${REPOPVD:-epics-base} pvDataCPP ${BRPVD:-master}
add_gh_flat pvAccess ${REPOPVA:-epics-base} pvAccessCPP ${BRPVA:-master}
add_gh_flat normativeTypes ${REPONT:-epics-base} normativeTypesCPP ${BRNT:-master}
if [ -e $CURDIR/configure/RELEASE.local ]
then
cat $CURDIR/configure/RELEASE.local
fi
EPICS_HOST_ARCH=`sh epics-base/startup/EpicsHostArch`
# requires wine and g++-mingw-w64-i686
if [ "$WINE" = "32" ]
then
echo "Cross mingw32"
sed -i -e '/CMPLR_PREFIX/d' epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
cat << EOF >> epics-base/configure/os/CONFIG_SITE.linux-x86.win32-x86-mingw
CMPLR_PREFIX=i686-w64-mingw32-
EOF
cat << EOF >> epics-base/configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS+=win32-x86-mingw
EOF
fi
if [ "$STATIC" = "YES" ]
then
echo "Build static libraries/executables"
cat << EOF >> epics-base/configure/CONFIG_SITE
SHARED_LIBRARIES=NO
STATIC_BUILD=YES
EOF
fi
case "$CMPLR" in
clang)
echo "Host compiler is clang"
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.$EPICS_HOST_ARCH
GNU = NO
CMPLR_CLASS = clang
CC = clang
CCC = clang++
EOF
# hack
sed -i -e 's/CMPLR_CLASS = gcc/CMPLR_CLASS = clang/' epics-base/configure/CONFIG.gnuCommon
clang --version
;;
*)
echo "Host compiler is default"
gcc --version
;;
esac
cat <<EOF >> epics-base/configure/CONFIG_SITE
USR_CPPFLAGS += $USR_CPPFLAGS
USR_CFLAGS += $USR_CFLAGS
USR_CXXFLAGS += $USR_CXXFLAGS
EOF
# set RTEMS to eg. "4.9" or "4.10"
# requires qemu, bison, flex, texinfo, install-info
if [ -n "$RTEMS" ]
then
echo "Cross RTEMS${RTEMS} for pc386"
curl -L "https://github.com/mdavidsaver/rsb/releases/download/20171203-${RTEMS}/i386-rtems${RTEMS}-trusty-20171203-${RTEMS}.tar.bz2" \
| tar -C / -xmj
sed -i -e '/^RTEMS_VERSION/d' -e '/^RTEMS_BASE/d' epics-base/configure/os/CONFIG_SITE.Common.RTEMS
cat << EOF >> epics-base/configure/os/CONFIG_SITE.Common.RTEMS
RTEMS_VERSION=$RTEMS
RTEMS_BASE=$HOME/.rtems
EOF
cat << EOF >> epics-base/configure/CONFIG_SITE
CROSS_COMPILER_TARGET_ARCHS += RTEMS-pc386-qemu
EOF
fi
make -j2 -C epics-base $EXTRA
make -j2 -C pvData $EXTRA
make -j2 -C normativeTypes $EXTRA
make -j2 -C pvAccess $EXTRA
+17
View 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
-31
View File
@@ -1,31 +0,0 @@
sudo: false
dist: trusty
language: c++
compiler:
- gcc
addons:
apt:
packages:
- libreadline6-dev
- libncurses5-dev
- perl
- clang
- g++-mingw-w64-i686
- qemu-system-x86
install:
- ./.ci/travis-prepare.sh
script:
- ./.ci/travis-build.sh
env:
- BRBASE=7.0
- BRBASE=7.0 CMPLR=clang
- BRBASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++98"
- BRBASE=7.0 EXTRA="CMD_CXXFLAGS=-std=c++11"
- BRBASE=7.0 CMPLR=clang EXTRA="CMD_CXXFLAGS=-std=c++11"
- BRBASE=7.0 WINE=32 TEST=NO STATIC=YES
- BRBASE=7.0 WINE=32 TEST=NO STATIC=NO
- BRBASE=7.0 RTEMS=4.10 TEST=NO
- BRBASE=7.0 RTEMS=4.9 TEST=NO
- BRBASE=3.16
- BRBASE=3.15
- BRBASE=3.14
+7 -6
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = pvaClientCPP
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = 4.8.1
# 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
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
STRIP_FROM_PATH = src
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -161,7 +161,7 @@ STRIP_FROM_PATH =
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
STRIP_FROM_INC_PATH = src
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@@ -765,7 +765,8 @@ 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 \
src/pv
# 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
@@ -796,7 +797,7 @@ FILE_PATTERNS =
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
@@ -1035,7 +1036,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
View File
@@ -0,0 +1,12 @@
# Version number for the PVA Client API and shared library
EPICS_PVACLIENT_MAJOR_VERSION = 4
EPICS_PVACLIENT_MINOR_VERSION = 8
EPICS_PVACLIENT_MAINTENANCE_VERSION = 1
# Development flag, set to zero for release versions
EPICS_PVACLIENT_DEVELOPMENT_FLAG = 0
# Immediately after a release the MAINTENANCE_VERSION
# will be incremented and the DEVELOPMENT_FLAG set to 1
+2
View File
@@ -2,6 +2,8 @@ TOP=..
include $(TOP)/configure/CONFIG
CFG += CONFIG_PVACLIENT_VERSION
TARGETS = $(CONFIG_TARGETS)
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
+32
View File
@@ -2,6 +2,38 @@
This document summarizes the changes to the module between releases.
## Release 4.8.1 (EPICS 7.0.10, Dec 2025)
* Fix error message generation code.
## Release 4.8.0 (EPICS 7.0.6 Jul 2021)
* PvaClientNTMultiData::getChannelChangeFlags is a new method. It fixes issue #66.
* Fix for issue #68. Both PvaClientArray and PvaClientField are not longer present. Neither was previously implemented.
* Several public methods are now protected. They were never meant to be called by clients.
* Issue #70 has been fixed.
* Changes was made to increase the performance of pvaMultiChannel.
* doxygen changes were made.
## Release 4.7.1 (EPICS 7.0.3.2 May 2020)
* support access to a union field that is a scalar or scalarArray
* fixed issues #62 and #63
## Release 4.7.0 (EPICS 7.0.3.1, Nov 2019)
* added JSON support for put and putGet
* Fix for
[GitHub issue #62](https://github.com/epics-base/pvaClientCPP/issues/62)
* Doxygen updates and read-the-docs integration.
## Release 4.6.0 (EPICS 7.0.3, Jul 2019)
* pvaClient now handles exceptions from the server properly (issue #54).
* MultiChannel classes now properly handle PV structures that don't have a top-level `value` field (issue #56), and are more tolerant of other missing fields (issue #57).
## Release 4.5.0 (EPICS 7.0.2.2, Apr 2019)
Changes have been made for getDouble, putDouble, getDoubleArray, putDoubleArray, getString, putString, getStringArray, and putStringArray.
+7
View File
@@ -0,0 +1,7 @@
.wy-side-nav-search {
background-color: #18334B;
}
.wy-side-nav-search input[type="text"] {
border-color: #18334b;
}
+80
View 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',
'pvaClientCPP.html',
]
# -- Run Doxygen ------------------------------------------------------------
import subprocess
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
-5
View File
@@ -1,5 +0,0 @@
NOT FOR DIRECT USE
==================
This directory holds files that are used by doxygen.
The files are not meant to be read except via the doxygen documention.
-146
View File
@@ -1,146 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClient</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClient</h1>
<h2>Overview</h2>
<p>
pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API.
Thus it is easier to use than pvAccess itself.
In addition pvaClient provides many convenience methods.
</p>
<p>
Class <b>PvaClient</b> is a class that is used by all the other pvaClient classes.
An application that uses pvaClient must call:</p>
<pre>
PvaClientPtr pvaClient = PvaClient::get(providers);
</pre>
<p>
before it uses any other pvaClient classes.
</p>
<p>
This is a singleton method, i. e. only one instance of PvaClient is created.
</p>
<p>
<b>pvaClient</b> must not be deleted until the client no longer wants to use any part
of pvaClient.
</p>
<p>
<b>providers</b> is a blank separated set of provider names.
For example:</p>
<pre>
PvaClientPtr pvaClient = PvaClient::get("ca pva");
</pre>
<p>
The providers <b>ca</b> and <b>pva</b> are special.
For each of these a client context is created when the <b>PvaClient</b>
is constructed and the context destroyed when <b>PvaClient</b> is deleted.
</p>
<h2>Channel Caching</h2>
<p>
<b>PvaClient</b> has a method:
</p>
<pre>
PvaClientChannelPtr channel(
string const &amp; channelName,
string const &amp;providerName = "pva",
double timeOut = 5.0);
</pre>
<p>
This method creates a
<b>PvaClientChannel</b> and then connects to the channel.
</p>
<p>
If a call is successful then multiple calls to the same channelName and providerName
share the same PvaClientChannel, i. e. the PvaClientChannel is cached.
</p>
<p>
<b>pvaClientChannelGet</b> and <b>pvaClientChannelPut</b> also implement caching.
</p>
<p>
For example consider a client that makes multiple calls like:
</p>
<pre>
double value;
value = pva->channel(channelName)->get()->getData()->getDouble();
...
value = pva->channel(channelName)->get()->getData()->getDouble();
</pre>
<p>
Only the first call creates a new PvaClientChannel and a new PvaClientGet.
The second call reuses the cached PvaClientChannel and PvaClientGet.
</p>
<h2>Non Cached Channels</h2>
<p>
<b>PvaClient</b> has a method:
</p>
<pre>
PvaClientChannelPtr createChannel(
string const &amp; channelName,
string const &amp;providerName = "pva");
</pre>
<p>
This method is just creates a new PvaClientChannel and returns it to the caller.
The caller must call the PvaClientChannel connect methods.
</p>
<h2>Blocking vs Non-Blocking Methods</h2>
<p>Each component of pvaClient provides a set of blocking and non-blocking calls.
For example several components (examples are <b>PvaClientChannel</b> and <b>PvaChannelGet</b>)
have methods:</p>
<dl>
<dt>connect</dt>
<dd>
This calls issueConnect and then waitConnect.
If waitConnect fails an exception is thrown.
Since waitConnect is a blocking method so is this.
</dd>
<dt>issueConnect</dt>
<dd>
This is a request to connect, i. e. issue a request to the server to create something
on the server. This is a non blocking call.
</dd>
<dt>waitConnect</dt>
<dd>
This waits for the server to respond to issueConnect.
It blocks until the server responds or a timeout occurs.
</dd>
</dl>
</body>
</html>
@@ -1,123 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientChannel</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientChannel</h1>
<h2>Overview</h2>
<p>
pvaClientChannel is a synchronous wrapper for the pvAccess::Channel API, which is a callback based API.
Thus it is easier to use than pvAccess::Channel itself.
</p>
<p>An instance of <b>PvaClientChannel</b> connects to a single channel.
An instance can only be created via class <b>PvaClient</b> which has both synchronous methods, which block, and non blocking methods.
The synchrouous methods block until a connection is made to the channel and throw an exception if a
timeout occurs while trying to make a connection.
The non blocking methods leave connection to the caller.
</p>
<p><b>PvaClientChannel</b> has methods:</p>
<dl>
<dt>Connect to channel</dt>
<dd>These can be called indirectly by a blocking request to <b>PvaClient</b>
or by the client if a non blocking request is made to <b>PvaClient</b>.
</dd>
<dt>Channel state change requester</dt>
<dd>The client can provide a callback that is called each time the connection state
of the channel changes.
</dd>
<dt>Creating all of the following</dt>
<dd>
<pre>
PvaClientField NOT IMPLEMENTED
PvaClientProcess
PvaClientGet
PvaClientPut
PvaClientPutGet
PvaClientMonitor
PvaClientArray NOT IMPLEMENTED
PvaClientRPC
</pre>
</dd>
</dl>
<h2>Connect: Blocking vs Non-Blocking </h2>
<p><b>PvaClientChannel</b> has methods:</p>
<dl>
<dt>connect</dt>
<dd>
This calls issueConnect and then waitConnect.
If waitConnect fails an exception is thrown.
Since waitConnect is a blocking method so is this.
</dd>
<dt>issueConnect</dt>
<dd>
This is a request to connect to the channel. This is a non blocking call.
</dd>
<dt>waitConnect</dt>
<dd>
This waits for the server to respond to issueConnect.
It blocks until the server responds or a timeout occurs.
</dd>
</dl>
<h2>Get and Put Caching</h2>
<p>
<b>PvaClientChannel</b> has methods:
</p>
<pre>
PvaClientGetPtr get(std::string const &amp; request);
PvaClientPutPtr put(std::string const &amp; request);
</pre>
<p>
Each of these caches.
For example all calls to <b>get</b> with the same <b>request</b> will share the same
<b>PvaChannelGet</b>
</p>
<p>
For example consider a client that makes multiple calls like:
</p>
<pre>
double value;
value = pva->channel(channelName)->get()->getData()->getDouble();
...
value = pva->channel(channelName)->get()->getData()->getDouble();
</pre>
<p>
Only the first call creates a new PvaClientChannel and a new PvaClientGet.
The second call reuses the cached PvaClientChannel and PvaClientGet.
</p>
</body>
</html>
@@ -1,81 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientChannelStateChangeRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientChannelStateChangeRequester</h1>
<p>This class has the single method <b>channelStateChange</b>.
It is called each time the channel connection status changes.
</p>
<p>
<b>NOTE:</b>
The implementation must not call a method that blocks waiting for a response from the server.
It it does the client may be blocked forever.
</p>
<p>
An example of illegal code is:
</p>
<pre>
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
{
if(isConnected&&!pvaClientPut)
{
pvaClientPut = pvaClientChannel->createPut(request);
pvaClientPut->connect();
}
}
</pre>
<p>
This is illegal because the call to <b>connect</b> blocks.
</p>
<p>The following is an example of legal code:
</p>
<pre>
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
{
if(isConnected&&!pvaClientPut)
{
pvaClientPut = pvaClientChannel->createPut(request);
pvaClientPut->issueConnect();
}
}
</pre>
<p>This is legal code because neither <b>createPut</b> or <b>issueConnect</b>
blocks.
</p>
</body>
</html>
@@ -1,74 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientGet</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientGet</h1>
<p>
pvaClientGet is a synchronous wrapper for the pvAccess::ChannelGet API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelGet itself.
</p>
<p>An instance of PvaClientGet is created via a call to one of the following:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientGetPtr get(std::string const &amp; request = "field(value,alarm,timeStamp)");
PvaClientGetPtr createGet(std::string const &amp; request = "");
PvaClientGetPtr createGet(epics::pvData::PVStructurePtr const &amp; pvRequest);
...
};
<p>An instance of <b>PvaClientGet</b> connects to a single channel.
<b>PvaClientGet</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientChannel</b> has methods:</p>
<pre>
connect Calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
get Calls issueGet and then waitGet.
issueGet issues a get request to the server.
waitGet waits until the server send a message that the get is complete.
getData get the data.
</pre>
<p>
<b>issueConnect</b> and <b>issueGet</b> do not block.
All other methods can block.
</p>
</body>
</html>
@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientGetData</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientGetData</h1>
<p>This class provides access to the data returned by calls to get data via <b>PvaChannelGet</b>
It provides methods:</p>
<pre>
getStructure Get the introspection interface for data returned from server
getPVStructure Get the complete set of data returned from the server.
getChangedBitSet Get the bitSet that shows which fields have a new value since last get.
showChanged Show all the fields that have changed value since the last get,
getAlarm If a alarm field is available get it.
getTimeStamp If a timeStamp field is available get it.
hasValue Does the PVStructure have a top level field named value
NOTE: The following only apply if hasValue is true.
isValueScalar Is the value field a scalar?
isValueScalarArray Is the value field a scalar array?
getValue Get the value field.
getScalarValue Get a scalar value field.
getArrayValue Get an array value field.
getScalarArrayValue Get a scalar array value field.
getDouble Get scalar value field as a double.
getString Get value field as a string.
getDoubleArray Get value field as a double array.
getStringArray Get value field as a string array.
</pre>
</body>
</html>
@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientGetRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientGetRequester</h1>
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientGet</b>.
It has the methods:</p>
<pre>
virtual void channelGetConnect(
const Status&amp; status,
PvaClientGetPtr const &amp; clientGet) {}
virtual void getDone(
const Status&amp; status,
PvaClientGetPtr const &amp; clientGet) = 0;
</pre>
<p>The client must call</p>
<pre>
pvaClientGet->setRequester(shared_from_this());
</pre>
<p>
after creating an instance of PvaClientGet.
</p>
</body>
</html>
@@ -1,106 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientMonitor</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientMonitor</h1>
<p>
<b>NOTE:</b> This is a work in progress.
</p>
<h2>Overview</h2>
<p>
This provides an easier way to create a monitor on a channel than to use pvAccessCPP itself.
It provides two main ways to create a monitor:
</p>
<h3>The client first creates a PvaClientMonitorChannel and then creates a monitor</h3>
The client calls:
<pre>
static PvaClientMonitorPtr create(
PvaClientMonitorPtr const &amp;PvaClientMonitor,
PvaClientMonitorChannelPtr const &amp; PvaClientMonitorChannel,
epics::pvData::PVStructurePtr const &amp;pvRequest
);
where
PvaClientMonitor
The PvaClientMonitor.
PvaClientMonitorChannel
The PvaClientMonitorChannel that has already been created by the client.
pvRequest
The pvRequest for creating the monitor.
</pre>
With this method the monitor is created and started.
This method blocks while the monitor is created.
<h3>The client provides names for a channel and a provider</h3>
The client calls:
<pre>
static PvaClientMonitorPtr create(
PvaClientMonitorPtr const &amp;PvaClientMonitor,
std::string const &amp; channelName,
std::string const &amp; providerName,
std::string const &amp; request,
PvaClientMonitorChannelStateChangeRequesterPtr const &amp; stateChangeRequester,
PvaClientMonitorRequesterPtr const &amp; monitorRequester
);
where
PvaClientMonitor
The PvaClientMonitor.
channelName
The name of the channel.
providerName
The name of the provider
request
The request for creating the monitor
stateChangeRequester
The client supplied state change requester.
This will be called each time a state change for the channel occurs.
monitorRequester
The client supplied monitor requester.
This is called each time a new monitor event is available.
</pre>
With this method a pvaChannel is created and after it connects a pvaMonitor is created and started.
This method never blocks.
</body>
</html>
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientMonitorData</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientMonitorData</h1>
<p>This class provides access to the data returned by calls to get data via <b>PvaChannelGet</b>
It provides methods:</p>
<pre>
getStructure Get the introspection interface for data returned from server
getPVStructure Get the complete set of data returned from the server.
getChangedBitSet Get the bitSet that shows which fields have a new value since last monitor event.
getOverrunBitSet Get the bitSet that shows which fields have changed more than once since last monitor event.
showChanged Show all the fields that have changed value since the last monitor event,
showChanged Show all the fields that have changed value more than once since last monitor event.
getAlarm If a alarm field is available get it.
getTimeStamp If a timeStamp field is available get it.
hasValue Does the PVStructure have a top level field named value
NOTE: The following only apply if hasValue is true.
isValueScalar Is the value field a scalar?
isValueScalarArray Is the value field a scalar array?
getValue Get the value field.
getScalarValue Get a scalar value field.
getArrayValue Get an array value field.
getScalarArrayValue Get a scalar array value field.
getDouble Get scalar value field as a double.
getString Get value field as a string.
getDoubleArray Get value field as a double array.
getStringArray Get value field as a string array.
</pre>
</body>
</html>
@@ -1,65 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientMonitorRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientMonitorRequester</h1>
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientMonitor</b>.
It has the methods:</p>
<pre>
virtual void monitorConnect(
const Status&amp; status,
PvaClientMonitorPtr const &amp; clientMonitor,
StructureConstPtr const &amp; structure) {}
virtual void event(
PvaClientMonitor const &amp; clientGet) = 0;
virtual void unlisten()
{
std::cerr &lt;&lt; "PvaClientMonitorRequester::unlisten called"
&lt;&lt; " but no PvaClientMonitorRequester::unlisten\n";
}
</pre>
<p>The client must call</p>
<pre>
pvaClientMonitor->setRequester(shared_from_this());
</pre>
<p>
after creating an instance of PvaClientMonitor.
</p>
</body>
</html>
@@ -1,71 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientProcess</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientProcess</h1>
<p>
pvaClientProcess is a synchronous wrapper for the pvAccess::ChannelProcess API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelProcess itself.
</p>
<p>An instance of PvaClientProcess is created via a call to one of the followimg:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientProcessPtr createProcess(std::string const &amp; request = "");
PvaClientProcessPtr createProcess(epics::pvData::PVStructurePtr const &amp; pvRequest);
...
};
<p>An instance of <b>PvaClientProcess</b> connects to a single channel.
<b>PvaClientProcess</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientChannel</b> has methods:</p>
<pre>
connect Calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
process Calls issueProcess and then waitProcess.
issueProcess issues a process request to the server.
waitProcess waits until the server send a message that the process is complete.
</pre>
<p>
<b>issueConnect</b> and <b>issueProcess</b> do not block.
All other methods can block.
</p>
</body>
</html>
@@ -1,82 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientChannelPut</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientChannelPut</h1>s
<p>
pvaClientPut is a synchronous wrapper for the pvAccess::ChannelPut API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelPut itself.
</p>
<p>
<b>NOTE:</b>
Except for union fields pvaClientPut takes care of modifying the bitSet associated with
the data sent to the server.
</p>
<p>An instance of PvaClientPut is created via a call to one of the followimg:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientPutPtr put(std::string const & request = "field(value,alarm,timeStamp)");
PvaClientPutPtr createPut(std::string const & request = "");
PvaClientPutPtr createPut(epics::pvData::PVStructurePtr const & pvRequest);
...
};
<p>An instance of <b>PvaClientPut/b> connects to a single channel.
<b>PvaClientPut</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientPut</b> has methods:</p>
<pre>
connect Calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
get Calls issueGet and then waitGet.
issueGet issues a request to the server to get the latest data.
waitGet waits until the server send a message that the get is complete.
put Calls issuePut and then waitPut.
issuePut issues a put request to the server.
waitPut waits until the server send a message that the put is complete.
getData get the data.
</pre>
<p>
Note that <b>issueConnect</b>, <b>issueGet</b> and <b>issuePut</b> do not block but all other methods
do block.
</p>
</body>
</html>
@@ -1,75 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientPutData</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientPutData</h1>
<p>This class provides access to data to send to the server via a <b>PvaChannelPut</b>
It is created by <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b>.
This the client only gets access to an instance by getting it from <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b>.
<p>
<p>Note also that for all field types except <b>union</b> the <b>BitSet</b> for the data is updated
by <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b> whenever the client changes a field.
For a <b>union</b> or <b>unionArray</b> field the client must update the <b>BitSet</b>.
</p>
<p>
PvaClientPutData provides methods:</p>
<pre>
getStructure Get the introspection interface for data sent to server
getPVStructure Get the complete set of data sent to the server.
getChangedBitSet Get the bitSet that shows which fields have a new value since last get.
showChanged Show all the fields that have changed value since the last get,
getAlarm If a alarm field is available get it.
getTimeStamp If a timeStamp field is available get it.
hasValue Does the PVStructure have a top level field named value
NOTE: The following only apply if hasValue is true.
isValueScalar Is the value field a scalar?
isValueScalarArray Is the value field a scalar array?
getValue Get the value field.
getScalarValue Get a scalar value field.
getArrayValue Get an array value field.
getScalarArrayValue Get a scalar array value field.
getDouble Get scalar value field as a double.
getString Get value field as a string.
getDoubleArray Get value field as a double array.
getStringArray Get value field as a string array.
putDouble Put scalar value field as a double.
putString Put value field as a string.
putDoubleArray Put value field as a double array.
putStringArray Put value field as a string array.
</pre>
</body>
</html>
@@ -1,85 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientPutGetGet</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientPutGetGet</h1>
<p>
pvaClientPutGet is a synchronous wrapper for the pvAccess::ChannelPutGet API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelPut itself.
</p>
<p>
<b>NOTE:</b>
Except for union fields pvaClientPutGet takes care of modifying the bitSet associated with
the data sent to the server.
</p>
<p>An instance of PvaClientPutGet is created via a call to one of the followimg:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientPutGetPtr createPutGet(std::string const &amp; request);
PvaClientPutGetPtr createPutGet(epics::pvData::PVStructurePtr const &amp; pvRequest);
...
};
<p>An instance of <b>PvaClientPutGet</b> connects to a single channel.
<b>PvaClientPutGet</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientPutGet</b> has methods:</p>
<pre>
connect calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
putGet call issuePutGet and then waitPutGet.
issuePutGet issue a putGet and return immediately.
waitPutGet wait until putGet completes.
getGet calls issueGetGet and then waitGetGet.
issueGetGet issues a request to the server to get the latest data for the get data.
waitGetGet waits until the server send a message that the getGet is complete.
getPut calls issueGetPut and then waitGetPut.
issueGetPut issues a request to the server to get the latest data for the put data.
waitGetPut waits until the server send a message that the getPut is complete.
getPutData get the put portion of the data.
getGetData get the get portion of the data.
</pre>
<p>
<b>issueConnect</b>, <b>issuePutGet</b>, <b>issueGetGet</b> and <b>issueGetPut</b> do not block.
All other methods can block.
</p>
</body>
</html>
@@ -1,66 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientPutGetRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientPutGetRequester</h1>
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientPut</b>.
It has the methods:</p>
<pre>
virtual void channelPutGetConnect(
const Status&amp; status,
PvaClientPutGetPtr const &amp; clientPutGet) {}
virtual void putGetDone(
const Status&amp; status,
PvaClientPutGetPtr const &amp; clientPutGet) {}
virtual void getPutDone(
const Status&amp; status,
PvaClientPutGetPtr const &amp; clientPutGet) = 0;
virtual void getGetDone(
const Status&amp; status,
PvaClientPutGetPtr const &amp; clientPutGet) = 0;
</pre>
<p>The client must call</p>
<pre>
pvaClientPutGet->setRequester(shared_from_this());
</pre>
<p>
after creating an instance of PvaClientPutGet.
</p>
</body>
</html>
@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientPutRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientPutRequester</h1>
<p>This is a virtual class that can be implemented by a client that uses <b>PvaClientPut</b>.
It has the methods:</p>
<pre>
virtual void channelPutConnect(
const Status&amp; status,
PvaClientPutPtr const &amp; clientPut) {}
virtual void getDone(
const Status&amp; status,
PvaClientPutPtr const &amp; clientPut) {}
virtual void putDone(
const Status&amp; status,
PvaClientPutPtr const &amp; clientPut) = 0;
</pre>
<p>The client must call</p>
<pre>
pvaClientPut->setRequester(shared_from_this());
</pre>
<p>
after creating an instance of PvaClientPut.
</p>
</body>
</html>
@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientRPC</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientRPC</h1>
<p>
<b>Not Yet Written</b>
</p>
</body>
</html>
@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientRPCRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![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>
</head>
<body>
<h1>PvaClientRPCRequester</h1>
<p>
<b>Not Yet Written</b>
</p>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

+17
View File
@@ -0,0 +1,17 @@
pvaClient (C++) Library
========================
.. toctree::
:hidden:
EPICS Website <https://epics-controls.org>
EPICS Documentation Home <https://docs.epics-controls.org>
.. toctree::
:maxdepth: 1
:caption: pvaClientCPP
Reference Manual <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/pvaClientCPP.html>
API Documentation <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/doxygen>
Source Code Repository on GitHub <https://github.com/epics-base/pvaClientCPP>
+13 -6
View File
@@ -6,9 +6,9 @@
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvaClientCPP</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[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
@@ -18,7 +18,7 @@
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
<script type="text/javascript" src="https://mrkraimer.github.io/website/css/tocgen.js"></script>
</head>
@@ -26,7 +26,7 @@
<div class="head">
<h1>EPICS pvaClientCPP</h1>
<h2 class="nocount">Release 4.4 - April 2019</h2>
<h2 class="nocount">Release 4.8 - March 2021</h2>
<h2 class="nocount">Abstract</h2>
@@ -66,9 +66,16 @@ The data for the channels is presented via normative type NTMultiChannel.
<hr />
<h2>Overview</h2>
<p>
Documentation for pvaClientCPP is available at:
<a
href="https://mrkraimer.github.io/website/developerGuide/pvaClient/pvaClientCPP.html">
pvaClient
</a>
</p>
<p>
pvaClientCPP is one of the components of
<a href="http://epics-pvdata.sourceforge.net">
EPICS Version 4
<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 pvaClientCPP
+1 -1
View File
@@ -6,7 +6,7 @@ include $(TOP)/configure/CONFIG
LIBRARY += pvaClient
# shared library ABI version.
SHRLIB_VERSION ?= 4.5.0
SHRLIB_VERSION ?= $(EPICS_PVACLIENT_MAJOR_VERSION).$(EPICS_PVACLIENT_MINOR_VERSION).$(EPICS_PVACLIENT_MAINTENANCE_VERSION)
INC += pv/pvaClient.h
INC += pv/pvaClientMultiChannel.h
+71 -95
View File
@@ -17,7 +17,8 @@
#include <list>
#include <iostream>
#include <sstream>
#include <ostream>
#include <sstream>
#include <pv/requester.h>
#include <pv/status.h>
#include <pv/event.h>
@@ -35,12 +36,12 @@
#ifdef pvaClientEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvaClientEpicsExportSharedSymbols
# undef pvaClientEpicsExportSharedSymbols
#endif
#include <shareLib.h>
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
class PvaClient;
typedef std::tr1::shared_ptr<PvaClient> PvaClientPtr;
@@ -57,8 +58,6 @@ typedef std::tr1::shared_ptr<PvaClientChannelStateChangeRequester> PvaClientChan
typedef std::tr1::weak_ptr<PvaClientChannelStateChangeRequester> PvaClientChannelStateChangeRequesterWPtr;
class PvaClientChannel;
typedef std::tr1::shared_ptr<PvaClientChannel> PvaClientChannelPtr;
class PvaClientField;
typedef std::tr1::shared_ptr<PvaClientField> PvaClientFieldPtr;
class PvaClientProcessRequester;
typedef std::tr1::shared_ptr<PvaClientProcessRequester> PvaClientProcessRequesterPtr;
typedef std::tr1::weak_ptr<PvaClientProcessRequester> PvaClientProcessRequesterWPtr;
@@ -84,8 +83,6 @@ typedef std::tr1::shared_ptr<PvaClientMonitor> PvaClientMonitorPtr;
class PvaClientMonitorRequester;
typedef std::tr1::shared_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterPtr;
typedef std::tr1::weak_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterWPtr;
class PvaClientArray;
typedef std::tr1::shared_ptr<PvaClientArray> PvaClientArrayPtr;
class PvaClientRPC;
typedef std::tr1::shared_ptr<PvaClientRPC> PvaClientRPCPtr;
class PvaClientRPCRequester;
@@ -100,7 +97,6 @@ typedef std::tr1::shared_ptr<PvaClientChannelCache> PvaClientChannelCachePtr;
/**
* @brief pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API.
*
* <a href = "../htmldoxygen/pvaClient.html">Overview of PvaClient</a>
*/
class epicsShareClass PvaClient :
public epics::pvData::Requester,
@@ -118,16 +114,11 @@ public:
* @return shared pointer to the single instance.
*/
static PvaClientPtr get(std::string const & providerNames = "pva ca");
/** @brief Get the requester name.
* @return The name.
*/
/** @brief Create an instance of PvaClient with providerName "pva ca".
/** @brief Create an instance of PvaClient with providerName "pva ca".
* @return shared pointer to the single instance
* @deprecated This method will go away in future versions. Use get instead.
*/
static PvaClientPtr create() EPICS_DEPRECATED;
std::string getRequesterName();
/** @brief A new message.
*
* If a requester is set then it is called otherwise message is displayed
@@ -155,18 +146,24 @@ public:
* @param channelName The channelName.
* @param providerName The provider.
* @return The interface.
* @throw runtime_error if connection fails.
*/
PvaClientChannelPtr createChannel(
std::string const & channelName,
std::string const & providerName = "pva");
/** @brief Set a requester.
*
* The default is for PvaClient to handle messages by printing to System.out.
* @param requester The requester.
*/
void setRequester(epics::pvData::RequesterPtr const & requester);
/** @brief Get the requester name.
*
* If client calls setRequester then the client supplies the name.
* Otherwise the name is pvaClient.
* @return The name.
*/
std::string getRequesterName();
/** @brief Clear the requester. PvaClient will handle messages.
*/
void clearRequester();
@@ -203,10 +200,9 @@ class PvaClientPutCache;
typedef std::tr1::shared_ptr<PvaClientPutCache> PvaClientPutCachePtr;
/**
/**
* @brief A callback for change in connection status.
*
* <a href = "../htmldoxygen/pvaClientChannelStateChangeRequester.html">Overview of PvaClientChannelStateChangeRequester</a>
*
*/
class epicsShareClass PvaClientChannelStateChangeRequester
@@ -227,10 +223,9 @@ public:
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected) = 0;
};
/**
/**
* @brief An easy to use alternative to directly calling the Channel methods of pvAccess.
*
* <a href = "../htmldoxygen/pvaClientChannel.html">Overview of PvaClientChannel</a>
*/
class epicsShareClass PvaClientChannel :
@@ -244,7 +239,7 @@ public:
*/
~PvaClientChannel();
/** @brief Set a client stateChangeRequester.
*
*
* @param stateChangeRequester The client stateChangeRequester implementation.
*/
void setStateChangeRequester(PvaClientChannelStateChangeRequesterPtr const &stateChangeRequester);
@@ -275,13 +270,6 @@ public:
* @return status.
*/
epics::pvData::Status waitConnect(double timeout = 5.0);
/** @brief Create a PvaClientField for the specified subField.
*
* @param subField The desired subField, i. e. "field.field...."
* An empty string, i. e. "", asks for the entire top level struture as defined by the server.
* @return The interface.
*/
PvaClientFieldPtr createField(std::string const & subField = "");
/** @brief First call createRequest as implemented by pvDataCPP and then call the next method.
*
* @param request The syntax of request is defined by the copy facility of pvData.
@@ -289,7 +277,7 @@ public:
* @throw runtime_error if failure.
*/
PvaClientProcessPtr createProcess(std::string const & request = "");
/** Creates a PvaClientProcess.
/** Creates a PvaClientProcess.
*
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
* @return The interface.
@@ -350,7 +338,7 @@ public:
epics::pvData::shared_vector<const std::string> getStringArray(
std::string const & request = "field(value)");
/** @brief create a PvaClientPut.
*
*
* Get a cached PvaClientPut or create and connect to a new PvaClientPut.
* Then call it's get method.
* @param request The syntax of request is defined by the copy facility of pvData.
@@ -396,7 +384,7 @@ public:
epics::pvData::shared_vector<const double> const & value,
std::string const & request = "field(value)");
/** @brief Copy array to the value field.
*
*
* @param value The new value.
* @param request The syntax of request is defined by the copy facility of pvData.
* @throw runtime_error if failure.
@@ -425,20 +413,6 @@ public:
* @return The interface.
*/
PvaClientPutGetPtr createPutGet(epics::pvData::PVStructurePtr const & pvRequest);
/** @brief Create a PvaClientArray.
*
* First call createRequest as implemented by pvDataJava and then call the next method.
* @param request The syntax of request is defined by the copy facility of pvData.
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientArrayPtr createArray(std::string const & request = "field(value)");
/** @brief Create a PvaClientArray.
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientArrayPtr createArray(epics::pvData::PVStructurePtr const & pvRequest);
/** @brief Create a PvaClientMonitor.
*
* Create and connect to a new PvaClientMonitor.
@@ -449,7 +423,7 @@ public:
* @throw runtime_error if failure.
*/
PvaClientMonitorPtr monitor(std::string const & request = "field(value,alarm,timeStamp)");
/** @brief Call the next method with request = "field(value,alarm,timeStamp)"
/** @brief Call the next method with request = "field(value,alarm,timeStamp)"
*
* @param pvaClientMonitorRequester The client callback.
* @return The interface.
@@ -538,7 +512,7 @@ private:
std::string channelName;
std::string providerName;
ConnectState connectState;
epics::pvData::CreateRequest::shared_pointer createRequest;
PvaClientGetCachePtr pvaClientGetCache;
PvaClientPutCachePtr pvaClientPutCache;
@@ -560,10 +534,9 @@ public:
friend class PvaClient;
};
/**
/**
* @brief A base class for PvaClientGetData, PvaClientPutData, and PvaClientMonitorData.
*
* <a href = "../htmldoxygen/pvaClientData.html">Overview of PvaClientData</a>
*/
class epicsShareClass PvaClientData
{
@@ -613,6 +586,7 @@ public:
void setData(
epics::pvData::PVStructurePtr const & pvStructureFrom,
epics::pvData::BitSetPtr const & bitSetFrom);
/** @brief Is there a top level field named value.
* @return The answer.
*/
@@ -679,24 +653,49 @@ public:
* @return The timeStamp.
*/
epics::pvData::TimeStamp getTimeStamp();
/** @brief Factory method for creating an instance of PvaClientData.
/** @brief parse from args
*
* NOTE: Not normally called by clients
* @param structure Introspection interface
* Accepts arguments of the form json or field='value' where value is json syntax.
* field is name.name...
* @param args The arguments.
* @throw runtime_error if failure.
*/
static PvaClientDataPtr create(epics::pvData::StructureConstPtr const & structure);
void parse(const std::vector<std::string> &args);
/** @brief generate JSON output from the current PVStructure and displays it on the output stream.
*
* @param strm The output stream.
* @param ignoreUnprintable false or true; The default is true.
* @param multiline false or true; The default is false.
*
* @throw runtime_error if failure.
*/
void streamJSON(
std::ostream& strm,
bool ignoreUnprintable = true,
bool multiLine = false);
/** @brief set length of all array fields to 0
*/
void zeroArrayLength();
protected:
static PvaClientDataPtr create(epics::pvData::StructureConstPtr const & structure);
PvaClientData(epics::pvData::StructureConstPtr const & structure);
epics::pvData::PVFieldPtr getSinglePVField();
void checkValue();
std::string messagePrefix;
private:
void parse(
const std::string &arg,
const epics::pvData::PVFieldPtr &dest,
epics::pvData::BitSetPtr &bitSet);
void parse(
const std::string &arg,
const epics::pvData::PVUnionPtr &dest);
void zeroArrayLength(const epics::pvData::PVStructurePtr &pvStructure);
epics::pvData::StructureConstPtr structure;
epics::pvData::PVStructurePtr pvStructure;
epics::pvData::BitSetPtr bitSet;
epics::pvData::PVFieldPtr pvValue;
epics::pvData::PVAlarm pvAlarm;
epics::pvData::PVTimeStamp pvTimeStamp;
@@ -704,10 +703,9 @@ private:
friend class PvaClientPutGet;
};
/**
/**
* @brief A class that holds data returned by PvaClientGet or PvaClientPutGet
*
* <a href = "../htmldoxygen/pvaClientGetData.html">Overview of PvaClientGetData</a>
*/
class epicsShareClass PvaClientGetData : public PvaClientData
{
@@ -731,10 +729,9 @@ private:
};
class PvaClientPostHandlerPvt; // private to PvaClientPutData
/**
/**
* @brief A class that holds data given to by PvaClientPut or PvaClientPutGet
*
* <a href = "../htmldoxygen/pvaClientPutData.html">Overview of PvaClientPutData</a>
*/
class epicsShareClass PvaClientPutData : public PvaClientData
{
@@ -742,7 +739,7 @@ public:
POINTER_DEFINITIONS(PvaClientPutData);
/**
* @brief Destructor
*/
*/
~PvaClientPutData() {}
/** @brief Put the value as a double.
* @param value The new value.
@@ -786,8 +783,6 @@ private:
/**
* @brief A class that holds data returned by PvaClientMonitor
*
* <a href = "../htmldoxygen/pvaClientMonitorData.html">Overview of PvaClientMonitorData</a>
*/
class epicsShareClass PvaClientMonitorData : public PvaClientData
{
@@ -795,7 +790,7 @@ public:
POINTER_DEFINITIONS(PvaClientMonitorData);
/**
* @brief Destructor
*/
*/
~PvaClientMonitorData() {}
/** @brief Get the overrun BitSet for the pvStructure
* This shows which fields have had more than one change.
@@ -828,7 +823,6 @@ private:
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientProcessRequester.html">Overview of PvaClientProcessRequester</a>
*/
class epicsShareClass PvaClientProcessRequester
{
@@ -863,7 +857,6 @@ typedef std::tr1::shared_ptr<ChannelProcessRequesterImpl> ChannelProcessRequeste
/**
* @brief An easy to use alternative to ChannelProcess.
*
* <a href = "../htmldoxygen/pvaClientProcess.html">Overview of PvaClientProcess</a>
*/
class epicsShareClass PvaClientProcess :
public std::tr1::enable_shared_from_this<PvaClientProcess>
@@ -881,7 +874,7 @@ public:
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest
);
/** @brief Destructor
*/
~PvaClientProcess();
@@ -935,7 +928,7 @@ private:
PvaClientPtr const &pvaClient,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest);
void checkProcessState();
enum ProcessConnectState {connectIdle,connectActive,connected};
@@ -968,7 +961,6 @@ typedef std::tr1::shared_ptr<ChannelGetRequesterImpl> ChannelGetRequesterImplPtr
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientGetRequester.html">Overview of PvaClientGetRequester</a>
*/
class epicsShareClass PvaClientGetRequester
{
@@ -997,7 +989,6 @@ public:
/**
* @brief An easy to use alternative to ChannelGet.
*
* <a href = "../htmldoxygen/pvaClientGet.html">Overview of PvaClientGet</a>
*/
class epicsShareClass PvaClientGet :
public std::tr1::enable_shared_from_this<PvaClientGet>
@@ -1113,7 +1104,6 @@ typedef std::tr1::shared_ptr<ChannelPutRequesterImpl> ChannelPutRequesterImplPtr
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientPutRequester.html">Overview of PvaClientPutRequester</a>
*/
class epicsShareClass PvaClientPutRequester
{
@@ -1153,7 +1143,6 @@ public:
/**
* @brief An easy to use alternative to ChannelPut.
*
* <a href = "../htmldoxygen/pvaClientPut.html">Overview of PvaClientPut</a>
*/
class epicsShareClass PvaClientPut :
public std::tr1::enable_shared_from_this<PvaClientPut>
@@ -1246,7 +1235,7 @@ private :
PvaClientPtr const &pvaClient,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest);
void checkConnectState();
enum PutConnectState {connectIdle,connectActive,connected};
@@ -1279,7 +1268,6 @@ typedef std::tr1::shared_ptr<ChannelPutGetRequesterImpl> ChannelPutGetRequesterI
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientPutGetRequester.html">Overview of PvaClientPutGetRequester</a>
*/
class epicsShareClass PvaClientPutGetRequester
{
@@ -1324,14 +1312,13 @@ public:
PvaClientPutGetPtr const & clientPutGet)
{
}
};
/**
/**
* @brief An easy to use alternative to ChannelPutGet.
*
* <a href = "../htmldoxygen/pvaClientPutGet.html">Overview of PvaClientPutGet</a>
*/
class epicsShareClass PvaClientPutGet :
public std::tr1::enable_shared_from_this<PvaClientPutGet>
@@ -1415,11 +1402,11 @@ public:
/** @brief Get the put data.
* @return The interface.
*/
PvaClientPutDataPtr getPutData();
PvaClientPutDataPtr getPutData();
/** @brief Get the get data.
* @return The interface.
*/
PvaClientGetDataPtr getGetData();
PvaClientGetDataPtr getGetData();
/** @brief Get the PvaClientChannel;
*
* @return The interface.
@@ -1478,11 +1465,9 @@ public:
friend class ChannelPutGetRequesterImpl;
};
//class ChannelMonitorRequester; // private to PvaClientMonitor
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientMonitorRequester.html">Overview of PvaClientMonitorRequester</a>
*/
class epicsShareClass PvaClientMonitorRequester
{
@@ -1523,7 +1508,6 @@ typedef std::tr1::shared_ptr<MonitorRequesterImpl> MonitorRequesterImplPtr;
/**
* @brief An easy to use alternative to Monitor.
*
* <a href = "../htmldoxygen/pvaClientMonitor.html">Overview of PvaClientMonitor</a>
*/
class epicsShareClass PvaClientMonitor :
public PvaClientChannelStateChangeRequester, // remove when deprecated create removed
@@ -1560,7 +1544,7 @@ public:
std::string const & request,
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester
= PvaClientChannelStateChangeRequesterPtr(),
PvaClientMonitorRequesterPtr const & monitorRequester
PvaClientMonitorRequesterPtr const & monitorRequester
= PvaClientMonitorRequesterPtr()
) EPICS_DEPRECATED;
/** @brief Destructor
@@ -1623,7 +1607,7 @@ public:
*
* @return The interface.
*/
PvaClientMonitorDataPtr getData();
PvaClientMonitorDataPtr getData();
private:
std::string getRequesterName();
void message(std::string const & message,epics::pvData::MessageType messageType);
@@ -1654,7 +1638,7 @@ private:
epics::pvData::Status monitorConnectStatus;
epics::pvData::MonitorPtr monitor;
epics::pvData::MonitorElementPtr monitorElement;
PvaClientMonitorRequesterWPtr pvaClientMonitorRequester;
MonitorConnectState connectState;
bool userPoll;
@@ -1672,7 +1656,6 @@ public:
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientRPCRequester.html">Overview of PvaClientRPCRequester</a>
*/
class PvaClientRPCRequester
{
@@ -1698,7 +1681,6 @@ typedef std::tr1::shared_ptr<RPCRequesterImpl> RPCRequesterImplPtr;
/**
* @brief An easy to use alternative to RPC.
*
* <a href = "../htmldoxygen/pvaClientRPC.html">Overview of PvaClientRPC</a>
*/
class epicsShareClass PvaClientRPC :
public std::tr1::enable_shared_from_this<PvaClientRPC>
@@ -1731,7 +1713,7 @@ public:
* @brief Set a timeout for a request.
* @param responseTimeout The time in seconds to wait for a request to complete.
*/
void setResponseTimeout(double responseTimeout)
void setResponseTimeout(double responseTimeout)
{
this->responseTimeout = responseTimeout;
}
@@ -1801,18 +1783,19 @@ private:
PvaClient::weak_pointer pvaClient;
epics::pvAccess::Channel::weak_pointer channel;
epics::pvData::PVStructurePtr pvRequest;
epics::pvData::Mutex mutex;
epics::pvData::Event waitForConnect;
epics::pvData::Event waitForDone;
PvaClientRPCRequesterWPtr pvaClientRPCRequester;
PvaClientRPCRequesterWPtr pvaClientRPCRequester;
RPCRequesterImplPtr rpcRequester;
epics::pvAccess::ChannelRPC::shared_pointer channelRPC;
epics::pvData::PVStructurePtr pvResponse;
enum RPCState {rpcIdle,rpcActive,rpcComplete};
RPCState rpcState;
epics::pvData::Status requestStatus;
double responseTimeout;
friend class RPCRequesterImpl;
};
@@ -1820,10 +1803,3 @@ private:
}}
#endif /* PVACLIENT_H */
/** @page Overview Documentation
*
* <a href = "../pvaClientCPP.html">pvaClientCPP.html</a>
*
*/
+84 -137
View File
@@ -21,14 +21,14 @@
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvaClientMultiChannelEpicsExportSharedSymbols
# undef pvaClientMultiChannelEpicsExportSharedSymbols
#endif
#include <pv/pvaClient.h>
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
class PvaClientMultiChannel;
@@ -66,14 +66,19 @@ public:
* @param pvaClient The interface to pvaClient.
* @param channelNames The names of the channel..
* @param providerName The name of the provider.
* This is also used for the provider for all channels
* with providerNames.size less than channelNames.size()
* @param maxNotConnected The maximum number of channels that can be disconnected.
* @param providerNames The providerName for each Channells
* @return The interface to the PvaClientMultiChannel
*/
static PvaClientMultiChannelPtr create(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelNames,
std::string const & providerName = "pva",
size_t maxNotConnected=0
size_t maxNotConnected=0,
epics::pvData::shared_vector<const std::string> const & providerNames
= epics::pvData::shared_vector<const std::string>()
);
/**
* @brief Destructor
@@ -115,7 +120,7 @@ public:
* @brief create a pvaClientMultiGetDouble
* @return The interface.
*/
PvaClientMultiGetDoublePtr createGet();
PvaClientMultiGetDoublePtr createGet();
/**
* @brief Create a pvaClientMultiPutDouble.
* @return The interface.
@@ -148,20 +153,24 @@ public:
private:
PvaClientMultiChannel(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelName,
epics::pvData::shared_vector<const std::string> const & channelNames,
std::string const & providerName,
size_t maxNotConnected);
size_t maxNotConnected,
epics::pvData::shared_vector<const std::string> const & providerNames);
void checkConnected();
PvaClientPtr pvaClient;
epics::pvData::shared_vector<const std::string> channelName;
epics::pvData::shared_vector<const std::string> channelNames;
std::string providerName;
size_t maxNotConnected;
epics::pvData::shared_vector<const std::string> const & providerNames;
size_t numChannel;
size_t numProviderNames;
epics::pvData::Mutex mutex;
size_t numConnected;
bool firstConnect;
PvaClientChannelArray pvaClientChannelArray;
epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
epics::pvData::CreateRequest::shared_pointer createRequest;
@@ -176,19 +185,16 @@ class epicsShareClass PvaClientMultiGetDouble :
public:
POINTER_DEFINITIONS(PvaClientMultiGetDouble);
/**
* @brief Create a PvaClientMultiGetDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientMultiGetDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiGetDouble();
/**
* @brief Create a channelGet for each channel.
*/
@@ -198,13 +204,6 @@ public:
* @return The double[] where each element is the value field of the corresponding channel.
*/
epics::pvData::shared_vector<double> get();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiGetDoublePtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientMultiGetDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -214,7 +213,7 @@ private:
PvaClientChannelArray pvaClientChannelArray;
size_t nchannel;
epics::pvData::Mutex mutex;
epics::pvData::shared_vector<double> doubleValue;
std::vector<PvaClientGetPtr> pvaClientGet;
bool isGetConnected;
@@ -229,15 +228,15 @@ class epicsShareClass PvaClientMultiPutDouble :
public:
POINTER_DEFINITIONS(PvaClientMultiPutDouble);
/** @brief Create a PvaClientMultiPutDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientMultiPutDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiPutDouble();
/**
* @brief Create a channelPut for each channel.
@@ -247,13 +246,7 @@ public:
* @param data The array of data for each channel.
*/
void put(epics::pvData::shared_vector<double> const &data);
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiPutDoublePtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientMultiPutDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -277,15 +270,15 @@ class epicsShareClass PvaClientMultiMonitorDouble :
public:
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
/** @brief Create a PvaClientMultiMonitorDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientMultiMonitorDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiMonitorDouble();
/**
* @brief Connect a channel monitor for each channel.
@@ -310,13 +303,7 @@ public:
* @return The double[] where each element is the value field of the corresponding channel.
*/
epics::pvData::shared_vector<double> get();
/** @brief Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiMonitorDoublePtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientMultiMonitorDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -341,18 +328,16 @@ class epicsShareClass PvaClientNTMultiGet :
public:
POINTER_DEFINITIONS(PvaClientNTMultiGet);
/**
* @brief Create a PvaClientNTMultiGet.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
* @return The interface.
*/
protected:
static PvaClientNTMultiGetPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiGet();
/**
* @brief Connect a channelGet for each channel.
@@ -360,20 +345,16 @@ public:
void connect();
/**
* @brief Get each channel.
*
* @param valueOnly use only value for union.
*/
void get();
void get(bool valueOnly = true);
/**
* @brief Get the data from the last get.
* @return the pvaClientNTMultiData.
*/
PvaClientNTMultiDataPtr getData();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiGetPtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientNTMultiGet(
epics::pvData::UnionConstPtr const & u,
@@ -386,8 +367,7 @@ private:
epics::pvData::PVStructurePtr pvRequest;
size_t nchannel;
epics::pvData::Mutex mutex;
PvaClientNTMultiDataPtr pvaClientNTMultiData;
std::vector<PvaClientGetPtr> pvaClientGet;
bool isConnected;
@@ -402,16 +382,15 @@ class epicsShareClass PvaClientNTMultiPut :
public:
POINTER_DEFINITIONS(PvaClientNTMultiPut);
/**
* @brief Create a PvaClientNTMultiPut.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientNTMultiPutPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiPut();
/**
* @brief Connect a channelPut for each channel.
@@ -424,15 +403,9 @@ public:
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
/**
* @brief Issue a put for each channel.
' */
void put();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiPutPtr getPtrSelf()
{
return shared_from_this();
}
void put();
private:
PvaClientNTMultiPut(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -458,16 +431,16 @@ class epicsShareClass PvaClientNTMultiMonitor :
public:
POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
/** @brief Create a PvaClientNTMultiMonitor.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
* @return The interface.
*/
protected:
static PvaClientNTMultiMonitorPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiMonitor();
/**
* @brief Connect to a channel monitor for each channel.
@@ -476,10 +449,11 @@ public:
/**
* @brief Poll each channel.
*
* @param valueOnly use only value for union.
* If any has new data it is used to update the double[].
* @return (false,true) if (no, at least one) value was updated.
*/
bool poll();
bool poll(bool valueOnly = true);
/**
* @brief Wait until poll returns true.
* @param secondsToWait The time to keep trying.
@@ -492,13 +466,7 @@ public:
* @return the pvaClientNTMultiData.
*/
PvaClientNTMultiDataPtr getData();
/** Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiMonitorPtr getPtrSelf()
{
return shared_from_this();
}
private:
PvaClientNTMultiMonitor(
epics::pvData::UnionConstPtr const & u,
@@ -525,61 +493,43 @@ class epicsShareClass PvaClientNTMultiData :
public:
POINTER_DEFINITIONS(PvaClientNTMultiData);
/**
* @brief Create a PvaClientNTMultiData.
*
* Normally only called by PvaClientNTMultiGet and PvaClientNTMultiMonitor.
* @param u The union interface for the value field of each channel.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
*/
static PvaClientNTMultiDataPtr create(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiData();
/**
/**
* @brief Get the number of channels.
* @return The number of channels.
*/
size_t getNumber();
/**
* @brief Set the timeStamp base for computing deltaTimes.
*/
void startDeltaTime();
/**
* @brief Update NTMultiChannel fields.
*/
void endDeltaTime();
/**
/**
* @brief Get the time when the last get was made.
* @return The timeStamp.
*/
epics::pvData::TimeStamp getTimeStamp();
epics::pvData::TimeStamp getTimeStamp();
/**
* @brief Get the NTMultiChannel.
* @return The value.
*/
epics::nt::NTMultiChannelPtr getNTMultiChannel();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
/**
* @brief Get channel change flags.
* @return Array of boolean fields that are set to true if corresponding channel changed
*/
PvaClientNTMultiDataPtr getPtrSelf()
{
return shared_from_this();
}
epics::pvData::shared_vector<epics::pvData::boolean> getChannelChangeFlags();
protected:
static PvaClientNTMultiDataPtr create(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
void startDeltaTime();
void endDeltaTime(bool valueOnly = true);
friend class PvaClientNTMultiGet;
friend class PvaClientNTMultiMonitor;
private:
PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
void setPVStructure(
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
@@ -592,6 +542,7 @@ private:
bool gotAlarm;
bool gotTimeStamp;
epics::pvData::shared_vector<epics::pvData::boolean> changeFlags;
epics::pvData::StructureConstPtr ntMultiChannelStructure;
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
epics::pvData::shared_vector<epics::pvData::int32> severity;
@@ -603,13 +554,9 @@ private:
epics::pvData::Alarm alarm;
epics::pvData::TimeStamp timeStamp;;
epics::pvData::PVTimeStamp pvTimeStamp;
friend class PvaClientNTMultiGet;
friend class PvaClientNTMultiPut;
friend class PvaClientNTMultiMonitor;
};
}}
#endif /* PVACLIENTMULTICHANNEL_H */
+5 -6
View File
@@ -23,7 +23,7 @@ using namespace epics::pvAccess;
using namespace epics::pvAccess::ca;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
class epicsShareClass PvaClientChannelCache
@@ -42,7 +42,7 @@ public:
private:
map<string,PvaClientChannelPtr> pvaClientChannelMap;
};
PvaClientChannelPtr PvaClientChannelCache::getChannel(
string const & channelName,
string const & providerName)
@@ -77,7 +77,7 @@ void PvaClientChannelCache::showCache()
string providerName = channel->getProvider()->getProviderName();
cout << "channel " << channelName << " provider " << providerName << endl;
pvaChannel->showCache();
}
}
}
size_t PvaClientChannelCache::cacheSize()
@@ -137,7 +137,7 @@ PvaClient::PvaClient(std::string const & providerNames)
}
CAClientFactory::start();
caStarted = true;
} else {
} else {
if(!channelRegistry->getProvider(providerName)) {
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
}
@@ -191,7 +191,7 @@ PvaClientChannelPtr PvaClient::channel(
std::string const & providerName,
double timeOut)
{
PvaClientChannelPtr pvaClientChannel =
PvaClientChannelPtr pvaClientChannel =
pvaClientChannelCache->getChannel(channelName,providerName);
if(pvaClientChannel) return pvaClientChannel;
pvaClientChannel = createChannel(channelName,providerName);
@@ -231,4 +231,3 @@ size_t PvaClient::cacheSize()
}
}}
+8 -42
View File
@@ -179,13 +179,10 @@ void PvaClientChannel::channelCreated(const Status& status, Channel::shared_poin
}
if(!status.isOK()) {
string message("PvaClientChannel::channelCreated");
message += " channel " + channelName
+ " status " + status.getMessage() + " why??";
throw std::runtime_error(message);
}
if(channel->isConnected()) {
connectState = connected;
waitForConnect.signal();
}
}
void PvaClientChannel::channelStateChange(
@@ -202,9 +199,6 @@ void PvaClientChannel::channelStateChange(
if(connectState==connectActive) waitingForConnect = true;
if(connectionState!=Channel::CONNECTED) {
Lock xx(mutex);
string mess(channelName +
" connection state " + Channel::ConnectionStateNames[connectionState]);
message(mess,errorMessage);
connectState = notConnected;
} else {
Lock xx(mutex);
@@ -267,7 +261,7 @@ void PvaClientChannel::connect(double timeout)
Status status = waitConnect(timeout);
if(status.isOK()) return;
if(PvaClient::getDebug()) cout << "PvaClientChannel::connect waitConnect failed\n";
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::connect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -319,18 +313,11 @@ Status PvaClientChannel::waitConnect(double timeout)
return Status(Status::STATUSTYPE_ERROR," not connected");
}
PvaClientFieldPtr PvaClientChannel::createField(string const & subField)
{
if(connectState!=connected) connect(5.0);
throw std::runtime_error("PvaClientChannel::createField not implemented");
}
PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createProcess invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -364,7 +351,7 @@ PvaClientGetPtr PvaClientChannel::createGet(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createGet invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -419,7 +406,7 @@ PvaClientPutPtr PvaClientChannel::createPut(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createPut invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -477,7 +464,7 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createPutGet invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -493,27 +480,6 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvReque
return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest);
}
PvaClientArrayPtr PvaClientChannel::createArray(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
+ " PvaClientChannel::createArray invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
}
return createArray(pvRequest);
}
PvaClientArrayPtr PvaClientChannel::createArray(PVStructurePtr const & pvRequest)
{
if(connectState!=connected) connect(5.0);
throw std::runtime_error("PvaClientChannel::createArray not implemented");
}
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
{
PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
@@ -541,7 +507,7 @@ PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createMonitor invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -561,7 +527,7 @@ PVStructurePtr PvaClientChannel::rpc(
PVStructurePtr const & pvRequest,
PVStructurePtr const & pvArgument)
{
PvaClientRPCPtr rpc = createRPC(pvRequest);
return rpc->request(pvArgument);
}
+191 -112
View File
@@ -11,9 +11,17 @@
#include <typeinfo>
#include <sstream>
#include <istream>
#include <ostream>
#include <pv/createRequest.h>
#include <pv/convert.h>
#include <pv/pvEnumerated.h>
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
# include <pv/json.h>
# define USE_JSON
#endif
#define epicsExportSharedSymbols
@@ -49,6 +57,30 @@ PvaClientData::PvaClientData(StructureConstPtr const & structure)
{
}
PVFieldPtr PvaClientData::getSinglePVField()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getSinglePVField\n";
PVStructurePtr pvStructure = getPVStructure();
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()==0) {
throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for empty structure");
}
if(fieldPtrArray.size()!=1) {
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type!=epics::pvData::structure) return pvValue;
}
throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type!=epics::pvData::structure) return pvField;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
void PvaClientData::checkValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n";
@@ -106,6 +138,7 @@ void PvaClientData::setData(
pvValue = pvStructure->getSubField("value");
}
bool PvaClientData::hasValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
@@ -171,34 +204,12 @@ PVScalarArrayPtr PvaClientData::getScalarArrayValue()
double PvaClientData::getDouble()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n";
PVScalarPtr pvScalar;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
}
if(!pvScalar) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::getDouble() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalar) {
throw std::logic_error(
"PvaClientData::getDouble() did not find a scalar field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::getDouble() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
@@ -214,70 +225,24 @@ double PvaClientData::getDouble()
string PvaClientData::getString()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getString\n";
PVScalarPtr pvScalar;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
}
if(!pvScalar) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::getString() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalar) {
throw std::logic_error(
"PvaClientData::getString() did not find a scalar field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::getString() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
return convert->toString(pvScalar);
}
shared_vector<const double> PvaClientData::getDoubleArray()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n";
PVScalarArrayPtr pvScalarArray;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
}
}
if(!pvScalarArray) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::getDoubleArray() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalarArray) {
throw std::logic_error(
"PvaClientData::getDoubleArray() did not find a scalarArray field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::getDoubleArray() did not find a scalarArray field");
}
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::logic_error(
@@ -291,36 +256,12 @@ shared_vector<const double> PvaClientData::getDoubleArray()
shared_vector<const string> PvaClientData::getStringArray()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n";
PVScalarArrayPtr pvScalarArray;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
}
}
if(!pvScalarArray) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::getStringArray() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalarArray) {
throw std::logic_error(
"PvaClientData::getStringArray() did not find a scalarArray field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::getStringArray() did not find a scalarArray field");
}
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
shared_vector<const string> retValue;
pvScalarArray->getAs<const string>(retValue);
return retValue;
@@ -358,4 +299,142 @@ TimeStamp PvaClientData::getTimeStamp()
throw std::runtime_error(messagePrefix + noTimeStamp);
}
void PvaClientData::zeroArrayLength()
{
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
zeroArrayLength(pvStructure);
}
void PvaClientData::parse(
const std::string &arg,const PVFieldPtr &dest,BitSetPtr & bitSet)
{
#ifdef USE_JSON
std::istringstream strm(arg);
parseJSON(strm, dest,&(*bitSet));
#else
throw std::runtime_error("JSON support not built");
#endif
}
void PvaClientData::parse(
const std::string &arg,const PVUnionPtr &pvUnion)
{
if(pvUnion->getUnion()->isVariant()) {
throw std::runtime_error(messagePrefix + "varient union not implemented");
}
size_t iequals = arg.find_first_of('=');
string field;
string rest;
if(iequals==std::string::npos) {
string mess(arg);
mess += " was expected to start with field=";
throw std::runtime_error(messagePrefix + mess);
}
field = arg.substr(0,iequals);
rest = arg.substr(iequals+1);
PVFieldPtr pvField(pvUnion->select(field));
if(pvField->getField()->getType()==epics::pvData::union_) {
PVUnionPtr pvu = static_pointer_cast<PVUnion>(pvField);
parse(rest,pvu);
return;
}
BitSetPtr bs;
parse(rest,pvField,bs);
return;
}
void PvaClientData::parse(const std::vector<std::string> &args)
{
if(!pvStructure) throw std::runtime_error(messagePrefix + noStructure);
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t num = args.size();
if(num<1) throw std::runtime_error(messagePrefix + " no arguments");
for(size_t i=0; i<num; ++i)
{
string val = args[i];
size_t iequals = val.find_first_of('=');
string field;
string rest(val);
if(iequals==std::string::npos) {
parse(rest,pvStructure,bitSet);
continue;
}
field = val.substr(0,iequals);
rest = val.substr(iequals+1);
if(field.size()==std::string::npos) {
parse(rest,pvStructure,bitSet);
continue;
}
PVFieldPtr pvField(pvStructure->getSubField(field));
if(!pvField) throw std::runtime_error(messagePrefix + field +" does not exist");
// look for enumerated structure
PVEnumerated pvEnumerated;
bool result = pvEnumerated.attach(pvField);
if(result) {
PVStringArray::const_svector choices(pvEnumerated.getChoices());
for(size_t i=0; i<choices.size(); ++i) {
if(choices[i]==rest) {
pvEnumerated.setIndex(i);
return;
}
}
}
// look for union
PVUnionPtr pvUnion(pvStructure->getSubField<PVUnion>(field));
if(pvUnion) {
parse(rest,pvUnion);
bitSet->set(pvUnion->getFieldOffset());
return;
}
parse(rest,pvField,bitSet);
}
}
void PvaClientData::streamJSON(
std::ostream& strm,
bool ignoreUnprintable,
bool multiLine)
{
#ifdef USE_JSON
JSONPrintOptions opts;
opts.ignoreUnprintable = ignoreUnprintable;
opts.multiLine = multiLine;
printJSON(strm,*pvStructure,*bitSet,opts);
#else
throw std::runtime_error("JSON support not built");
#endif
}
void PvaClientData::zeroArrayLength(const PVStructurePtr &pvStructure)
{
const PVFieldPtrArray pvFields(pvStructure->getPVFields());
for(size_t i=0; i<pvFields.size(); ++i) {
PVFieldPtr pvField = pvFields[i];
Type type(pvField->getField()->getType());
switch(type) {
case scalarArray:
{
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
pvScalarArray->setLength(0);
}
break;
case structureArray:
{
PVStructureArrayPtr pvStructureArray = static_pointer_cast<PVStructureArray>(pvField);
pvStructureArray->setLength(0);
}
break;
case epics::pvData::structure:
{
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
zeroArrayLength(pvStructure);
}
break;
default:
break;
}
}
}
}}
+11 -50
View File
@@ -42,7 +42,7 @@ public:
return clientGet->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return;
clientGet->message(message,messageType);
@@ -55,7 +55,7 @@ public:
{
PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return;
clientGet->channelGetConnect(status,channelGet,structure);
clientGet->channelGetConnect(status,channelGet,structure);
}
virtual void getDone(
@@ -134,19 +134,14 @@ void PvaClientGet::checkConnectState()
}
}
// from ChannelGetRequester
string PvaClientGet::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientGet::getRequesterName PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientGet::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientGet::channelGetConnect(
@@ -162,27 +157,19 @@ void PvaClientGet::channelGetConnect(
}
{
Lock xx(mutex);
this->channelGet = channelGet;
channelGetConnectStatus = status;
if(status.isOK()) {
channelGetConnectStatus = status;
this->channelGet = channelGet;
connectState = connected;
pvaClientData = PvaClientGetData::create(structure);
pvaClientData->setMessagePrefix(channelGet->getChannel()->getChannelName());
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientGet::channelGetConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
channelGetConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
}
}
waitForConnect.signal();
}
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) {
req->channelGetConnect(status,shared_from_this());
}
waitForConnect.signal();
}
}
void PvaClientGet::getDone(
@@ -200,16 +187,16 @@ void PvaClientGet::getDone(
{
Lock xx(mutex);
channelGetStatus = status;
getState = getComplete;
if(status.isOK()) {
pvaClientData->setData(pvStructure,bitSet);
}
getState = getComplete;
waitForGet.signal();
}
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) {
req->getDone(status,shared_from_this());
}
waitForGet.signal();
}
void PvaClientGet::connect()
@@ -248,20 +235,7 @@ Status PvaClientGet::waitConnect()
cout << "PvaClientGet::waitConnect channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
{
Lock xx(mutex);
if(connectState==connected) {
if(!channelGetConnectStatus.isOK()) connectState = connectIdle;
return channelGetConnectStatus;
}
if(connectState!=connectActive) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientGet::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
}
waitForConnect.wait();
if(!channelGetConnectStatus.isOK()) connectState = connectIdle;
return channelGetConnectStatus;
}
@@ -301,20 +275,7 @@ Status PvaClientGet::waitGet()
cout << "PvaClientGet::waitGet channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
{
Lock xx(mutex);
if(getState==getComplete) {
getState = getIdle;
return channelGetStatus;
}
if(getState!=getActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientGet::waitGet llegal get state";
throw std::runtime_error(message);
}
}
waitForGet.wait();
getState = getComplete;
return channelGetStatus;
}
PvaClientGetDataPtr PvaClientGet::getData()
+23 -34
View File
@@ -44,7 +44,7 @@ public:
return clientMonitor->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->message(message,messageType);
@@ -57,21 +57,21 @@ public:
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->monitorConnect(status,monitor,structure);
clientMonitor->monitorConnect(status,monitor,structure);
}
virtual void unlisten(epics::pvData::MonitorPtr const & monitor)
virtual void unlisten(MonitorPtr const & monitor)
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->unlisten(monitor);
clientMonitor->unlisten(monitor);
}
virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor)
virtual void monitorEvent(MonitorPtr const & monitor)
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->monitorEvent(monitor);
clientMonitor->monitorEvent(monitor);
}
};
@@ -131,7 +131,7 @@ PvaClientMonitor::PvaClientMonitor(
{
if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::PvaClientMonitor\n"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
@@ -201,16 +201,12 @@ void PvaClientMonitor::checkMonitorState()
string PvaClientMonitor::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientMonitor::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientMonitor::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientMonitor::monitorConnect(
@@ -226,19 +222,24 @@ void PvaClientMonitor::monitorConnect(
}
{
Lock xx(mutex);
this->monitor = monitor;
if(!status.isOK()) {
monitorConnectStatus = status;
if(status.isOK()) {
this->monitor = monitor;
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientMonitor::monitorConnect)")
+ "\nchannelName=" + pvaClientChannel->getChannel()->getChannelName()
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
waitForConnect.signal();
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->monitorConnect(status,shared_from_this(),structure);
return;
}
}
bool signal = (connectState==connectWait) ? true : false;
monitorConnectStatus = status;
connectState = connected;
if(isStarted) {
if(PvaClient::getDebug()) {
@@ -247,6 +248,9 @@ void PvaClientMonitor::monitorConnect(
<< " is already started "
<< endl;
}
waitForConnect.signal();
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->monitorConnect(status,shared_from_this(),structure);
return;
}
pvaClientData = PvaClientMonitorData::create(structure);
@@ -276,7 +280,7 @@ void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
cout << "PvaClientMonitor::monitorEvent"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
if(req) req->event(shared_from_this());
if(userWait) waitForEvent.signal();
@@ -288,9 +292,7 @@ void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
if(req) {
req->unlisten();
return;
}
cerr << pvaClientChannel->getChannel()->getChannelName() + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n";
}
@@ -300,7 +302,7 @@ void PvaClientMonitor::connect()
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
string message = string("channel ")
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::connect "
+ status.getMessage();
@@ -327,20 +329,7 @@ Status PvaClientMonitor::waitConnect()
<< pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(connectState==connected) {
if(!monitorConnectStatus.isOK()) connectState = connectIdle;
return monitorConnectStatus;
}
if(connectState!=connectWait) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
}
waitForConnect.wait();
connectState = monitorConnectStatus.isOK() ? connected : connectIdle;
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::waitConnect"
<< " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected")
@@ -438,7 +427,7 @@ bool PvaClientMonitor::poll()
if(!monitorElement) return false;
userPoll = true;
pvaClientData->setData(monitorElement);
return true;
return true;
}
bool PvaClientMonitor::waitEvent(double secondsToWait)
+32 -18
View File
@@ -28,26 +28,32 @@ static CreateRequest::shared_pointer createRequestPvt = CreateRequest::create()
PvaClientMultiChannelPtr PvaClientMultiChannel::create(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const string> const & channelNames,
shared_vector<const string> const & channelNames,
string const & providerName,
size_t maxNotConnected)
size_t maxNotConnected,
shared_vector<const string> const & providerNames)
{
return PvaClientMultiChannelPtr(
new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected));
new PvaClientMultiChannel(
pvaClient,channelNames,providerName,maxNotConnected,providerNames));
}
PvaClientMultiChannel::PvaClientMultiChannel(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const string> const & channelName,
shared_vector<const string> const & channelNames,
string const & providerName,
size_t maxNotConnected)
size_t maxNotConnected,
shared_vector<const string> const & providerNames)
: pvaClient(pvaClient),
channelName(channelName),
channelNames(channelNames),
providerName(providerName),
maxNotConnected(maxNotConnected),
numChannel(channelName.size()),
providerNames(providerNames),
numChannel(channelNames.size()),
numProviderNames(providerNames.size()),
numConnected(0),
firstConnect(true),
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
createRequest(CreateRequest::create())
@@ -62,25 +68,34 @@ PvaClientMultiChannel::~PvaClientMultiChannel()
void PvaClientMultiChannel::checkConnected()
{
if(numConnected==0) connect();
if(firstConnect) {
connect();
firstConnect = false;
}
}
epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames()
shared_vector<const string> PvaClientMultiChannel::getChannelNames()
{
return channelName;
return channelNames;
}
Status PvaClientMultiChannel::connect(double timeout)
{
if(!firstConnect) return Status::Ok;
firstConnect = false;
for(size_t i=0; i< numChannel; ++i) {
pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName);
if(numProviderNames<=i) {
pvaClientChannelArray[i] = pvaClient->createChannel(channelNames[i],providerName);
} else {
pvaClientChannelArray[i] = pvaClient->createChannel(channelNames[i],providerNames[i]);
}
pvaClientChannelArray[i]->issueConnect();
}
Status returnStatus = Status::Ok;
Status status = Status::Ok;
size_t numBad = 0;
for(size_t i=0; i< numChannel; ++i) {
if(numBad==0) {
if(numBad==0) {
status = pvaClientChannelArray[i]->waitConnect(timeout);
} else {
status = pvaClientChannelArray[i]->waitConnect(.001);
@@ -88,11 +103,10 @@ Status PvaClientMultiChannel::connect(double timeout)
if(status.isOK()) {
++numConnected;
isConnected[i] = true;
continue;
} else {
if(returnStatus.isOK()) returnStatus = status;
++numBad;
}
if(returnStatus.isOK()) returnStatus = status;
++numBad;
if(numBad>maxNotConnected) break;
}
return numBad>maxNotConnected ? returnStatus : Status::Ok;
}
@@ -115,7 +129,7 @@ bool PvaClientMultiChannel::connectionChange()
return false;
}
epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
{
for(size_t i=0; i<numChannel; ++i) {
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
@@ -140,7 +154,7 @@ PvaClientPtr PvaClientMultiChannel::getPvaClient()
return pvaClient;
}
PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
{
+16 -7
View File
@@ -21,7 +21,7 @@ using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create(
@@ -39,7 +39,7 @@ PvaClientMultiGetDouble::PvaClientMultiGetDouble(
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()),
doubleValue(shared_vector<double>(nchannel)),
doubleValue( shared_vector<double>(nchannel)),
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
isGetConnected(false)
{
@@ -53,7 +53,7 @@ PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
void PvaClientMultiGetDouble::connect()
{
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
shared_vector<epics::pvData::boolean>isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
for(size_t i=0; i<nchannel; ++i)
{
@@ -75,14 +75,14 @@ void PvaClientMultiGetDouble::connect()
isGetConnected = true;
}
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
shared_vector<double> PvaClientMultiGetDouble::get()
{
if(!isGetConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientGet[i]) pvaClientGet[i]=pvaClientChannelArray[i]->createGet("value");
pvaClientGet[i]->issueGet();
}
}
@@ -96,13 +96,22 @@ epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
throw std::runtime_error(message);
}
}
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i])
{
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure();
doubleValue[i] = getConvert()->toDouble(pvStructure->getSubField<PVScalar>("value"));
PVScalarPtr pvScalar(pvStructure->getSubField<PVScalar>("value"));
if(pvScalar) {
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(ScalarTypeFunc::isNumeric(scalarType)) {
doubleValue[i] = getConvert()->toDouble(pvScalar);
} else {
doubleValue[i] = epicsNAN;
}
} else {
doubleValue[i] = epicsNAN;
}
} else {
doubleValue[i] = epicsNAN;
}
+13 -2
View File
@@ -21,7 +21,7 @@ using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
@@ -90,6 +90,17 @@ bool PvaClientMultiMonitorDouble::poll()
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientMonitor[i]){
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor("value");
pvaClientMonitor[i]->issueConnect();
Status status = pvaClientMonitor[i]->waitConnect();
if(!status.isOK()) {
string message = string("channel ") + pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
pvaClientMonitor[i]->start();
}
if(pvaClientMonitor[i]->poll()) {
doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
pvaClientMonitor[i]->releaseEvent();
@@ -116,7 +127,7 @@ bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent)
return false;
}
epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get()
shared_vector<double> PvaClientMultiMonitorDouble::get()
{
return doubleValue;
}
+13 -5
View File
@@ -21,7 +21,7 @@ using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
@@ -76,7 +76,7 @@ void PvaClientMultiPutDouble::connect()
isPutConnected = true;
}
void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data)
void PvaClientMultiPutDouble::put(shared_vector<double> const &data)
{
if(!isPutConnected) connect();
if(data.size()!=nchannel) {
@@ -86,10 +86,18 @@ void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &da
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientPut[i]) pvaClientPut[i]=pvaClientChannelArray[i]->createPut("value");
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
getConvert()->fromDouble(pvValue,data[i]);
pvaClientPut[i]->issuePut();
PVScalarPtr pvScalar= pvTop->getSubField<PVScalar>("value");
if(pvScalar && ScalarTypeFunc::isNumeric(pvScalar->getScalar()->getScalarType())) {
getConvert()->fromDouble(pvScalar,data[i]);
pvaClientPut[i]->issuePut();
} else {
string message = string("channel ")
+ pvaClientChannelArray[i]->getChannelName()
+ " is not a numeric scalar";
throw std::runtime_error(message);
}
}
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut();
+48 -34
View File
@@ -20,10 +20,10 @@ using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
epics::pvData::UnionConstPtr const & u,
UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
PVStructurePtr const & pvRequest)
@@ -33,22 +33,21 @@ PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
}
PvaClientNTMultiData::PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u,
UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest)
PVStructurePtr const & pvRequest)
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()),
gotAlarm(false),
gotTimeStamp(false)
{
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
if(!pvValue) {
throw std::runtime_error("pvRequest did not specify value");
}
changeFlags = shared_vector<epics::pvData::boolean>(nchannel);
topPVStructure.resize(nchannel);
unionValue.resize(nchannel);
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(size_t i=0; i< nchannel; ++i) {
@@ -67,7 +66,7 @@ PvaClientNTMultiData::PvaClientNTMultiData(
severity.resize(nchannel);
status.resize(nchannel);
message.resize(nchannel);
}
if(pvRequest->getSubField("field.timeStamp")) {
gotTimeStamp = true;
@@ -88,30 +87,24 @@ PvaClientNTMultiData::~PvaClientNTMultiData()
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n";
}
void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
{
FieldConstPtr field = structure->getField("value");
if(!field) {
string message = "channel "
+ pvaClientChannelArray[index]->getChannel()->getChannelName()
+ " does not have top level value field";
throw std::runtime_error(message);
}
}
void PvaClientNTMultiData::setPVStructure(
PVStructurePtr const &pvStructure,size_t index)
{
topPVStructure[index] = pvStructure;
}
shared_vector<epics::pvData::boolean> PvaClientNTMultiData::getChannelChangeFlags()
{
return changeFlags;
}
size_t PvaClientNTMultiData::getNumber()
{
return nchannel;
}
void PvaClientNTMultiData::startDeltaTime()
{
for(size_t i=0; i<nchannel; ++i)
@@ -137,28 +130,49 @@ void PvaClientNTMultiData::startDeltaTime()
}
void PvaClientNTMultiData::endDeltaTime()
void PvaClientNTMultiData::endDeltaTime(bool valueOnly)
{
for(size_t i=0; i<nchannel; ++i)
{
PVStructurePtr pvst = topPVStructure[i];
if(!pvst) {
unionValue[i] = PVUnionPtr();
} else if(unionValue[i]) {
unionValue[i]->set(pvst->getSubField("value"));
changeFlags[i] = false;
if(pvst&&unionValue[i]) {
changeFlags[i] = true;
if(valueOnly) {
PVFieldPtr pvValue = pvst->getSubField("value");
if(pvValue) {
unionValue[i]->set(pvst->getSubField("value"));
}
} else {
unionValue[i]->set(pvst);
}
if(gotAlarm)
{
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
message[i] = pvst->getSubField<PVString>("alarm.message")->get();
PVIntPtr pvSeverity = pvst->getSubField<PVInt>("alarm.severity");
PVIntPtr pvStatus = pvst->getSubField<PVInt>("alarm.status");
PVStringPtr pvMessage = pvst->getSubField<PVString>("alarm.message");
if(pvSeverity&&pvStatus&&pvMessage) {
severity[i] = pvSeverity->get();
status[i] = pvStatus->get();
message[i] = pvMessage->get();
} else {
severity[i] = undefinedAlarm;
status[i] = undefinedStatus;
message[i] = "no alarm field";
}
}
if(gotTimeStamp)
{
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
PVLongPtr pvEpoch = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch");
PVIntPtr pvNano = pvst->getSubField<PVInt>("timeStamp.nanoseconds");
PVIntPtr pvTag = pvst->getSubField<PVInt>("timeStamp.userTag");
if(pvEpoch&&pvNano&&pvTag) {
secondsPastEpoch[i] = pvEpoch->get();
nanoseconds[i] = pvNano->get();
userTag[i] = pvTag->get();
}
}
}
}
}
}
@@ -173,7 +187,7 @@ NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(ntMultiChannelStructure);
NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure);
ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames());
shared_vector<epics::pvData::PVUnionPtr> val(nchannel);
shared_vector<PVUnionPtr> val(nchannel);
for(size_t i=0; i<nchannel; ++i) val[i] = unionValue[i];
ntMultiChannel->getValue()->replace(freeze(val));
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
+12 -11
View File
@@ -20,7 +20,7 @@ using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
@@ -38,7 +38,7 @@ PvaClientNTMultiGet::PvaClientNTMultiGet(
UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest)
PVStructurePtr const & pvRequest)
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
pvRequest(pvRequest),
@@ -63,13 +63,10 @@ void PvaClientNTMultiGet::connect()
{
pvaClientGet.resize(nchannel);
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request);
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(pvRequest);
pvaClientGet[i]->issueConnect();
}
}
@@ -78,7 +75,7 @@ void PvaClientNTMultiGet::connect()
if(isConnected[i]) {
Status status = pvaClientGet[i]->waitConnect();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelGet::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -86,14 +83,18 @@ void PvaClientNTMultiGet::connect()
this->isConnected = true;
}
void PvaClientNTMultiGet::get()
void PvaClientNTMultiGet::get(bool valueOnly)
{
if(!isConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientGet[i]){
pvaClientGet[i]=pvaClientChannelArray[i]->createGet(pvRequest);
pvaClientGet[i]->connect();
}
pvaClientGet[i]->issueGet();
}
}
@@ -102,7 +103,7 @@ void PvaClientNTMultiGet::get()
if(isConnected[i]) {
Status status = pvaClientGet[i]->waitGet();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelGet::waitGet " + status.getMessage();
throw std::runtime_error(message);
}
@@ -114,7 +115,7 @@ void PvaClientNTMultiGet::get()
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
}
}
pvaClientNTMultiData->endDeltaTime();
pvaClientNTMultiData->endDeltaTime(valueOnly);
}
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
+16 -14
View File
@@ -23,12 +23,12 @@ using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest)
PVStructurePtr const & pvRequest)
{
UnionConstPtr u = getFieldCreate()->createVariantUnion();
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
@@ -67,13 +67,10 @@ void PvaClientNTMultiMonitor::connect()
{
pvaClientMonitor.resize(nchannel);
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(pvRequest);
pvaClientMonitor[i]->issueConnect();
}
}
@@ -82,7 +79,7 @@ void PvaClientNTMultiMonitor::connect()
if(isConnected[i]) {
Status status = pvaClientMonitor[i]->waitConnect();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -94,24 +91,29 @@ void PvaClientNTMultiMonitor::connect()
this->isConnected = true;
}
bool PvaClientNTMultiMonitor::poll()
bool PvaClientNTMultiMonitor::poll(bool valueOnly)
{
if(!isConnected) connect();
bool result = false;
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
pvaClientNTMultiData->startDeltaTime();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
pvaClientNTMultiData->startDeltaTime();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(pvaClientMonitor[i]->poll()) {
if(!pvaClientMonitor[i]){
pvaClientMonitor[i]=pvaClientChannelArray[i]->createMonitor(pvRequest);
pvaClientMonitor[i]->connect();
pvaClientMonitor[i]->start();
}
if(pvaClientMonitor[i]->poll()) {
pvaClientNTMultiData->setPVStructure(
pvaClientMonitor[i]->getData()->getPVStructure(),i);
pvaClientMonitor[i]->getData()->getPVStructure(),i);
pvaClientMonitor[i]->releaseEvent();
result = true;
}
}
}
if(result) pvaClientNTMultiData->endDeltaTime();
}
if(result) pvaClientNTMultiData->endDeltaTime(valueOnly);
return result;
}
+43 -12
View File
@@ -22,7 +22,7 @@ using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
PvaClientMultiChannelPtr const &pvaMultiChannel,
@@ -38,8 +38,8 @@ PvaClientNTMultiPut::PvaClientNTMultiPut(
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()),
unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())),
value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())),
unionValue(shared_vector<PVUnionPtr>(nchannel,PVUnionPtr())),
value(shared_vector<PVFieldPtr>(nchannel,PVFieldPtr())),
isConnected(false)
{
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::PvaClientNTMultiPut()\n";
@@ -67,7 +67,7 @@ void PvaClientNTMultiPut::connect()
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitConnect();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -83,7 +83,7 @@ void PvaClientNTMultiPut::connect()
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitGet();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitGet " + status.getMessage();
throw std::runtime_error(message);
}
@@ -102,9 +102,26 @@ void PvaClientNTMultiPut::connect()
this->isConnected = true;
}
shared_vector<epics::pvData::PVUnionPtr> PvaClientNTMultiPut::getValues()
shared_vector<PVUnionPtr> PvaClientNTMultiPut::getValues()
{
if(!isConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientPut[i]){
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
pvaClientPut[i]->connect();
pvaClientPut[i]->get();
value[i] = pvaClientPut[i]->getData()->getValue();
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
builder->add("value",value[i]->getField());
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
}
}
}
return unionValue;
}
@@ -115,15 +132,29 @@ void PvaClientNTMultiPut::put()
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientPut[i]){
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
pvaClientPut[i]->connect();
pvaClientPut[i]->get();
value[i] = pvaClientPut[i]->getData()->getValue();
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
builder->add("value",value[i]->getField());
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
}
value[i]->copy(*unionValue[i]->get());
pvaClientPut[i]->issuePut();
}
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitPut " + status.getMessage();
throw std::runtime_error(message);
}
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitPut " + status.getMessage();
throw std::runtime_error(message);
}
}
}
+9 -45
View File
@@ -42,7 +42,7 @@ public:
return clientProcess->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return;
clientProcess->message(message,messageType);
@@ -54,7 +54,7 @@ public:
{
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return;
clientProcess->channelProcessConnect(status,channelProcess);
clientProcess->channelProcessConnect(status,channelProcess);
}
virtual void processDone(
@@ -111,19 +111,14 @@ PvaClientProcess::~PvaClientProcess()
}
}
// from ChannelProcessRequester
string PvaClientProcess::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientProcess::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientProcess::channelProcessConnect(
@@ -138,25 +133,17 @@ void PvaClientProcess::channelProcessConnect(
}
{
Lock xx(mutex);
this->channelProcess = channelProcess;
channelProcessConnectStatus = status;
if(status.isOK()) {
channelProcessConnectStatus = status;
this->channelProcess = channelProcess;
connectState = connected;
} else {
stringstream ss;
ss << pvRequest;
string message = string("PvaClientProcess::channelProcessConnect")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
channelProcessConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
}
}
waitForConnect.signal();
}
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) {
req->channelProcessConnect(status,shared_from_this());
}
waitForConnect.signal();
}
void PvaClientProcess::processDone(
@@ -173,13 +160,12 @@ void PvaClientProcess::processDone(
Lock xx(mutex);
channelProcessStatus = status;
processState = processComplete;
waitForProcess.signal();
}
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) {
req->processDone(status,shared_from_this());
}
waitForProcess.signal();
}
void PvaClientProcess::connect()
@@ -221,17 +207,7 @@ Status PvaClientProcess::waitConnect()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connected) {
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
return channelProcessConnectStatus;
}
if(connectState!=connectActive) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientProcess illegal connect state ";
throw std::runtime_error(message);
}
waitForConnect.wait();
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
return channelProcessConnectStatus;
}
@@ -274,18 +250,6 @@ Status PvaClientProcess::waitProcess()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(processState==processComplete) {
processState = processIdle;
return channelProcessStatus;
}
if(processState!=processActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientProcess::waitProcess llegal process state";
throw std::runtime_error(message);
}
}
waitForProcess.wait();
processState = processComplete;
return channelProcessStatus;
+21 -66
View File
@@ -42,7 +42,7 @@ public:
return clientPut->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return;
clientPut->message(message,messageType);
@@ -55,7 +55,7 @@ public:
{
PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return;
clientPut->channelPutConnect(status,channelPut,structure);
clientPut->channelPutConnect(status,channelPut,structure);
}
virtual void getDone(
@@ -138,16 +138,12 @@ void PvaClientPut::checkConnectState()
string PvaClientPut::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientPut::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientPut::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientPut::channelPutConnect(
@@ -163,27 +159,19 @@ void PvaClientPut::channelPutConnect(
}
{
Lock xx(mutex);
this->channelPut = channelPut;
channelPutConnectStatus = status;
if(status.isOK()) {
channelPutConnectStatus = status;
this->channelPut = channelPut;
connectState = connected;
pvaClientData = PvaClientPutData::create(structure);
pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName());
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientPut::channelPutConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
}
}
waitForConnect.signal();
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->channelPutConnect(status,shared_from_this());
}
waitForConnect.signal();
}
void PvaClientPut::getDone(
@@ -207,14 +195,14 @@ void PvaClientPut::getDone(
BitSetPtr bs = pvaClientData->getChangedBitSet();
bs->clear();
*bs |= *bitSet;
putState = putComplete;
}
}
putState = putComplete;
waitForGetPut.signal();
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->getDone(status,shared_from_this());
}
waitForGetPut.signal();
}
void PvaClientPut::putDone(
@@ -231,12 +219,10 @@ void PvaClientPut::putDone(
Lock xx(mutex);
channelGetPutStatus = status;
putState = putComplete;
waitForGetPut.signal();
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->putDone(status,shared_from_this());
}
waitForGetPut.signal();
if(req) { req->putDone(status,shared_from_this());}
}
void PvaClientPut::connect()
@@ -249,7 +235,7 @@ void PvaClientPut::connect()
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
string message = string("channel ")
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::connect "
+ status.getMessage();
@@ -271,7 +257,7 @@ void PvaClientPut::issueConnect()
connectState = connectActive;
channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
}
Status PvaClientPut::waitConnect()
@@ -281,20 +267,7 @@ Status PvaClientPut::waitConnect()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(connectState==connected) {
if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
return channelPutConnectStatus;
}
if(connectState!=connectActive) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
}
waitForConnect.wait();
if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
return channelPutConnectStatus;
}
@@ -308,7 +281,7 @@ void PvaClientPut::get()
issueGet();
Status status = waitGet();
if(status.isOK()) return;
string message = string("channel ")
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::get "
+ status.getMessage();
@@ -340,17 +313,8 @@ Status PvaClientPut::waitGet()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(putState==putComplete) return channelGetPutStatus;
if(putState!=getActive){
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::waitGet illegal put state";
throw std::runtime_error(message);
}
}
waitForGetPut.wait();
putState = putComplete;
return channelGetPutStatus;
}
@@ -376,15 +340,15 @@ void PvaClientPut::issuePut()
if(PvaClient::getDebug()) {
cout << "PvaClientPut::issuePut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " pvStructure\n" << pvaClientData->getPVStructure()
<< " pvStructure\n" << pvaClientData->getPVStructure()
<< " bitSet " << *pvaClientData->getChangedBitSet() << endl
<< endl;
}
}
if(connectState==connectIdle) connect();
if(putState==getActive || putState==putActive) {
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ "PvaClientPut::issuePut get or put aleady active ";
+ " PvaClientPut::issuePut get or put aleady active ";
throw std::runtime_error(message);
}
putState = putActive;
@@ -398,17 +362,8 @@ Status PvaClientPut::waitPut()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(putState==putComplete) return channelGetPutStatus;
if(putState!=putActive){
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::waitPut illegal put state";
throw std::runtime_error(message);
}
}
waitForGetPut.wait();
putState = putComplete;
if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
return channelGetPutStatus;
}
+20 -112
View File
@@ -74,34 +74,12 @@ PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
void PvaClientPutData::putDouble(double value)
{
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n";
PVScalarPtr pvScalar;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
}
if(!pvScalar) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::putDouble() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalar) {
throw std::logic_error(
"PvaClientData::putDouble() did not find a scalar field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::putDouble() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
@@ -118,70 +96,24 @@ void PvaClientPutData::putDouble(double value)
void PvaClientPutData::putString(std::string const & value)
{
if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n";
PVScalarPtr pvScalar;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalar) pvScalar = static_pointer_cast<PVScalar>(pvValue);
}
if(!pvScalar) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::putString() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalar) {
throw std::logic_error(
"PvaClientData::putString() did not find a scalar field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::putString() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
convert->fromString(pvScalar,value);
}
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
{
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n";
PVScalarArrayPtr pvScalarArray;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
}
}
if(!pvScalarArray) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::putDoubleArray() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalarArray) {
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalarArray) {
throw std::logic_error(
"PvaClientData::putDoubleArray() did not find a scalarArray field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::putDoubleArray() did not find a scalarArray field");
}
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::logic_error(
@@ -193,36 +125,12 @@ void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value)
{
if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n";
PVScalarArrayPtr pvScalarArray;
PVStructurePtr pvStructure = getPVStructure();
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type==scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvValue);
}
}
if(!pvScalarArray) {
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()!=1) {
throw std::logic_error(
"PvaClientData::putStringArray() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type==scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
break;
}
if(pvField->getField()->getType()!=epics::pvData::structure) break;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
if(!pvScalarArray) {
throw std::logic_error(
"PvaClientData::putStringArray() did not find a scalarArray field");
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::putStringArray() did not find a scalarArray field");
}
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
pvScalarArray->putFrom<const string>(value);
return;
}
+19 -67
View File
@@ -41,7 +41,7 @@ public:
return clientPutGet->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
if(!clientPutGet) return;
clientPutGet->message(message,messageType);
@@ -55,7 +55,7 @@ public:
{
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
if(!clientPutGet) return;
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
}
virtual void putGetDone(
@@ -150,16 +150,12 @@ void PvaClientPutGet::checkPutGetState()
string PvaClientPutGet::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientPutGet::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientPutGet::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientPutGet::channelPutGetConnect(
@@ -173,33 +169,24 @@ void PvaClientPutGet::channelPutGetConnect(
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
}
{
Lock xx(mutex);
this->channelPutGet = channelPutGet;
channelPutGetConnectStatus = status;
if(status.isOK()) {
channelPutGetConnectStatus = status;
this->channelPutGet = channelPutGet;
connectState = connected;
pvaClientPutData = PvaClientPutData::create(putStructure);
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
pvaClientGetData = PvaClientGetData::create(getStructure);
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientPutGet::channelPutGetConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
}
}
waitForConnect.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->channelPutGetConnect(status,shared_from_this());
}
waitForConnect.signal();
}
void PvaClientPutGet::putGetDone(
@@ -217,16 +204,16 @@ void PvaClientPutGet::putGetDone(
{
Lock xx(mutex);
channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
}
putGetState = putGetComplete;
waitForPutGet.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->putGetDone(status,shared_from_this());
}
waitForPutGet.signal();
}
void PvaClientPutGet::getPutDone(
@@ -244,7 +231,6 @@ void PvaClientPutGet::getPutDone(
{
Lock xx(mutex);
channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) {
PVStructurePtr pvs = pvaClientPutData->getPVStructure();
pvs->copyUnchecked(*putPVStructure,*putBitSet);
@@ -252,12 +238,13 @@ void PvaClientPutGet::getPutDone(
bs->clear();
*bs |= *putBitSet;
}
putGetState = putGetComplete;
waitForPutGet.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->getPutDone(status,shared_from_this());
}
waitForPutGet.signal();
}
void PvaClientPutGet::getGetDone(
@@ -275,16 +262,16 @@ void PvaClientPutGet::getGetDone(
{
Lock xx(mutex);
channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
}
putGetState = putGetComplete;
waitForPutGet.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->getGetDone(status,shared_from_this());
}
waitForPutGet.signal();
}
void PvaClientPutGet::connect()
@@ -297,7 +284,7 @@ void PvaClientPutGet::connect()
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
string message = string("channel ")
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::connect "
+ status.getMessage();
@@ -329,21 +316,7 @@ Status PvaClientPutGet::waitConnect()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(connectState==connected) {
if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle;
return channelPutGetConnectStatus;
}
if(connectState!=connectActive) {
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
}
waitForConnect.wait();
if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle;
return channelPutGetConnectStatus;
}
@@ -358,7 +331,7 @@ void PvaClientPutGet::putGet()
issuePutGet();
Status status = waitPutGet();
if(status.isOK()) return;
string message = string("channel ")
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::putGet "
+ status.getMessage();
@@ -391,13 +364,6 @@ Status PvaClientPutGet::waitPutGet()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(putGetState==putGetComplete) return channelPutGetStatus;
if(putGetState!=putGetActive){
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::waitPutGet get or put aleady active ";
throw std::runtime_error(message);
}
waitForPutGet.wait();
if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear();
return channelPutGetStatus;
@@ -413,7 +379,7 @@ void PvaClientPutGet::getGet()
issueGetGet();
Status status = waitGetGet();
if(status.isOK()) return;
string message = string("channel ")
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::getGet "
+ status.getMessage();
@@ -445,13 +411,6 @@ Status PvaClientPutGet::waitGetGet()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(putGetState==putGetComplete) return channelPutGetStatus;
if(putGetState!=putGetActive){
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::waitGetGet get or put aleady active ";
throw std::runtime_error(message);
}
waitForPutGet.wait();
return channelPutGetStatus;
}
@@ -466,7 +425,7 @@ void PvaClientPutGet::getPut()
issueGetPut();
Status status = waitGetPut();
if(status.isOK()) return;
string message = string("channel ")
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::getPut "
+ status.getMessage();
@@ -498,13 +457,6 @@ Status PvaClientPutGet::waitGetPut()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(putGetState==putGetComplete) return channelPutGetStatus;
if(putGetState!=putGetActive){
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::waitGetPut get or put aleady active ";
throw std::runtime_error(message);
}
waitForPutGet.wait();
return channelPutGetStatus;
}
+22 -12
View File
@@ -12,6 +12,7 @@
#include <sstream>
#include <pv/event.h>
#include <pv/bitSetUtil.h>
#include <pv/rpcService.h>
#define epicsExportSharedSymbols
@@ -44,14 +45,14 @@ public:
return clientRPC->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
if(!clientRPC) return;
clientRPC->message(message,messageType);
}
virtual void channelRPCConnect(
const epics::pvData::Status& status,
const Status& status,
ChannelRPC::shared_pointer const & channelRPC)
{
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
@@ -93,7 +94,7 @@ PvaClientRPC::PvaClientRPC(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
:
:
connectState(connectIdle),
pvaClient(pvaClient),
channel(channel),
@@ -103,7 +104,7 @@ PvaClientRPC::PvaClientRPC(
{
if(PvaClient::getDebug()) {
cout<< "PvaClientRPC::PvaClientRPC()"
<< " channelName " << channel->getChannelName()
<< " channelName " << channel->getChannelName()
<< endl;
}
}
@@ -169,7 +170,7 @@ void PvaClientRPC::rpcConnect(
cout << "PvaClientRPC::rpcConnect calling waitForConnect.signal\n";
}
waitForConnect.signal();
}
void PvaClientRPC::requestDone(
@@ -180,6 +181,7 @@ void PvaClientRPC::requestDone(
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
{
Lock xx(mutex);
requestStatus = status;
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
@@ -193,7 +195,7 @@ void PvaClientRPC::requestDone(
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ channelName
+" PvaClientRPC::requestDone"
+ " but not active";
throw std::runtime_error(message);
@@ -220,11 +222,11 @@ void PvaClientRPC::connect()
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
string message = string("channel ")
+ channelName
+ " PvaClientRPC::connect "
+ status.getMessage();
throw std::runtime_error(message);
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
}
void PvaClientRPC::issueConnect()
@@ -235,7 +237,7 @@ void PvaClientRPC::issueConnect()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ channelName
+ " pvaClientRPC already connected ";
throw std::runtime_error(message);
}
@@ -305,10 +307,18 @@ PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer co
string message = "channel "
+ channelName
+ " PvaClientRPC::request request timeout ";
throw std::runtime_error(message);
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
}
rpcState = rpcIdle;
return pvResponse;
if(requestStatus.isOK()) return pvResponse;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ " PvaClientRPC::request status ";
message += requestStatus.getMessage();
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
}
@@ -316,7 +326,7 @@ void PvaClientRPC::request(
PVStructure::shared_pointer const & pvArgument,
PvaClientRPCRequesterPtr const & pvaClientRPCRequester)
{
checkRPCState();
checkRPCState();
this->pvaClientRPCRequester = pvaClientRPCRequester;
if(responseTimeout<=0.0) {
{