43 Commits

Author SHA1 Message Date
Andrew Johnson 429c47a34a Update version numbers after tagging 2025-12-15 15:35:55 -06:00
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
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
50 changed files with 802 additions and 2327 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 # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = PROJECT_NUMBER = 4.8.2-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started. # will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES. # 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 # 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 # 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 # specify the list of include paths that are normally passed to the compiler
# using the -I flag. # 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 # 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 # 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 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = include INPUT = src \
src/pv
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -796,7 +797,7 @@ FILE_PATTERNS =
# be searched for input files as well. # be searched for input files as well.
# The default value is: NO. # The default value is: NO.
RECURSIVE = YES RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should be # 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 # 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. # The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = documentation/html HTML_OUTPUT = html/doxygen
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp). # generated HTML page (for example: .htm, .php, .asp).
+11 -2
View File
@@ -1,3 +1,12 @@
# Version number for the PVA Client API and shared library
EPICS_PVACLIENT_MAJOR_VERSION = 4 EPICS_PVACLIENT_MAJOR_VERSION = 4
EPICS_PVACLIENT_MINOR_VERSION = 6 EPICS_PVACLIENT_MINOR_VERSION = 8
EPICS_PVACLIENT_MAINTENANCE_VERSION = 0 EPICS_PVACLIENT_MAINTENANCE_VERSION = 2
# Development flag, set to zero for release versions
EPICS_PVACLIENT_DEVELOPMENT_FLAG = 1
# Immediately after a release the MAINTENANCE_VERSION
# will be incremented and the DEVELOPMENT_FLAG set to 1
+26
View File
@@ -2,6 +2,32 @@
This document summarizes the changes to the module between releases. 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) ## Release 4.6.0 (EPICS 7.0.3, Jul 2019)
* pvaClient now handles exceptions from the server properly (issue #54). * pvaClient now handles exceptions from the server properly (issue #54).
+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" /> <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>EPICS pvaClientCPP</title> <title>EPICS pvaClientCPP</title>
<link rel="stylesheet" type="text/css" <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" <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"> <style type="text/css">
/*<![CDATA[*/ /*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em} .about { margin-left: 3em; margin-right: 3em; font-size: .83em}
@@ -18,7 +18,7 @@
/*]]>*/</style> /*]]>*/</style>
<!-- Script that generates the Table of Contents --> <!-- 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> </head>
@@ -26,7 +26,7 @@
<div class="head"> <div class="head">
<h1>EPICS pvaClientCPP</h1> <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> <h2 class="nocount">Abstract</h2>
@@ -66,9 +66,16 @@ The data for the channels is presented via normative type NTMultiChannel.
<hr /> <hr />
<h2>Overview</h2> <h2>Overview</h2>
<p> <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 pvaClientCPP is one of the components of
<a href="http://epics-pvdata.sourceforge.net"> <a href="https://epics-controls.org/resources-and-support/base/epics-7/">
EPICS Version 4 EPICS-7
</a> </a>
</p> </p>
<p>This document is only a guide to help locate code and documentation related to pvaClientCPP <p>This document is only a guide to help locate code and documentation related to pvaClientCPP
+39 -64
View File
@@ -17,6 +17,7 @@
#include <list> #include <list>
#include <iostream> #include <iostream>
#include <ostream>
#include <sstream> #include <sstream>
#include <pv/requester.h> #include <pv/requester.h>
#include <pv/status.h> #include <pv/status.h>
@@ -57,8 +58,6 @@ typedef std::tr1::shared_ptr<PvaClientChannelStateChangeRequester> PvaClientChan
typedef std::tr1::weak_ptr<PvaClientChannelStateChangeRequester> PvaClientChannelStateChangeRequesterWPtr; typedef std::tr1::weak_ptr<PvaClientChannelStateChangeRequester> PvaClientChannelStateChangeRequesterWPtr;
class PvaClientChannel; class PvaClientChannel;
typedef std::tr1::shared_ptr<PvaClientChannel> PvaClientChannelPtr; typedef std::tr1::shared_ptr<PvaClientChannel> PvaClientChannelPtr;
class PvaClientField;
typedef std::tr1::shared_ptr<PvaClientField> PvaClientFieldPtr;
class PvaClientProcessRequester; class PvaClientProcessRequester;
typedef std::tr1::shared_ptr<PvaClientProcessRequester> PvaClientProcessRequesterPtr; typedef std::tr1::shared_ptr<PvaClientProcessRequester> PvaClientProcessRequesterPtr;
typedef std::tr1::weak_ptr<PvaClientProcessRequester> PvaClientProcessRequesterWPtr; typedef std::tr1::weak_ptr<PvaClientProcessRequester> PvaClientProcessRequesterWPtr;
@@ -84,8 +83,6 @@ typedef std::tr1::shared_ptr<PvaClientMonitor> PvaClientMonitorPtr;
class PvaClientMonitorRequester; class PvaClientMonitorRequester;
typedef std::tr1::shared_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterPtr; typedef std::tr1::shared_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterPtr;
typedef std::tr1::weak_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterWPtr; typedef std::tr1::weak_ptr<PvaClientMonitorRequester> PvaClientMonitorRequesterWPtr;
class PvaClientArray;
typedef std::tr1::shared_ptr<PvaClientArray> PvaClientArrayPtr;
class PvaClientRPC; class PvaClientRPC;
typedef std::tr1::shared_ptr<PvaClientRPC> PvaClientRPCPtr; typedef std::tr1::shared_ptr<PvaClientRPC> PvaClientRPCPtr;
class PvaClientRPCRequester; 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. * @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 : class epicsShareClass PvaClient :
public epics::pvData::Requester, public epics::pvData::Requester,
@@ -118,16 +114,11 @@ public:
* @return shared pointer to the single instance. * @return shared pointer to the single instance.
*/ */
static PvaClientPtr get(std::string const & providerNames = "pva ca"); 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 * @return shared pointer to the single instance
* @deprecated This method will go away in future versions. Use get instead. * @deprecated This method will go away in future versions. Use get instead.
*/ */
static PvaClientPtr create() EPICS_DEPRECATED; static PvaClientPtr create() EPICS_DEPRECATED;
std::string getRequesterName();
/** @brief A new message. /** @brief A new message.
* *
* If a requester is set then it is called otherwise message is displayed * If a requester is set then it is called otherwise message is displayed
@@ -155,7 +146,6 @@ public:
* @param channelName The channelName. * @param channelName The channelName.
* @param providerName The provider. * @param providerName The provider.
* @return The interface. * @return The interface.
* @throw runtime_error if connection fails.
*/ */
PvaClientChannelPtr createChannel( PvaClientChannelPtr createChannel(
std::string const & channelName, std::string const & channelName,
@@ -167,6 +157,13 @@ public:
* @param requester The requester. * @param requester The requester.
*/ */
void setRequester(epics::pvData::RequesterPtr const & 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. /** @brief Clear the requester. PvaClient will handle messages.
*/ */
void clearRequester(); void clearRequester();
@@ -206,7 +203,6 @@ typedef std::tr1::shared_ptr<PvaClientPutCache> PvaClientPutCachePtr;
/** /**
* @brief A callback for change in connection status. * @brief A callback for change in connection status.
* *
* <a href = "../htmldoxygen/pvaClientChannelStateChangeRequester.html">Overview of PvaClientChannelStateChangeRequester</a>
* *
*/ */
class epicsShareClass PvaClientChannelStateChangeRequester class epicsShareClass PvaClientChannelStateChangeRequester
@@ -230,7 +226,6 @@ public:
/** /**
* @brief An easy to use alternative to directly calling the Channel methods of pvAccess. * @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 : class epicsShareClass PvaClientChannel :
@@ -275,13 +270,6 @@ public:
* @return status. * @return status.
*/ */
epics::pvData::Status waitConnect(double timeout = 5.0); 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. /** @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. * @param request The syntax of request is defined by the copy facility of pvData.
@@ -425,20 +413,6 @@ public:
* @return The interface. * @return The interface.
*/ */
PvaClientPutGetPtr createPutGet(epics::pvData::PVStructurePtr const & pvRequest); 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. /** @brief Create a PvaClientMonitor.
* *
* Create and connect to a new PvaClientMonitor. * Create and connect to a new PvaClientMonitor.
@@ -563,7 +537,6 @@ public:
/** /**
* @brief A base class for PvaClientGetData, PvaClientPutData, and PvaClientMonitorData. * @brief A base class for PvaClientGetData, PvaClientPutData, and PvaClientMonitorData.
* *
* <a href = "../htmldoxygen/pvaClientData.html">Overview of PvaClientData</a>
*/ */
class epicsShareClass PvaClientData class epicsShareClass PvaClientData
{ {
@@ -613,6 +586,7 @@ public:
void setData( void setData(
epics::pvData::PVStructurePtr const & pvStructureFrom, epics::pvData::PVStructurePtr const & pvStructureFrom,
epics::pvData::BitSetPtr const & bitSetFrom); epics::pvData::BitSetPtr const & bitSetFrom);
/** @brief Is there a top level field named value. /** @brief Is there a top level field named value.
* @return The answer. * @return The answer.
*/ */
@@ -679,24 +653,49 @@ public:
* @return The timeStamp. * @return The timeStamp.
*/ */
epics::pvData::TimeStamp getTimeStamp(); epics::pvData::TimeStamp getTimeStamp();
/** @brief Factory method for creating an instance of PvaClientData. /** @brief parse from args
* *
* NOTE: Not normally called by clients * Accepts arguments of the form json or field='value' where value is json syntax.
* @param structure Introspection interface * field is name.name...
* @param args The arguments.
* @throw runtime_error if failure. * @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: protected:
static PvaClientDataPtr create(epics::pvData::StructureConstPtr const & structure);
PvaClientData(epics::pvData::StructureConstPtr const & structure); PvaClientData(epics::pvData::StructureConstPtr const & structure);
epics::pvData::PVFieldPtr getSinglePVField();
void checkValue(); void checkValue();
std::string messagePrefix; std::string messagePrefix;
private: 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::StructureConstPtr structure;
epics::pvData::PVStructurePtr pvStructure; epics::pvData::PVStructurePtr pvStructure;
epics::pvData::BitSetPtr bitSet; epics::pvData::BitSetPtr bitSet;
epics::pvData::PVFieldPtr pvValue; epics::pvData::PVFieldPtr pvValue;
epics::pvData::PVAlarm pvAlarm; epics::pvData::PVAlarm pvAlarm;
epics::pvData::PVTimeStamp pvTimeStamp; epics::pvData::PVTimeStamp pvTimeStamp;
@@ -707,7 +706,6 @@ private:
/** /**
* @brief A class that holds data returned by PvaClientGet or 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 class epicsShareClass PvaClientGetData : public PvaClientData
{ {
@@ -734,7 +732,6 @@ class PvaClientPostHandlerPvt; // private to PvaClientPutData
/** /**
* @brief A class that holds data given to by PvaClientPut or PvaClientPutGet * @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 class epicsShareClass PvaClientPutData : public PvaClientData
{ {
@@ -786,8 +783,6 @@ private:
/** /**
* @brief A class that holds data returned by PvaClientMonitor * @brief A class that holds data returned by PvaClientMonitor
*
* <a href = "../htmldoxygen/pvaClientMonitorData.html">Overview of PvaClientMonitorData</a>
*/ */
class epicsShareClass PvaClientMonitorData : public PvaClientData class epicsShareClass PvaClientMonitorData : public PvaClientData
{ {
@@ -828,7 +823,6 @@ private:
/** /**
* @brief Optional client callback. * @brief Optional client callback.
* *
* <a href = "../htmldoxygen/pvaClientProcessRequester.html">Overview of PvaClientProcessRequester</a>
*/ */
class epicsShareClass PvaClientProcessRequester class epicsShareClass PvaClientProcessRequester
{ {
@@ -863,7 +857,6 @@ typedef std::tr1::shared_ptr<ChannelProcessRequesterImpl> ChannelProcessRequeste
/** /**
* @brief An easy to use alternative to ChannelProcess. * @brief An easy to use alternative to ChannelProcess.
* *
* <a href = "../htmldoxygen/pvaClientProcess.html">Overview of PvaClientProcess</a>
*/ */
class epicsShareClass PvaClientProcess : class epicsShareClass PvaClientProcess :
public std::tr1::enable_shared_from_this<PvaClientProcess> public std::tr1::enable_shared_from_this<PvaClientProcess>
@@ -968,7 +961,6 @@ typedef std::tr1::shared_ptr<ChannelGetRequesterImpl> ChannelGetRequesterImplPtr
/** /**
* @brief Optional client callback. * @brief Optional client callback.
* *
* <a href = "../htmldoxygen/pvaClientGetRequester.html">Overview of PvaClientGetRequester</a>
*/ */
class epicsShareClass PvaClientGetRequester class epicsShareClass PvaClientGetRequester
{ {
@@ -997,7 +989,6 @@ public:
/** /**
* @brief An easy to use alternative to ChannelGet. * @brief An easy to use alternative to ChannelGet.
* *
* <a href = "../htmldoxygen/pvaClientGet.html">Overview of PvaClientGet</a>
*/ */
class epicsShareClass PvaClientGet : class epicsShareClass PvaClientGet :
public std::tr1::enable_shared_from_this<PvaClientGet> public std::tr1::enable_shared_from_this<PvaClientGet>
@@ -1113,7 +1104,6 @@ typedef std::tr1::shared_ptr<ChannelPutRequesterImpl> ChannelPutRequesterImplPtr
/** /**
* @brief Optional client callback. * @brief Optional client callback.
* *
* <a href = "../htmldoxygen/pvaClientPutRequester.html">Overview of PvaClientPutRequester</a>
*/ */
class epicsShareClass PvaClientPutRequester class epicsShareClass PvaClientPutRequester
{ {
@@ -1153,7 +1143,6 @@ public:
/** /**
* @brief An easy to use alternative to ChannelPut. * @brief An easy to use alternative to ChannelPut.
* *
* <a href = "../htmldoxygen/pvaClientPut.html">Overview of PvaClientPut</a>
*/ */
class epicsShareClass PvaClientPut : class epicsShareClass PvaClientPut :
public std::tr1::enable_shared_from_this<PvaClientPut> public std::tr1::enable_shared_from_this<PvaClientPut>
@@ -1279,7 +1268,6 @@ typedef std::tr1::shared_ptr<ChannelPutGetRequesterImpl> ChannelPutGetRequesterI
/** /**
* @brief Optional client callback. * @brief Optional client callback.
* *
* <a href = "../htmldoxygen/pvaClientPutGetRequester.html">Overview of PvaClientPutGetRequester</a>
*/ */
class epicsShareClass PvaClientPutGetRequester class epicsShareClass PvaClientPutGetRequester
{ {
@@ -1331,7 +1319,6 @@ public:
/** /**
* @brief An easy to use alternative to ChannelPutGet. * @brief An easy to use alternative to ChannelPutGet.
* *
* <a href = "../htmldoxygen/pvaClientPutGet.html">Overview of PvaClientPutGet</a>
*/ */
class epicsShareClass PvaClientPutGet : class epicsShareClass PvaClientPutGet :
public std::tr1::enable_shared_from_this<PvaClientPutGet> public std::tr1::enable_shared_from_this<PvaClientPutGet>
@@ -1478,11 +1465,9 @@ public:
friend class ChannelPutGetRequesterImpl; friend class ChannelPutGetRequesterImpl;
}; };
//class ChannelMonitorRequester; // private to PvaClientMonitor
/** /**
* @brief Optional client callback. * @brief Optional client callback.
* *
* <a href = "../htmldoxygen/pvaClientMonitorRequester.html">Overview of PvaClientMonitorRequester</a>
*/ */
class epicsShareClass PvaClientMonitorRequester class epicsShareClass PvaClientMonitorRequester
{ {
@@ -1523,7 +1508,6 @@ typedef std::tr1::shared_ptr<MonitorRequesterImpl> MonitorRequesterImplPtr;
/** /**
* @brief An easy to use alternative to Monitor. * @brief An easy to use alternative to Monitor.
* *
* <a href = "../htmldoxygen/pvaClientMonitor.html">Overview of PvaClientMonitor</a>
*/ */
class epicsShareClass PvaClientMonitor : class epicsShareClass PvaClientMonitor :
public PvaClientChannelStateChangeRequester, // remove when deprecated create removed public PvaClientChannelStateChangeRequester, // remove when deprecated create removed
@@ -1672,7 +1656,6 @@ public:
/** /**
* @brief Optional client callback. * @brief Optional client callback.
* *
* <a href = "../htmldoxygen/pvaClientRPCRequester.html">Overview of PvaClientRPCRequester</a>
*/ */
class PvaClientRPCRequester class PvaClientRPCRequester
{ {
@@ -1698,7 +1681,6 @@ typedef std::tr1::shared_ptr<RPCRequesterImpl> RPCRequesterImplPtr;
/** /**
* @brief An easy to use alternative to RPC. * @brief An easy to use alternative to RPC.
* *
* <a href = "../htmldoxygen/pvaClientRPC.html">Overview of PvaClientRPC</a>
*/ */
class epicsShareClass PvaClientRPC : class epicsShareClass PvaClientRPC :
public std::tr1::enable_shared_from_this<PvaClientRPC> public std::tr1::enable_shared_from_this<PvaClientRPC>
@@ -1821,10 +1803,3 @@ private:
}} }}
#endif /* PVACLIENT_H */ #endif /* PVACLIENT_H */
/** @page Overview Documentation
*
* <a href = "../pvaClientCPP.html">pvaClientCPP.html</a>
*
*/
+70 -126
View File
@@ -66,14 +66,19 @@ public:
* @param pvaClient The interface to pvaClient. * @param pvaClient The interface to pvaClient.
* @param channelNames The names of the channel.. * @param channelNames The names of the channel..
* @param providerName The name of the provider. * @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 maxNotConnected The maximum number of channels that can be disconnected.
* @param providerNames The providerName for each Channells
* @return The interface to the PvaClientMultiChannel * @return The interface to the PvaClientMultiChannel
*/ */
static PvaClientMultiChannelPtr create( static PvaClientMultiChannelPtr create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelNames, epics::pvData::shared_vector<const std::string> const & channelNames,
std::string const & providerName = "pva", 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 * @brief Destructor
@@ -148,20 +153,24 @@ public:
private: private:
PvaClientMultiChannel( PvaClientMultiChannel(
PvaClientPtr const &pvaClient, 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, std::string const & providerName,
size_t maxNotConnected); size_t maxNotConnected,
epics::pvData::shared_vector<const std::string> const & providerNames);
void checkConnected(); void checkConnected();
PvaClientPtr pvaClient; PvaClientPtr pvaClient;
epics::pvData::shared_vector<const std::string> channelName; epics::pvData::shared_vector<const std::string> channelNames;
std::string providerName; std::string providerName;
size_t maxNotConnected; size_t maxNotConnected;
epics::pvData::shared_vector<const std::string> const & providerNames;
size_t numChannel; size_t numChannel;
size_t numProviderNames;
epics::pvData::Mutex mutex; epics::pvData::Mutex mutex;
size_t numConnected; size_t numConnected;
bool firstConnect;
PvaClientChannelArray pvaClientChannelArray; PvaClientChannelArray pvaClientChannelArray;
epics::pvData::shared_vector<epics::pvData::boolean> isConnected; epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
epics::pvData::CreateRequest::shared_pointer createRequest; epics::pvData::CreateRequest::shared_pointer createRequest;
@@ -176,19 +185,16 @@ class epicsShareClass PvaClientMultiGetDouble :
public: public:
POINTER_DEFINITIONS(PvaClientMultiGetDouble); POINTER_DEFINITIONS(PvaClientMultiGetDouble);
protected:
/**
* @brief Create a PvaClientMultiGetDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientMultiGetDoublePtr create( static PvaClientMultiGetDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray); PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiGetDouble(); ~PvaClientMultiGetDouble();
/** /**
* @brief Create a channelGet for each channel. * @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. * @return The double[] where each element is the value field of the corresponding channel.
*/ */
epics::pvData::shared_vector<double> get(); epics::pvData::shared_vector<double> get();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiGetDoublePtr getPtrSelf()
{
return shared_from_this();
}
private: private:
PvaClientMultiGetDouble( PvaClientMultiGetDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -229,15 +228,15 @@ class epicsShareClass PvaClientMultiPutDouble :
public: public:
POINTER_DEFINITIONS(PvaClientMultiPutDouble); POINTER_DEFINITIONS(PvaClientMultiPutDouble);
protected:
/** @brief Create a PvaClientMultiPutDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientMultiPutDoublePtr create( static PvaClientMultiPutDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray); PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiPutDouble(); ~PvaClientMultiPutDouble();
/** /**
* @brief Create a channelPut for each channel. * @brief Create a channelPut for each channel.
@@ -247,13 +246,7 @@ public:
* @param data The array of data for each channel. * @param data The array of data for each channel.
*/ */
void put(epics::pvData::shared_vector<double> const &data); 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: private:
PvaClientMultiPutDouble( PvaClientMultiPutDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -277,15 +270,15 @@ class epicsShareClass PvaClientMultiMonitorDouble :
public: public:
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble); POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
protected:
/** @brief Create a PvaClientMultiMonitorDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientMultiMonitorDoublePtr create( static PvaClientMultiMonitorDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray); PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiMonitorDouble(); ~PvaClientMultiMonitorDouble();
/** /**
* @brief Connect a channel monitor for each channel. * @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. * @return The double[] where each element is the value field of the corresponding channel.
*/ */
epics::pvData::shared_vector<double> get(); epics::pvData::shared_vector<double> get();
/** @brief Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiMonitorDoublePtr getPtrSelf()
{
return shared_from_this();
}
private: private:
PvaClientMultiMonitorDouble( PvaClientMultiMonitorDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -341,18 +328,16 @@ class epicsShareClass PvaClientNTMultiGet :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiGet); POINTER_DEFINITIONS(PvaClientNTMultiGet);
/** protected:
* @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.
*/
static PvaClientNTMultiGetPtr create( static PvaClientNTMultiGetPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest); epics::pvData::PVStructurePtr const & pvRequest);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiGet(); ~PvaClientNTMultiGet();
/** /**
* @brief Connect a channelGet for each channel. * @brief Connect a channelGet for each channel.
@@ -369,13 +354,7 @@ public:
* @return the pvaClientNTMultiData. * @return the pvaClientNTMultiData.
*/ */
PvaClientNTMultiDataPtr getData(); PvaClientNTMultiDataPtr getData();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiGetPtr getPtrSelf()
{
return shared_from_this();
}
private: private:
PvaClientNTMultiGet( PvaClientNTMultiGet(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -389,7 +368,6 @@ private:
size_t nchannel; size_t nchannel;
epics::pvData::Mutex mutex; epics::pvData::Mutex mutex;
PvaClientNTMultiDataPtr pvaClientNTMultiData; PvaClientNTMultiDataPtr pvaClientNTMultiData;
std::vector<PvaClientGetPtr> pvaClientGet; std::vector<PvaClientGetPtr> pvaClientGet;
bool isConnected; bool isConnected;
@@ -404,16 +382,15 @@ class epicsShareClass PvaClientNTMultiPut :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiPut); POINTER_DEFINITIONS(PvaClientNTMultiPut);
/** protected:
* @brief Create a PvaClientNTMultiPut.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
static PvaClientNTMultiPutPtr create( static PvaClientNTMultiPutPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray); PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiPut(); ~PvaClientNTMultiPut();
/** /**
* @brief Connect a channelPut for each channel. * @brief Connect a channelPut for each channel.
@@ -426,15 +403,9 @@ public:
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues(); epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
/** /**
* @brief Issue a put for each channel. * @brief Issue a put for each channel.
' */
void put();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/ */
PvaClientNTMultiPutPtr getPtrSelf() void put();
{
return shared_from_this();
}
private: private:
PvaClientNTMultiPut( PvaClientNTMultiPut(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -460,16 +431,16 @@ class epicsShareClass PvaClientNTMultiMonitor :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiMonitor); POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
/** @brief Create a PvaClientNTMultiMonitor. protected:
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
* @return The interface.
*/
static PvaClientNTMultiMonitorPtr create( static PvaClientNTMultiMonitorPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest); epics::pvData::PVStructurePtr const & pvRequest);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiMonitor(); ~PvaClientNTMultiMonitor();
/** /**
* @brief Connect to a channel monitor for each channel. * @brief Connect to a channel monitor for each channel.
@@ -495,13 +466,7 @@ public:
* @return the pvaClientNTMultiData. * @return the pvaClientNTMultiData.
*/ */
PvaClientNTMultiDataPtr getData(); PvaClientNTMultiDataPtr getData();
/** Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiMonitorPtr getPtrSelf()
{
return shared_from_this();
}
private: private:
PvaClientNTMultiMonitor( PvaClientNTMultiMonitor(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -528,38 +493,12 @@ class epicsShareClass PvaClientNTMultiData :
public: public:
POINTER_DEFINITIONS(PvaClientNTMultiData); 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(); ~PvaClientNTMultiData();
/** /**
* @brief Get the number of channels. * @brief Get the number of channels.
* @return The number of channels. * @return The number of channels.
*/ */
size_t getNumber(); size_t getNumber();
/**
* @brief Set the timeStamp base for computing deltaTimes.
*/
void startDeltaTime();
/**
* @brief Update NTMultiChannel fields.
*
* @param valueOnly use only value for union.
*/
void endDeltaTime(bool valueOnly = true);
/** /**
* @brief Get the time when the last get was made. * @brief Get the time when the last get was made.
* @return The timeStamp. * @return The timeStamp.
@@ -570,13 +509,21 @@ public:
* @return The value. * @return The value.
*/ */
epics::nt::NTMultiChannelPtr getNTMultiChannel(); 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() epics::pvData::shared_vector<epics::pvData::boolean> getChannelChangeFlags();
{ protected:
return shared_from_this(); 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: private:
PvaClientNTMultiData( PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -595,6 +542,7 @@ private:
bool gotAlarm; bool gotAlarm;
bool gotTimeStamp; bool gotTimeStamp;
epics::pvData::shared_vector<epics::pvData::boolean> changeFlags;
epics::pvData::StructureConstPtr ntMultiChannelStructure; epics::pvData::StructureConstPtr ntMultiChannelStructure;
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue; epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
epics::pvData::shared_vector<epics::pvData::int32> severity; epics::pvData::shared_vector<epics::pvData::int32> severity;
@@ -606,13 +554,9 @@ private:
epics::pvData::Alarm alarm; epics::pvData::Alarm alarm;
epics::pvData::TimeStamp timeStamp;; epics::pvData::TimeStamp timeStamp;;
epics::pvData::PVTimeStamp pvTimeStamp; epics::pvData::PVTimeStamp pvTimeStamp;
friend class PvaClientNTMultiGet;
friend class PvaClientNTMultiPut;
friend class PvaClientNTMultiMonitor;
}; };
}} }}
#endif /* PVACLIENTMULTICHANNEL_H */ #endif /* PVACLIENTMULTICHANNEL_H */
-1
View File
@@ -231,4 +231,3 @@ size_t PvaClient::cacheSize()
} }
}} }}
+1 -35
View File
@@ -179,13 +179,10 @@ void PvaClientChannel::channelCreated(const Status& status, Channel::shared_poin
} }
if(!status.isOK()) { if(!status.isOK()) {
string message("PvaClientChannel::channelCreated"); string message("PvaClientChannel::channelCreated");
message += " channel " + channelName
+ " status " + status.getMessage() + " why??"; + " status " + status.getMessage() + " why??";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(channel->isConnected()) {
connectState = connected;
waitForConnect.signal();
}
} }
void PvaClientChannel::channelStateChange( void PvaClientChannel::channelStateChange(
@@ -202,9 +199,6 @@ void PvaClientChannel::channelStateChange(
if(connectState==connectActive) waitingForConnect = true; if(connectState==connectActive) waitingForConnect = true;
if(connectionState!=Channel::CONNECTED) { if(connectionState!=Channel::CONNECTED) {
Lock xx(mutex); Lock xx(mutex);
string mess(channelName +
" connection state " + Channel::ConnectionStateNames[connectionState]);
message(mess,errorMessage);
connectState = notConnected; connectState = notConnected;
} else { } else {
Lock xx(mutex); Lock xx(mutex);
@@ -319,13 +313,6 @@ Status PvaClientChannel::waitConnect(double timeout)
return Status(Status::STATUSTYPE_ERROR," not connected"); 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) PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
{ {
PVStructurePtr pvRequest = createRequest->createRequest(request); PVStructurePtr pvRequest = createRequest->createRequest(request);
@@ -493,27 +480,6 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvReque
return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest); 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 PvaClientChannel::monitor(string const & request)
{ {
PvaClientMonitorPtr pvaClientMonitor = createMonitor(request); PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
+187 -108
View File
@@ -11,9 +11,17 @@
#include <typeinfo> #include <typeinfo>
#include <sstream> #include <sstream>
#include <istream>
#include <ostream>
#include <pv/createRequest.h> #include <pv/createRequest.h>
#include <pv/convert.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 #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() void PvaClientData::checkValue()
{ {
if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n"; if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n";
@@ -106,6 +138,7 @@ void PvaClientData::setData(
pvValue = pvStructure->getSubField("value"); pvValue = pvStructure->getSubField("value");
} }
bool PvaClientData::hasValue() bool PvaClientData::hasValue()
{ {
if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n"; if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
@@ -171,34 +204,12 @@ PVScalarArrayPtr PvaClientData::getScalarArrayValue()
double PvaClientData::getDouble() double PvaClientData::getDouble()
{ {
if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n"; if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n";
PVScalarPtr pvScalar; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalar) { if(type!=scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField); throw std::logic_error("PvaClientData::getDouble() did not find a scalar field");
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");
} }
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
ScalarType scalarType = pvScalar->getScalar()->getScalarType(); ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) { if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar); PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
@@ -214,70 +225,24 @@ double PvaClientData::getDouble()
string PvaClientData::getString() string PvaClientData::getString()
{ {
if(PvaClient::getDebug()) cout << "PvaClientData::getString\n"; if(PvaClient::getDebug()) cout << "PvaClientData::getString\n";
PVScalarPtr pvScalar; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalar) { if(type!=scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField); throw std::logic_error("PvaClientData::getString() did not find a scalar field");
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");
} }
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
return convert->toString(pvScalar); return convert->toString(pvScalar);
} }
shared_vector<const double> PvaClientData::getDoubleArray() shared_vector<const double> PvaClientData::getDoubleArray()
{ {
if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n"; if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n";
PVScalarArrayPtr pvScalarArray; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalarArray) { if(type!=scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField); throw std::logic_error("PvaClientData::getDoubleArray() did not find a scalarArray field");
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");
} }
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(!ScalarTypeFunc::isNumeric(scalarType)) { if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::logic_error( throw std::logic_error(
@@ -291,36 +256,12 @@ shared_vector<const double> PvaClientData::getDoubleArray()
shared_vector<const string> PvaClientData::getStringArray() shared_vector<const string> PvaClientData::getStringArray()
{ {
if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n"; if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n";
PVScalarArrayPtr pvScalarArray; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalarArray) { if(type!=scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField); throw std::logic_error("PvaClientData::getStringArray() did not find a scalarArray field");
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");
} }
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
shared_vector<const string> retValue; shared_vector<const string> retValue;
pvScalarArray->getAs<const string>(retValue); pvScalarArray->getAs<const string>(retValue);
return retValue; return retValue;
@@ -358,4 +299,142 @@ TimeStamp PvaClientData::getTimeStamp()
throw std::runtime_error(messagePrefix + noTimeStamp); 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;
}
}
}
}} }}
+8 -47
View File
@@ -42,7 +42,7 @@ public:
return clientGet->getRequesterName(); 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()); PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return; if(!clientGet) return;
clientGet->message(message,messageType); clientGet->message(message,messageType);
@@ -134,19 +134,14 @@ void PvaClientGet::checkConnectState()
} }
} }
// from ChannelGetRequester
string PvaClientGet::getRequesterName() string PvaClientGet::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); return pvaClientChannel->getRequesterName();
if(!yyy) return string("PvaClientGet::getRequesterName PvaClient isDestroyed");
return yyy->getRequesterName();
} }
void PvaClientGet::message(string const & message,MessageType messageType) void PvaClientGet::message(string const & message,MessageType messageType)
{ {
PvaClientPtr yyy = pvaClient.lock(); pvaClientChannel->message(message,messageType);
if(!yyy) return;
yyy->message(message, messageType);
} }
void PvaClientGet::channelGetConnect( void PvaClientGet::channelGetConnect(
@@ -162,27 +157,19 @@ void PvaClientGet::channelGetConnect(
} }
{ {
Lock xx(mutex); Lock xx(mutex);
this->channelGet = channelGet;
if(status.isOK()) {
channelGetConnectStatus = status; channelGetConnectStatus = status;
if(status.isOK()) {
this->channelGet = channelGet;
connectState = connected; connectState = connected;
pvaClientData = PvaClientGetData::create(structure); pvaClientData = PvaClientGetData::create(structure);
pvaClientData->setMessagePrefix(channelGet->getChannel()->getChannelName()); 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()); PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) { if(req) {
req->channelGetConnect(status,shared_from_this()); req->channelGetConnect(status,shared_from_this());
} }
waitForConnect.signal();
} }
void PvaClientGet::getDone( void PvaClientGet::getDone(
@@ -200,16 +187,16 @@ void PvaClientGet::getDone(
{ {
Lock xx(mutex); Lock xx(mutex);
channelGetStatus = status; channelGetStatus = status;
getState = getComplete;
if(status.isOK()) { if(status.isOK()) {
pvaClientData->setData(pvStructure,bitSet); pvaClientData->setData(pvStructure,bitSet);
} }
getState = getComplete;
waitForGet.signal();
} }
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock()); PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) { if(req) {
req->getDone(status,shared_from_this()); req->getDone(status,shared_from_this());
} }
waitForGet.signal();
} }
void PvaClientGet::connect() void PvaClientGet::connect()
@@ -248,20 +235,7 @@ Status PvaClientGet::waitConnect()
cout << "PvaClientGet::waitConnect channelName " cout << "PvaClientGet::waitConnect channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n"; << 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(); waitForConnect.wait();
if(!channelGetConnectStatus.isOK()) connectState = connectIdle;
return channelGetConnectStatus; return channelGetConnectStatus;
} }
@@ -301,20 +275,7 @@ Status PvaClientGet::waitGet()
cout << "PvaClientGet::waitGet channelName " cout << "PvaClientGet::waitGet channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n"; << 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(); waitForGet.wait();
getState = getComplete;
return channelGetStatus; return channelGetStatus;
} }
PvaClientGetDataPtr PvaClientGet::getData() PvaClientGetDataPtr PvaClientGet::getData()
+15 -26
View File
@@ -44,7 +44,7 @@ public:
return clientMonitor->getRequesterName(); 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()); PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return; if(!clientMonitor) return;
clientMonitor->message(message,messageType); clientMonitor->message(message,messageType);
@@ -60,14 +60,14 @@ public:
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()); PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return; 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()); PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return; if(!clientMonitor) return;
@@ -201,16 +201,12 @@ void PvaClientMonitor::checkMonitorState()
string PvaClientMonitor::getRequesterName() string PvaClientMonitor::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); return pvaClientChannel->getRequesterName();
if(!yyy) return string("PvaClientMonitor::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
} }
void PvaClientMonitor::message(string const & message,MessageType messageType) void PvaClientMonitor::message(string const & message,MessageType messageType)
{ {
PvaClientPtr yyy = pvaClient.lock(); pvaClientChannel->message(message,messageType);
if(!yyy) return;
yyy->message(message, messageType);
} }
void PvaClientMonitor::monitorConnect( void PvaClientMonitor::monitorConnect(
@@ -226,19 +222,24 @@ void PvaClientMonitor::monitorConnect(
} }
{ {
Lock xx(mutex); Lock xx(mutex);
monitorConnectStatus = status;
if(status.isOK()) {
this->monitor = monitor; this->monitor = monitor;
if(!status.isOK()) { } else {
stringstream ss; stringstream ss;
ss << pvRequest; ss << pvRequest;
string message = string("\nPvaClientMonitor::monitorConnect)") string message = string("\nPvaClientMonitor::monitorConnect)")
+ "\nchannelName=" + pvaClientChannel->getChannel()->getChannelName()
+ "\npvRequest\n" + ss.str() + "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage(); + "\nerror\n" + status.getMessage();
monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message); monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
waitForConnect.signal();
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->monitorConnect(status,shared_from_this(),structure);
return; return;
} }
} }
bool signal = (connectState==connectWait) ? true : false; bool signal = (connectState==connectWait) ? true : false;
monitorConnectStatus = status;
connectState = connected; connectState = connected;
if(isStarted) { if(isStarted) {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
@@ -247,6 +248,9 @@ void PvaClientMonitor::monitorConnect(
<< " is already started " << " is already started "
<< endl; << endl;
} }
waitForConnect.signal();
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->monitorConnect(status,shared_from_this(),structure);
return; return;
} }
pvaClientData = PvaClientMonitorData::create(structure); pvaClientData = PvaClientMonitorData::create(structure);
@@ -288,9 +292,7 @@ void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock(); PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
if(req) { if(req) {
req->unlisten(); req->unlisten();
return;
} }
cerr << pvaClientChannel->getChannel()->getChannelName() + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n";
} }
@@ -327,20 +329,7 @@ Status PvaClientMonitor::waitConnect()
<< pvaClientChannel->getChannel()->getChannelName() << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForConnect.wait();
connectState = monitorConnectStatus.isOK() ? connected : connectIdle;
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::waitConnect" cout << "PvaClientMonitor::waitConnect"
<< " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected") << " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected")
+29 -15
View File
@@ -28,26 +28,32 @@ static CreateRequest::shared_pointer createRequestPvt = CreateRequest::create()
PvaClientMultiChannelPtr PvaClientMultiChannel::create( PvaClientMultiChannelPtr PvaClientMultiChannel::create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const string> const & channelNames, shared_vector<const string> const & channelNames,
string const & providerName, string const & providerName,
size_t maxNotConnected) size_t maxNotConnected,
shared_vector<const string> const & providerNames)
{ {
return PvaClientMultiChannelPtr( return PvaClientMultiChannelPtr(
new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected)); new PvaClientMultiChannel(
pvaClient,channelNames,providerName,maxNotConnected,providerNames));
} }
PvaClientMultiChannel::PvaClientMultiChannel( PvaClientMultiChannel::PvaClientMultiChannel(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const string> const & channelName, shared_vector<const string> const & channelNames,
string const & providerName, string const & providerName,
size_t maxNotConnected) size_t maxNotConnected,
shared_vector<const string> const & providerNames)
: pvaClient(pvaClient), : pvaClient(pvaClient),
channelName(channelName), channelNames(channelNames),
providerName(providerName), providerName(providerName),
maxNotConnected(maxNotConnected), maxNotConnected(maxNotConnected),
numChannel(channelName.size()), providerNames(providerNames),
numChannel(channelNames.size()),
numProviderNames(providerNames.size()),
numConnected(0), numConnected(0),
firstConnect(true),
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())), pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)), isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
createRequest(CreateRequest::create()) createRequest(CreateRequest::create())
@@ -62,18 +68,27 @@ PvaClientMultiChannel::~PvaClientMultiChannel()
void PvaClientMultiChannel::checkConnected() 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) Status PvaClientMultiChannel::connect(double timeout)
{ {
if(!firstConnect) return Status::Ok;
firstConnect = false;
for(size_t i=0; i< numChannel; ++i) { 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(); pvaClientChannelArray[i]->issueConnect();
} }
Status returnStatus = Status::Ok; Status returnStatus = Status::Ok;
@@ -88,11 +103,10 @@ Status PvaClientMultiChannel::connect(double timeout)
if(status.isOK()) { if(status.isOK()) {
++numConnected; ++numConnected;
isConnected[i] = true; isConnected[i] = true;
continue; } else {
}
if(returnStatus.isOK()) returnStatus = status; if(returnStatus.isOK()) returnStatus = status;
++numBad; ++numBad;
if(numBad>maxNotConnected) break; }
} }
return numBad>maxNotConnected ? returnStatus : Status::Ok; return numBad>maxNotConnected ? returnStatus : Status::Ok;
} }
@@ -115,7 +129,7 @@ bool PvaClientMultiChannel::connectionChange()
return false; 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) { for(size_t i=0; i<numChannel; ++i) {
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i]; PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
+15 -6
View File
@@ -39,7 +39,7 @@ PvaClientMultiGetDouble::PvaClientMultiGetDouble(
: pvaClientMultiChannel(pvaClientMultiChannel), : pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray), pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
doubleValue(shared_vector<double>(nchannel)), doubleValue( shared_vector<double>(nchannel)),
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())), pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
isGetConnected(false) isGetConnected(false)
{ {
@@ -53,7 +53,7 @@ PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
void PvaClientMultiGetDouble::connect() void PvaClientMultiGetDouble::connect()
{ {
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); shared_vector<epics::pvData::boolean>isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value"; string request = "value";
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
@@ -75,14 +75,14 @@ void PvaClientMultiGetDouble::connect()
isGetConnected = true; isGetConnected = true;
} }
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get() shared_vector<double> PvaClientMultiGetDouble::get()
{ {
if(!isGetConnected) connect(); if(!isGetConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected(); shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) { if(isConnected[i]) {
if(!pvaClientGet[i]) pvaClientGet[i]=pvaClientChannelArray[i]->createGet("value");
pvaClientGet[i]->issueGet(); pvaClientGet[i]->issueGet();
} }
} }
@@ -96,13 +96,22 @@ epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
throw std::runtime_error(message); throw std::runtime_error(message);
} }
} }
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) if(isConnected[i])
{ {
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure(); 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 { } else {
doubleValue[i] = epicsNAN; doubleValue[i] = epicsNAN;
} }
+12 -1
View File
@@ -90,6 +90,17 @@ bool PvaClientMultiMonitorDouble::poll()
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[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()) { if(pvaClientMonitor[i]->poll()) {
doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble(); doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
pvaClientMonitor[i]->releaseEvent(); pvaClientMonitor[i]->releaseEvent();
@@ -116,7 +127,7 @@ bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent)
return false; return false;
} }
epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get() shared_vector<double> PvaClientMultiMonitorDouble::get()
{ {
return doubleValue; return doubleValue;
} }
+11 -3
View File
@@ -76,7 +76,7 @@ void PvaClientMultiPutDouble::connect()
isPutConnected = true; isPutConnected = true;
} }
void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data) void PvaClientMultiPutDouble::put(shared_vector<double> const &data)
{ {
if(!isPutConnected) connect(); if(!isPutConnected) connect();
if(data.size()!=nchannel) { 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) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) { if(isConnected[i]) {
if(!pvaClientPut[i]) pvaClientPut[i]=pvaClientChannelArray[i]->createPut("value");
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure(); PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value"); PVScalarPtr pvScalar= pvTop->getSubField<PVScalar>("value");
getConvert()->fromDouble(pvValue,data[i]); if(pvScalar && ScalarTypeFunc::isNumeric(pvScalar->getScalar()->getScalarType())) {
getConvert()->fromDouble(pvScalar,data[i]);
pvaClientPut[i]->issuePut(); pvaClientPut[i]->issuePut();
} else {
string message = string("channel ")
+ pvaClientChannelArray[i]->getChannelName()
+ " is not a numeric scalar";
throw std::runtime_error(message);
}
} }
if(isConnected[i]) { if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut(); Status status = pvaClientPut[i]->waitPut();
+16 -9
View File
@@ -23,7 +23,7 @@ using namespace std;
namespace epics { namespace pvaClient { namespace epics { namespace pvaClient {
PvaClientNTMultiDataPtr PvaClientNTMultiData::create( PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
epics::pvData::UnionConstPtr const & u, UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
PVStructurePtr const & pvRequest) PVStructurePtr const & pvRequest)
@@ -33,18 +33,21 @@ PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
} }
PvaClientNTMultiData::PvaClientNTMultiData( PvaClientNTMultiData::PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u, UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest) PVStructurePtr const & pvRequest)
: pvaClientMultiChannel(pvaClientMultiChannel), : pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray), pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
gotAlarm(false), gotAlarm(false),
gotTimeStamp(false) gotTimeStamp(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n"; if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
changeFlags = shared_vector<epics::pvData::boolean>(nchannel);
topPVStructure.resize(nchannel); topPVStructure.resize(nchannel);
unionValue.resize(nchannel); unionValue.resize(nchannel);
PVDataCreatePtr pvDataCreate = getPVDataCreate(); PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(size_t i=0; i< nchannel; ++i) { for(size_t i=0; i< nchannel; ++i) {
@@ -90,12 +93,18 @@ void PvaClientNTMultiData::setPVStructure(
topPVStructure[index] = pvStructure; topPVStructure[index] = pvStructure;
} }
shared_vector<epics::pvData::boolean> PvaClientNTMultiData::getChannelChangeFlags()
{
return changeFlags;
}
size_t PvaClientNTMultiData::getNumber() size_t PvaClientNTMultiData::getNumber()
{ {
return nchannel; return nchannel;
} }
void PvaClientNTMultiData::startDeltaTime() void PvaClientNTMultiData::startDeltaTime()
{ {
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
@@ -126,15 +135,13 @@ void PvaClientNTMultiData::endDeltaTime(bool valueOnly)
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
PVStructurePtr pvst = topPVStructure[i]; PVStructurePtr pvst = topPVStructure[i];
if(!pvst) { changeFlags[i] = false;
unionValue[i] = PVUnionPtr(); if(pvst&&unionValue[i]) {
} else if(unionValue[i]) { changeFlags[i] = true;
if(valueOnly) { if(valueOnly) {
PVFieldPtr pvValue = pvst->getSubField("value"); PVFieldPtr pvValue = pvst->getSubField("value");
if(pvValue) { if(pvValue) {
unionValue[i]->set(pvst->getSubField("value")); unionValue[i]->set(pvst->getSubField("value"));
} else {
unionValue[i] = PVUnionPtr();
} }
} else { } else {
unionValue[i]->set(pvst); unionValue[i]->set(pvst);
@@ -180,7 +187,7 @@ NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(ntMultiChannelStructure); PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(ntMultiChannelStructure);
NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure); NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure);
ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames()); 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]; for(size_t i=0; i<nchannel; ++i) val[i] = unionValue[i];
ntMultiChannel->getValue()->replace(freeze(val)); ntMultiChannel->getValue()->replace(freeze(val));
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected(); shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
+5 -1
View File
@@ -38,7 +38,7 @@ PvaClientNTMultiGet::PvaClientNTMultiGet(
UnionConstPtr const & u, UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest) PVStructurePtr const & pvRequest)
: pvaClientMultiChannel(pvaClientMultiChannel), : pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray), pvaClientChannelArray(pvaClientChannelArray),
pvRequest(pvRequest), pvRequest(pvRequest),
@@ -91,6 +91,10 @@ void PvaClientNTMultiGet::get(bool valueOnly)
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) { if(isConnected[i]) {
if(!pvaClientGet[i]){
pvaClientGet[i]=pvaClientChannelArray[i]->createGet(pvRequest);
pvaClientGet[i]->connect();
}
pvaClientGet[i]->issueGet(); pvaClientGet[i]->issueGet();
} }
} }
+6 -1
View File
@@ -28,7 +28,7 @@ namespace epics { namespace pvaClient {
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create( PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
PvaClientMultiChannelPtr const &pvaMultiChannel, PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray, PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest) PVStructurePtr const & pvRequest)
{ {
UnionConstPtr u = getFieldCreate()->createVariantUnion(); UnionConstPtr u = getFieldCreate()->createVariantUnion();
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor( PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
@@ -100,6 +100,11 @@ bool PvaClientNTMultiMonitor::poll(bool valueOnly)
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[i]) { if(isConnected[i]) {
if(!pvaClientMonitor[i]){
pvaClientMonitor[i]=pvaClientChannelArray[i]->createMonitor(pvRequest);
pvaClientMonitor[i]->connect();
pvaClientMonitor[i]->start();
}
if(pvaClientMonitor[i]->poll()) { if(pvaClientMonitor[i]->poll()) {
pvaClientNTMultiData->setPVStructure( pvaClientNTMultiData->setPVStructure(
pvaClientMonitor[i]->getData()->getPVStructure(),i); pvaClientMonitor[i]->getData()->getPVStructure(),i);
+34 -3
View File
@@ -38,8 +38,8 @@ PvaClientNTMultiPut::PvaClientNTMultiPut(
: pvaClientMultiChannel(pvaClientMultiChannel), : pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray), pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()), nchannel(pvaClientChannelArray.size()),
unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())), unionValue(shared_vector<PVUnionPtr>(nchannel,PVUnionPtr())),
value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())), value(shared_vector<PVFieldPtr>(nchannel,PVFieldPtr())),
isConnected(false) isConnected(false)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::PvaClientNTMultiPut()\n"; if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::PvaClientNTMultiPut()\n";
@@ -102,9 +102,26 @@ void PvaClientNTMultiPut::connect()
this->isConnected = true; this->isConnected = true;
} }
shared_vector<epics::pvData::PVUnionPtr> PvaClientNTMultiPut::getValues() shared_vector<PVUnionPtr> PvaClientNTMultiPut::getValues()
{ {
if(!isConnected) connect(); 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; return unionValue;
} }
@@ -115,9 +132,23 @@ void PvaClientNTMultiPut::put()
for(size_t i=0; i<nchannel; ++i) for(size_t i=0; i<nchannel; ++i)
{ {
if(isConnected[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()); value[i]->copy(*unionValue[i]->get());
pvaClientPut[i]->issuePut(); pvaClientPut[i]->issuePut();
} }
}
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) { if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut(); Status status = pvaClientPut[i]->waitPut();
if(status.isOK()) continue; if(status.isOK()) continue;
+7 -43
View File
@@ -42,7 +42,7 @@ public:
return clientProcess->getRequesterName(); 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()); PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return; if(!clientProcess) return;
clientProcess->message(message,messageType); clientProcess->message(message,messageType);
@@ -111,19 +111,14 @@ PvaClientProcess::~PvaClientProcess()
} }
} }
// from ChannelProcessRequester
string PvaClientProcess::getRequesterName() string PvaClientProcess::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); return pvaClientChannel->getRequesterName();
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
return yyy->getRequesterName();
} }
void PvaClientProcess::message(string const & message,MessageType messageType) void PvaClientProcess::message(string const & message,MessageType messageType)
{ {
PvaClientPtr yyy = pvaClient.lock(); pvaClientChannel->message(message,messageType);
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType);
} }
void PvaClientProcess::channelProcessConnect( void PvaClientProcess::channelProcessConnect(
@@ -138,25 +133,17 @@ void PvaClientProcess::channelProcessConnect(
} }
{ {
Lock xx(mutex); Lock xx(mutex);
this->channelProcess = channelProcess;
if(status.isOK()) {
channelProcessConnectStatus = status; channelProcessConnectStatus = status;
if(status.isOK()) {
this->channelProcess = channelProcess;
connectState = connected; 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()); PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) { if(req) {
req->channelProcessConnect(status,shared_from_this()); req->channelProcessConnect(status,shared_from_this());
} }
waitForConnect.signal();
} }
void PvaClientProcess::processDone( void PvaClientProcess::processDone(
@@ -173,13 +160,12 @@ void PvaClientProcess::processDone(
Lock xx(mutex); Lock xx(mutex);
channelProcessStatus = status; channelProcessStatus = status;
processState = processComplete; processState = processComplete;
waitForProcess.signal();
} }
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock()); PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) { if(req) {
req->processDone(status,shared_from_this()); req->processDone(status,shared_from_this());
} }
waitForProcess.signal();
} }
void PvaClientProcess::connect() void PvaClientProcess::connect()
@@ -221,17 +207,7 @@ Status PvaClientProcess::waitConnect()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForConnect.wait();
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
return channelProcessConnectStatus; return channelProcessConnectStatus;
} }
@@ -274,18 +250,6 @@ Status PvaClientProcess::waitProcess()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForProcess.wait();
processState = processComplete; processState = processComplete;
return channelProcessStatus; return channelProcessStatus;
+13 -58
View File
@@ -42,7 +42,7 @@ public:
return clientPut->getRequesterName(); 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()); PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return; if(!clientPut) return;
clientPut->message(message,messageType); clientPut->message(message,messageType);
@@ -138,16 +138,12 @@ void PvaClientPut::checkConnectState()
string PvaClientPut::getRequesterName() string PvaClientPut::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); return pvaClientChannel->getRequesterName();
if(!yyy) return string("PvaClientPut::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
} }
void PvaClientPut::message(string const & message,MessageType messageType) void PvaClientPut::message(string const & message,MessageType messageType)
{ {
PvaClientPtr yyy = pvaClient.lock(); pvaClientChannel->message(message,messageType);
if(!yyy) return;
yyy->message(message, messageType);
} }
void PvaClientPut::channelPutConnect( void PvaClientPut::channelPutConnect(
@@ -163,27 +159,19 @@ void PvaClientPut::channelPutConnect(
} }
{ {
Lock xx(mutex); Lock xx(mutex);
this->channelPut = channelPut;
if(status.isOK()) {
channelPutConnectStatus = status; channelPutConnectStatus = status;
if(status.isOK()) {
this->channelPut = channelPut;
connectState = connected; connectState = connected;
pvaClientData = PvaClientPutData::create(structure); pvaClientData = PvaClientPutData::create(structure);
pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName()); 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()); PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) { if(req) {
req->channelPutConnect(status,shared_from_this()); req->channelPutConnect(status,shared_from_this());
} }
waitForConnect.signal();
} }
void PvaClientPut::getDone( void PvaClientPut::getDone(
@@ -207,14 +195,14 @@ void PvaClientPut::getDone(
BitSetPtr bs = pvaClientData->getChangedBitSet(); BitSetPtr bs = pvaClientData->getChangedBitSet();
bs->clear(); bs->clear();
*bs |= *bitSet; *bs |= *bitSet;
putState = putComplete;
} }
putState = putComplete;
waitForGetPut.signal();
} }
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock()); PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) { if(req) {
req->getDone(status,shared_from_this()); req->getDone(status,shared_from_this());
} }
waitForGetPut.signal();
} }
void PvaClientPut::putDone( void PvaClientPut::putDone(
@@ -231,12 +219,10 @@ void PvaClientPut::putDone(
Lock xx(mutex); Lock xx(mutex);
channelGetPutStatus = status; channelGetPutStatus = status;
putState = putComplete; putState = putComplete;
waitForGetPut.signal();
} }
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock()); PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) { if(req) { req->putDone(status,shared_from_this());}
req->putDone(status,shared_from_this());
}
waitForGetPut.signal();
} }
void PvaClientPut::connect() void PvaClientPut::connect()
@@ -281,20 +267,7 @@ Status PvaClientPut::waitConnect()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForConnect.wait();
if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
return channelPutConnectStatus; return channelPutConnectStatus;
} }
@@ -340,17 +313,8 @@ Status PvaClientPut::waitGet()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForGetPut.wait();
putState = putComplete;
return channelGetPutStatus; return channelGetPutStatus;
} }
@@ -384,7 +348,7 @@ void PvaClientPut::issuePut()
if(putState==getActive || putState==putActive) { if(putState==getActive || putState==putActive) {
string message = string("channel ") string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName() + pvaClientChannel->getChannel()->getChannelName()
+ "PvaClientPut::issuePut get or put aleady active "; + " PvaClientPut::issuePut get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
putState = putActive; putState = putActive;
@@ -398,17 +362,8 @@ Status PvaClientPut::waitPut()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForGetPut.wait();
putState = putComplete;
if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear(); if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
return channelGetPutStatus; return channelGetPutStatus;
} }
+16 -108
View File
@@ -74,34 +74,12 @@ PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
void PvaClientPutData::putDouble(double value) void PvaClientPutData::putDouble(double value)
{ {
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n"; if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n";
PVScalarPtr pvScalar; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalar) { if(type!=scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField); throw std::logic_error("PvaClientData::putDouble() did not find a scalar field");
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");
} }
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
ScalarType scalarType = pvScalar->getScalar()->getScalarType(); ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) { if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar); PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
@@ -118,70 +96,24 @@ void PvaClientPutData::putDouble(double value)
void PvaClientPutData::putString(std::string const & value) void PvaClientPutData::putString(std::string const & value)
{ {
if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n"; if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n";
PVScalarPtr pvScalar; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalar) { if(type!=scalar) {
pvScalar = static_pointer_cast<PVScalar>(pvField); throw std::logic_error("PvaClientData::putString() did not find a scalar field");
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");
} }
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
convert->fromString(pvScalar,value); convert->fromString(pvScalar,value);
} }
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value) void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
{ {
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n"; if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n";
PVScalarArrayPtr pvScalarArray; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalarArray) { if(type!=scalarArray) {
throw std::logic_error("PvaClientData::putDoubleArray() did not find a scalarArray field");
}
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField); 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");
}
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType(); ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(!ScalarTypeFunc::isNumeric(scalarType)) { if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::logic_error( 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) void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value)
{ {
if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n"; if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n";
PVScalarArrayPtr pvScalarArray; PVFieldPtr pvField = getSinglePVField();
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(); Type type = pvField->getField()->getType();
if(type==scalarArray) { if(type!=scalarArray) {
pvScalarArray = static_pointer_cast<PVScalarArray>(pvField); throw std::logic_error("PvaClientData::putStringArray() did not find a scalarArray field");
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");
} }
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
pvScalarArray->putFrom<const string>(value); pvScalarArray->putFrom<const string>(value);
return; return;
} }
+12 -60
View File
@@ -41,7 +41,7 @@ public:
return clientPutGet->getRequesterName(); 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()); PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
if(!clientPutGet) return; if(!clientPutGet) return;
clientPutGet->message(message,messageType); clientPutGet->message(message,messageType);
@@ -150,16 +150,12 @@ void PvaClientPutGet::checkPutGetState()
string PvaClientPutGet::getRequesterName() string PvaClientPutGet::getRequesterName()
{ {
PvaClientPtr yyy = pvaClient.lock(); return pvaClientChannel->getRequesterName();
if(!yyy) return string("PvaClientPutGet::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
} }
void PvaClientPutGet::message(string const & message,MessageType messageType) void PvaClientPutGet::message(string const & message,MessageType messageType)
{ {
PvaClientPtr yyy = pvaClient.lock(); pvaClientChannel->message(message,messageType);
if(!yyy) return;
yyy->message(message, messageType);
} }
void PvaClientPutGet::channelPutGetConnect( void PvaClientPutGet::channelPutGetConnect(
@@ -176,30 +172,21 @@ void PvaClientPutGet::channelPutGetConnect(
} }
{ {
Lock xx(mutex); Lock xx(mutex);
this->channelPutGet = channelPutGet;
if(status.isOK()) {
channelPutGetConnectStatus = status; channelPutGetConnectStatus = status;
if(status.isOK()) {
this->channelPutGet = channelPutGet;
connectState = connected; connectState = connected;
pvaClientPutData = PvaClientPutData::create(putStructure); pvaClientPutData = PvaClientPutData::create(putStructure);
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
pvaClientGetData = PvaClientGetData::create(getStructure); pvaClientGetData = PvaClientGetData::create(getStructure);
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); 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()); PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) { if(req) {
req->channelPutGetConnect(status,shared_from_this()); req->channelPutGetConnect(status,shared_from_this());
} }
waitForConnect.signal();
} }
void PvaClientPutGet::putGetDone( void PvaClientPutGet::putGetDone(
@@ -217,16 +204,16 @@ void PvaClientPutGet::putGetDone(
{ {
Lock xx(mutex); Lock xx(mutex);
channelPutGetStatus = status; channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) { if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet); pvaClientGetData->setData(getPVStructure,getChangedBitSet);
} }
putGetState = putGetComplete;
waitForPutGet.signal();
} }
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) { if(req) {
req->putGetDone(status,shared_from_this()); req->putGetDone(status,shared_from_this());
} }
waitForPutGet.signal();
} }
void PvaClientPutGet::getPutDone( void PvaClientPutGet::getPutDone(
@@ -244,7 +231,6 @@ void PvaClientPutGet::getPutDone(
{ {
Lock xx(mutex); Lock xx(mutex);
channelPutGetStatus = status; channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) { if(status.isOK()) {
PVStructurePtr pvs = pvaClientPutData->getPVStructure(); PVStructurePtr pvs = pvaClientPutData->getPVStructure();
pvs->copyUnchecked(*putPVStructure,*putBitSet); pvs->copyUnchecked(*putPVStructure,*putBitSet);
@@ -252,12 +238,13 @@ void PvaClientPutGet::getPutDone(
bs->clear(); bs->clear();
*bs |= *putBitSet; *bs |= *putBitSet;
} }
putGetState = putGetComplete;
waitForPutGet.signal();
} }
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) { if(req) {
req->getPutDone(status,shared_from_this()); req->getPutDone(status,shared_from_this());
} }
waitForPutGet.signal();
} }
void PvaClientPutGet::getGetDone( void PvaClientPutGet::getGetDone(
@@ -275,16 +262,16 @@ void PvaClientPutGet::getGetDone(
{ {
Lock xx(mutex); Lock xx(mutex);
channelPutGetStatus = status; channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) { if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet); pvaClientGetData->setData(getPVStructure,getChangedBitSet);
} }
putGetState = putGetComplete;
waitForPutGet.signal();
} }
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) { if(req) {
req->getGetDone(status,shared_from_this()); req->getGetDone(status,shared_from_this());
} }
waitForPutGet.signal();
} }
void PvaClientPutGet::connect() void PvaClientPutGet::connect()
@@ -329,21 +316,7 @@ Status PvaClientPutGet::waitConnect()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForConnect.wait();
if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle;
return channelPutGetConnectStatus; return channelPutGetConnectStatus;
} }
@@ -391,13 +364,6 @@ Status PvaClientPutGet::waitPutGet()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForPutGet.wait();
if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear(); if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear();
return channelPutGetStatus; return channelPutGetStatus;
@@ -445,13 +411,6 @@ Status PvaClientPutGet::waitGetGet()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForPutGet.wait();
return channelPutGetStatus; return channelPutGetStatus;
} }
@@ -498,13 +457,6 @@ Status PvaClientPutGet::waitGetPut()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << 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(); waitForPutGet.wait();
return channelPutGetStatus; return channelPutGetStatus;
} }
+2 -2
View File
@@ -45,14 +45,14 @@ public:
return clientRPC->getRequesterName(); 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()); PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
if(!clientRPC) return; if(!clientRPC) return;
clientRPC->message(message,messageType); clientRPC->message(message,messageType);
} }
virtual void channelRPCConnect( virtual void channelRPCConnect(
const epics::pvData::Status& status, const Status& status,
ChannelRPC::shared_pointer const & channelRPC) ChannelRPC::shared_pointer const & channelRPC)
{ {
PvaClientRPCPtr clientRPC(pvaClientRPC.lock()); PvaClientRPCPtr clientRPC(pvaClientRPC.lock());