66 Commits

Author SHA1 Message Date
Andrew Johnson b1c101578b Update version numbers and formatting in documentation 2018-12-17 16:17:52 -06:00
Andrew Johnson 8ab4dd1fdb Correct SHRLIB_VERSION 2018-12-17 16:16:59 -06:00
Andrew Johnson 5242540725 Update and unify README.md 2018-12-17 16:16:06 -06:00
Michael Davidsaver a8f296ceb3 update travis-ci 2018-10-29 18:02:20 -07:00
Marty Kraimer 6633d4f21e Merge pull request #52 from mrkraimer/master
with multiple threads callback can occur before create completes
2018-10-06 05:59:14 -04:00
mrkraimer 8745dd03b3 with multithreads callback can occur before create completes 2018-10-05 15:59:59 -04:00
Marty Kraimer cfc3c9b998 Merge pull request #51 from mrkraimer/master
several changes
2018-09-28 07:00:34 -04:00
mrkraimer d57893b566 remove #include <pv/pvCopy.h> 2018-09-27 15:34:02 -04:00
mrkraimer b7ea0fe59a fix bug that causes failure in monotor::stop for privider ca 2018-07-27 05:43:47 -04:00
Marty Kraimer 4e4554af4e Merge pull request #50 from mrkraimer/master
re-implement methods used by pvaPy
2018-01-30 09:11:28 -05:00
mrkraimer d6d5bcf771 merge with epics-base 2018-01-12 15:20:47 -05:00
mrkraimer 6bcc036c71 reimplement methods called by pvaPy
The methods are:
static PvaClientPtr create() EPICS_DEPRECATED;
and
static PvaClientMonitorPtr create(
    PvaClientPtr const &pvaClient,
    std::string const & channelName,
    std::string const & providerName,
    std::string const & request,
    PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester
            = PvaClientChannelStateChangeRequesterPtr(),
    PvaClientMonitorRequesterPtr const & monitorRequester
            = PvaClientMonitorRequesterPtr()
) EPICS_DEPRECATED;
2018-01-12 13:51:13 -05:00
Marty Kraimer a405dd7bdb Merge pull request #49 from epics-base/revert-48-master
Revert "Minor changes"
2018-01-09 15:58:58 -05:00
Marty Kraimer 22e260351c Revert "Minor changes" 2018-01-09 15:14:30 -05:00
Marty Kraimer 5a5b8f809d Merge pull request #48 from mrkraimer/master
Minor changes
2018-01-09 11:16:52 -05:00
mrkraimer 9d5f06c11d pull latest from epics-base 2018-01-08 09:20:13 -05:00
mrkraimer 28a23dc5a8 remove a create method from monitor; remove unused channelStateChange methods 2018-01-05 14:38:42 -05:00
Ralph Lange dcda03c9fc jenkins-ci: fix CloudBees doc job 2017-12-19 09:20:11 +01:00
Andrew Johnson b5291d9619 Update/fix version numbers in documentation 2017-12-14 18:55:23 -06:00
Andrew Johnson 74d381e68c Use EPICS_BASE_PVA_CORE_LIBS 2017-12-06 22:45:00 -06:00
Andrew Johnson c789406f0b Include <top>/../RELEASE.<host>.local 2017-12-06 20:39:49 -06:00
Andrew Johnson a21e5b5913 Use 'make test-results' in travis-build script 2017-11-30 13:06:27 -06:00
Andrew Johnson cb374fcefa Unify .gitignore files 2017-11-30 12:08:10 -06:00
Andrew Johnson 90b2bdc162 Remove ExampleRELEASE.local file 2017-11-30 12:07:52 -06:00
Marty Kraimer ea5809be9b Merge pull request #47 from mrkraimer/master
fix bug in pvaClientNTMultiData that can cause a crash
2017-11-21 05:58:47 -05:00
mrkraimer 0fb4612680 fix bug in pvaClientNTMultiData that can cause a crash 2017-11-21 05:25:51 -05:00
Ralph Lange 5a84b94520 jenkins: remove microbench option and pvCommon dependency from CB build 2017-11-15 17:22:25 +01:00
Marty Kraimer 411560ea8d Merge pull request #46 from mrkraimer/master
ignore mutiple calls to PvaClientMonitor::start
2017-11-10 10:38:20 -05:00
mrkraimer 3e9645c883 Merge https://github.com/epics-base/pvaClientCPP 2017-11-10 09:57:46 -05:00
Andrew Johnson 25b621890b Convert debug into a file static data member
MSVC doesn't seem to be able to provide access to it as a
class static, so this fixes the DLL build errors of exampleCPP
2017-11-06 12:57:21 -06:00
mrkraimer fe15b9dd09 ignore mutiple calls to PvaClientMonitor::start 2017-10-23 10:16:31 -04:00
Ralph Lange 64fc25c240 travis-ci: consolidate travis configuration 2017-09-28 15:10:30 +02:00
Ralph Lange c9e7bc32bd travis-ci: pvaClient does not have unit tests 2017-09-27 15:42:05 +02:00
Ralph Lange ab4c69301f travis-ci: fix requisite build for Base 3.x 2017-09-27 14:46:55 +02:00
Ralph Lange 5b9b84f7d0 travis-ci: update/streamline configuration for EPICS 7 2017-09-27 14:02:33 +02:00
Marty Kraimer dd65681630 Merge pull request #45 from mrkraimer/master
more callbacks for callbacks introduced by pvAccess; doc changes
2017-09-13 10:53:02 -04:00
mrkraimer e11cc25dd7 travis: change required for normativeTypesCPP 2017-09-13 10:24:57 -04:00
mrkraimer 05a454fa69 travis; use pvaSrv as model 2017-09-13 05:07:33 -04:00
mrkraimer b5e9aa6a60 yet more support for noblock; add ci 2017-09-12 14:20:13 -04:00
mrkraimer 4606d84185 add more support for no block; removed extra create methods for put and get 2017-09-08 14:22:50 -04:00
mrkraimer 97d9dc2034 add more calbacks; documentation changes 2017-08-08 06:23:35 -04:00
mrkraimer e1d50000d4 pull from epics-base 2017-07-20 09:52:19 -04:00
Marty Kraimer 878cc27aa7 Merge pull request #44 from mrkraimer/new-pva-api
change version number
2017-07-18 15:02:59 -04:00
mrkraimer 5c99282ee2 change version number 2017-07-18 14:47:44 -04:00
Marty Kraimer 3b344fdb25 Merge pull request #43 from mrkraimer/new-pva-api
New pva api
2017-07-18 13:36:04 -04:00
mrkraimer 932d90ff70 minor changes 2017-07-18 06:01:53 -04:00
mrkraimer d7bf6a8910 add nowait support to pvaClientGet, pvaClientPut, pvaClientMonitor 2017-07-14 15:16:49 -04:00
mrkraimer 9b1539f368 more work on doxygen 2017-07-12 06:38:55 -04:00
mrkraimer 8c7506449b doxygen changes 2017-07-12 06:11:29 -04:00
mrkraimer 609c887c19 replace getChannelProviderRegistry with ChannelProviderRegistry::clients 2017-07-07 10:46:22 -04:00
mrkraimer 8f6cc08f85 MessageType::errorMessage => errorMessage 2017-07-06 15:33:08 -04:00
mrkraimer ae49f8ad99 add PvaClientMonitor::getPvaClientChannel() 2017-07-06 14:04:26 -04:00
mrkraimer 696c251ecc remove some cout messages 2017-07-05 10:08:53 -04:00
mrkraimer 594d8dd19f changes to documentation 2017-06-29 09:47:14 -04:00
mrkraimer d8ab89e96a changes for new-pva-api; improve pvaClientMonitor 2017-06-28 10:36:23 -04:00
mrkraimer 9712f001c8 remove extra print statements 2017-06-26 07:43:12 -04:00
Marty Kraimer 91e6392e77 Merge pull request #1 from epics-base/master
create a branch for changes because of API changes in pvAccessCPP
2017-06-26 07:18:17 -04:00
mrkraimer 094336b5e0 let pvaClientMonitor do what pvaMonitor was doing 2017-06-23 14:45:44 -04:00
mrkraimer f0efef68ea add start and stop methods to PvaMonitor 2017-06-21 15:01:41 -04:00
mrkraimer 0912756a2e back out ChannelProvider change; add PvaMonitor 2017-06-15 14:40:13 -04:00
mrkraimer e071e0f9e3 PvaClientChannel::channelStateChange set state before calling stateChangeRequester 2017-06-14 06:14:47 -04:00
mrkraimer 619bacc0f4 use the new ChannelProviderRegistry methods 2017-06-04 07:58:00 -04:00
Marty Kraimer 7fd5af9e3c Merge pull request #42 from mrkraimer/master
fix issue 41
2017-05-25 06:02:07 -04:00
mrkraimer 6762c54e60 fix issue 41 2017-05-23 07:34:35 -04:00
Marty Kraimer 63947e1c3c Merge pull request #40 from mrkraimer/master
Fix stateChangeRequester and  channelGet
2017-04-07 13:35:06 -04:00
mrkraimer c019b205dd call stateChangeRequester when connecting; ChannelGet.get only does one get 2017-03-30 10:41:10 -04:00
41 changed files with 2908 additions and 829 deletions
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
set -e -x
make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make -j2 tapfiles
make -j2 -s test-results
fi
+111
View File
@@ -0,0 +1,111 @@
#!/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
+16 -12
View File
@@ -1,13 +1,17 @@
bin/ /cfg/
lib/ /bin/
doc/ /lib/
include/ /db/
db/ /dbd/
dbd/ /html/
documentation/html /include/
documentation/*.tag /templates/
/configure/*.local
/documentation/html
/documentation/*.tag
O.*/
/QtC-*
envPaths envPaths
configure/*.local *.orig
!configure/ExampleRELEASE.local *.log
**/O.* .*.swp
QtC-*
+31
View File
@@ -0,0 +1,31 @@
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
+11 -43
View File
@@ -1,49 +1,17 @@
pvaClientCPP # pvaClientCPP
============
pvaClient is a synchronous client interface to pvAccess, The **pvaClient** API provides a synchronous client interface that was designed to be easier to use than the original basic pvAccess client API.
which is callback based.
pvaClient is thus easier to use than pvAccess itself.
See documentation/pvaClientCPP.html for details. The pvaClientCPP module implements the pvaClient API for C++ client applications.
Building ## Links
--------
If a proper RELEASE.local file exists one directory level above pvaClientCPP - General information about EPICS can be found at the
then just type: [EPICS Controls website](https://epics-controls.org).
- API documentation for this module can be found in its
documentation directory, in particular the file
pvaClientCPP.html
make ## Building
It can also be built by: This module is included as a submodule of a full EPICS 7 release and will be compiled during builds of that software.
cp configure/ExampleRELEASE.local configure/RELEASE.local
edit configure/RELEASE.local
make
Examples
------------
Project exampleCPP has examples for pvaClientCPP
Status
------
* The API is for EPICS Version 4 release 4.6.0
* Everything defined in pvaClient.h is ready but see below for remaining work.
* Everything defined in pvaClientMultiChannel.h is ready but see below for remaining work.
pvaClientChannel
---------------
Channel::getField and channelArray are not supported for release 4.6
pvaClientMultiChannel
---------------
For release 4.5 support is available for multiDouble and NTMultiChannel.
In the future additional support should be provided that at least includes NTScalarMultiChannel.
Testing with some channels not connected has not been done.
-8
View File
@@ -1,8 +0,0 @@
EPICS4_DIR=/home/epicsv4/master
PVACCESS=${EPICS4_DIR}/pvAccessCPP
NORMATIVETYPES=${EPICS4_DIR}/normativeTypesCPP
PVDATA=${EPICS4_DIR}/pvDataCPP
PVCOMMON=${EPICS4_DIR}/pvCommonCPP
TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
EPICS_BASE=/home/install/epics/base
+33 -19
View File
@@ -1,30 +1,44 @@
# easyPVACPP RELEASE - Location of external support modules # RELEASE - Location of external support modules
# #
# IF YOU CHANGE this file or any file it includes you must # IF YOU CHANGE ANY PATHS in this file or make API changes to
# subsequently do a "gnumake rebuild" in the application's # any modules it refers to, you should do a "make rebuild" in
# top level directory. # this application's top level directory.
# #
# The build process does not check dependencies against files # The EPICS build process does not check dependencies against
# that are outside this application, thus you should also do a # any files from outside the application, so it is safest to
# "gnumake rebuild" in the top level directory after EPICS_BASE # rebuild it completely if any modules it depends on change.
# or any other external module pointed to below is rebuilt.
# #
# Host- or target-specific settings can be given in files named # Host- or target-specific settings can be given in files named
# RELEASE.$(EPICS_HOST_ARCH).Common # RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(T_A) # RELEASE.Common.$(T_A)
# RELEASE.$(EPICS_HOST_ARCH).$(T_A) # RELEASE.$(EPICS_HOST_ARCH).$(T_A)
# EPICS V4 Developers: Do not edit the locations in this file!
# #
# A RELEASE.local must exist that has the following definitions # This file is parsed by both GNUmake and an EPICS Perl script,
# EPICS_BASE=/home/install/epics/base # so it may ONLY contain definititions of paths to other support
# EPICS4_DIR=/home/epicsv4 # modules, variable definitions that are used in module paths,
# PVCOMMON=${EPICS4_DIR}/pvCommonCPP # and include statements that pull in other RELEASE files.
# PVDATA=${EPICS4_DIR}/pvDataCPP # Variables may be used before their values have been set.
# NORMATIVETYPES=${EPICSV4}/normativeTypesCPP # Build variables that are NOT used in paths should be set in
# PVACCESS=${EPICS4_DIR}/pvAccessCPP # the CONFIG_SITE file.
#Either create a RELEASE.local one level above the TOP for this module
#OR copy ExampleRELEASE.local to RELEASE.local and edit it.
# Variables and paths to dependent modules:
#MODULES = /path/to/modules
#MYMODULE = $(MODULES)/my-module
# If building the EPICS modules individually, set these:
#EPICS_PVACCESS = $(MODULES)/pvAccess
#EPICS_NORMATIVETYPES = $(MODULES)/normativeTypes
#EPICS_PVDATA = $(MODULES)/pvData
#EPICS_DATABASE = $(MODULES)/database
#EPICS_CA = $(MODULES)/ca
#EPICS_LIBCOM = $(MODULES)/libcom
#EPICS_BASE = $(MODULES)/core
# Set RULES here if you want to use build rules from elsewhere:
#RULES = $(MODULES)/build-rules
# These allow developers to override the RELEASE variable settings
# without having to modify the configure/RELEASE file itself.
-include $(TOP)/../RELEASE.local -include $(TOP)/../RELEASE.local
-include $(TOP)/../RELEASE.$(EPICS_HOST_ARCH).local
-include $(TOP)/configure/RELEASE.local -include $(TOP)/configure/RELEASE.local
+58 -8
View File
@@ -1,19 +1,69 @@
EPICS V4 release 4.6 # pvaClientCPP Module
==========================
This document summarizes the changes to the module between releases.
## Release 4.4 (EPICS 7.0.2, Dec 2018)
### API changes to PvaClientMonitor
The create method that had arguments for stateChangeRequester and monitorRequester no longer exists.
### API changes to PvaClientGet, ..., PvaClientMonitor
Previously the pvaClientGet, ..., pvaClientMonitor classes all implemented PvaClientChannelStateChangeRequester(). This method was never called and has been removed.
## Release 4.3 (EPICS 7.0.1, Dec 2017)
### Requires pvDataCPP-7.0 and pvAccessCPP-6.0 versions
This release will not work with older versions of these modules.
### Destroy methods removed
All the destroy() methods have been removed, implementation is RAII compliant.
### API changes to PvaClientMonitor
The second argument of method
static PvaClientMonitorPtr create(
PvaClientPtr const &pvaClient,
epics::pvAccess::Channel::shared_pointer const & channel,
epics::pvData::PVStructurePtr const &pvRequest
);
is now changed to
static PvaClientMonitorPtr create(
PvaClientPtr const &pvaClient,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest
);
A new method is also implemented
static PvaClientMonitorPtr create(
PvaClientPtr const &pvaClient,
std::string const & channelName,
std::string const & providerName,
std::string const & request,
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester,
PvaClientMonitorRequesterPtr const & monitorRequester
);
## Release 4.2 (EPICS V4.6, Aug 2016)
* The examples are moved to exampleCPP. * The examples are moved to exampleCPP.
* Support for channelRPC is now available. * Support for channelRPC is now available.
* In PvaClientMultiChannel checkConnected() now throws an exception if connect fails. * In PvaClientMultiChannel checkConnected() now throws an exception if connect fails.
## Release 4.1 (EPICS V4.5, Oct 2015)
EPICS V4 release 4.5
==========================
pvaClient is a synchronous API for pvAccess. pvaClient is a synchronous API for pvAccess.
This is the first release of pvaClientCPP. This is the first release of pvaClientCPP.
It provides an API that is similar to pvaClientJava. It provides an API that is similar to pvaClientJava.
+5
View File
@@ -0,0 +1,5 @@
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
@@ -0,0 +1,146 @@
<?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>
@@ -0,0 +1,123 @@
<?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>
@@ -0,0 +1,81 @@
<?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>
@@ -0,0 +1,74 @@
<?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>
@@ -0,0 +1,63 @@
<?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>
@@ -0,0 +1,59 @@
<?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>
@@ -0,0 +1,106 @@
<?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>
@@ -0,0 +1,66 @@
<?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>
@@ -0,0 +1,65 @@
<?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>
@@ -0,0 +1,71 @@
<?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>
@@ -0,0 +1,82 @@
<?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>
@@ -0,0 +1,75 @@
<?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>
@@ -0,0 +1,85 @@
<?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>
@@ -0,0 +1,66 @@
<?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>
@@ -0,0 +1,63 @@
<?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>
@@ -0,0 +1,44 @@
<?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>
@@ -0,0 +1,44 @@
<?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>
+9 -17
View File
@@ -4,7 +4,7 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<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 pva</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="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css" <link rel="stylesheet" type="text/css"
@@ -26,11 +26,11 @@
<div class="head"> <div class="head">
<h1>EPICS pvaClientCPP</h1> <h1>EPICS pvaClientCPP</h1>
<h2 class="nocount">Release 4.2.1 - 2016-08-26</h2> <h2 class="nocount">Release 4.4 - December 2018</h2>
<h2 class="nocount">Abstract</h2> <h2 class="nocount">Abstract</h2>
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly <p>pvaClient is a software library that provides, to an EPICS client programmer, a friendly
client side programming interface to the data of an EPICS based control system. It is intended client side programming interface to the data of an EPICS based control system. It is intended
for such uses as rapid development of ad hoc programs by controls engineers, or to provide for such uses as rapid development of ad hoc programs by controls engineers, or to provide
scientists a way to directly develop analytical applications.</p> scientists a way to directly develop analytical applications.</p>
@@ -62,11 +62,6 @@ The data for the channels is presented via normative type NTMultiChannel.
</div> <!-- head --> </div> <!-- head -->
<div id="toc">
<h2 class="nocount">Table of Contents</h2>
</div>
<!-- Place what you would like in the Table of Contents, inside the contents div -->
<div id="contents" class="contents"> <div id="contents" class="contents">
<hr /> <hr />
<h2>Overview</h2> <h2>Overview</h2>
@@ -76,10 +71,10 @@ pvaClientCPP is one of the components of
EPICS Version 4 EPICS Version 4
</a> </a>
</p> </p>
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP <p>This document is only a guide to help locate code and documentation related to pvaClientCPP
</p> </p>
<p> <p>
It is intended for developers that want to use pvDatabaseCPP. It is intended for developers that want to use pvaClientCPP.
</p> </p>
<h2>Developer Guide</h2> <h2>Developer Guide</h2>
<p>A guide for developers is available at <p>A guide for developers is available at
@@ -88,14 +83,11 @@ href="http://epics-pvdata.sourceforge.net/informative/developerGuide/developerGu
developerGuide developerGuide
</a> </a>
</p> </p>
<p>This guide discusses all the components that are part of an <b>EPICS V4</b> release. <p>This guide provides an overview of the components that are part of an <b>EPICS V4</b> release.
Some understanding of the components and how they are related is necessary in order to Some understanding of the components and how they are related is necessary in order to
develop code that uses pvDatabaseCPP. develop code that uses pvaClientCPP.
In particular read everything related to pvaClient. In particular read everything related to pvaClient.
</p> </p>
<p>The developerGuide discusses code in a way that applies to both CPP and C++.
For the descriptions of the CPP specific code consult the next section.
</p>
<h2>doxygen</h2> <h2>doxygen</h2>
<p>doxygen documentation is available at <p>doxygen documentation is available at
@@ -104,9 +96,9 @@ href="./html/index.html">doxygen</a>
</p> </p>
<h2>exampleCPP</h2> <h2>exampleCPP</h2>
<p>Example code is available as part of this release. <p>Example code is available at
<a <a
href="http://epics-pvdata.sourceforge.net/docbuild/exampleCPP/tip/documentation/exampleCPP.html"> href="https://github.com/epics-base/exampleCPP">
exampleCPP exampleCPP
</a> </a>
</p> </p>
+5 -15
View File
@@ -21,31 +21,22 @@ installE4 () {
local module=$1 local module=$1
local branch=$2 local branch=$2
# If microbench version does not exist, try without wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
if [ "${MB}" = "WITH_MICROBENCH" ]; then
if ! wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=WITH_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz; then
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
else
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
tar -xzf ${module}.CB-dist.tar.gz tar -xzf ${module}.CB-dist.tar.gz
} }
########################################### ###########################################
# Defaults for EPICS Base and MB # Defaults for EPICS Base
DEFAULT_BASE=3.15.4 DEFAULT_BASE=3.15.4
BASE=${BASE:-${DEFAULT_BASE}} BASE=${BASE:-${DEFAULT_BASE}}
MB=${MB:-"NO_MICROBENCH"}
########################################### ###########################################
# Dependent module branches # Dependent module branches
PVCOMMON_BRANCH="release-4.2" PVDATA_BRANCH="master"
PVDATA_BRANCH="release-6.0" PVACCESS_BRANCH="master"
PVACCESS_BRANCH="release-5.0" NORMATIVETYPES_BRANCH="master"
NORMATIVETYPES_BRANCH="release-5.1"
########################################### ###########################################
# Fetch and unpack dependencies # Fetch and unpack dependencies
@@ -59,7 +50,6 @@ cd ${STUFF}
installTool Boost 1.61.0 installTool Boost 1.61.0
installTool Base ${BASE} installTool Base ${BASE}
installE4 pvCommon ${PVCOMMON_BRANCH}
installE4 pvData ${PVDATA_BRANCH} installE4 pvData ${PVDATA_BRANCH}
installE4 pvAccess ${PVACCESS_BRANCH} installE4 pvAccess ${PVACCESS_BRANCH}
installE4 normativeTypes ${NORMATIVETYPES_BRANCH} installE4 normativeTypes ${NORMATIVETYPES_BRANCH}
+3 -10
View File
@@ -21,14 +21,7 @@ installE4 () {
local module=$1 local module=$1
local branch=$2 local branch=$2
# If microbench version does not exist, try without wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
if [ "${MB}" = "WITH_MICROBENCH" ]; then
if ! wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=WITH_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz; then
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
else
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE},MB=NO_MICROBENCH/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
fi
tar -xzf ${module}.CB-dist.tar.gz tar -xzf ${module}.CB-dist.tar.gz
} }
@@ -65,9 +58,9 @@ doxygen
########################################### ###########################################
# Publish # Publish
if [ "${PUBLISH}" != "NO" ]; then if [ "${PUBLISH}" != "DONT" ]; then
# Upload explicit dummy to ensure target directory exists # Upload explicit dummy to ensure target directory exists
echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY echo "Created by CloudBees Jenkins upload job. Should be deleted as part of the job." > DUMMY
rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/ rsync -q -e ssh DUMMY epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/DUMMY
rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/ rsync -aqP --delete -e ssh documentation epics-jenkins@web.sourceforge.net:/home/project-web/epics-pvdata/htdocs/docbuild/pvaClientCPP/${PUBLISH}/
fi fi
+4 -4
View File
@@ -6,7 +6,7 @@ include $(TOP)/configure/CONFIG
LIBRARY += pvaClient LIBRARY += pvaClient
# shared library ABI version. # shared library ABI version.
SHRLIB_VERSION ?= 4.2 SHRLIB_VERSION ?= 4.4.0
INC += pv/pvaClient.h INC += pv/pvaClient.h
INC += pv/pvaClientMultiChannel.h INC += pv/pvaClientMultiChannel.h
@@ -31,8 +31,8 @@ LIBSRCS += pvaClientNTMultiGet.cpp
LIBSRCS += pvaClientNTMultiMonitor.cpp LIBSRCS += pvaClientNTMultiMonitor.cpp
LIBSRCS += pvaClientRPC.cpp LIBSRCS += pvaClientRPC.cpp
pvaClient_LIBS += pvAccess nt pvData Com pvaClient_LIBS += nt
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS) pvaClient_LIBS += $(EPICS_BASE_PVA_CORE_LIBS)
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES include $(TOP)/configure/RULES
+393 -126
View File
File diff suppressed because it is too large Load Diff
-32
View File
@@ -145,10 +145,6 @@ public:
*/ */
PvaClientNTMultiMonitorPtr createNTMonitor( PvaClientNTMultiMonitorPtr createNTMonitor(
std::string const &request= "field(value,alarm,timeStamp)"); std::string const &request= "field(value,alarm,timeStamp)");
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientMultiChannel( PvaClientMultiChannel(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
@@ -209,10 +205,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientMultiGetDouble( PvaClientMultiGetDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -262,10 +254,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientMultiPutDouble( PvaClientMultiPutDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -329,10 +317,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientMultiMonitorDouble( PvaClientMultiMonitorDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -390,10 +374,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiGet( PvaClientNTMultiGet(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -453,10 +433,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiPut( PvaClientNTMultiPut(
PvaClientMultiChannelPtr const &pvaClientMultiChannel, PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -523,10 +499,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiMonitor( PvaClientNTMultiMonitor(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
@@ -601,10 +573,6 @@ public:
{ {
return shared_from_this(); return shared_from_this();
} }
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private: private:
PvaClientNTMultiData( PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u, epics::pvData::UnionConstPtr const & u,
+32 -10
View File
@@ -87,7 +87,18 @@ size_t PvaClientChannelCache::cacheSize()
} }
bool PvaClient::debug = false; // MSVC doesn't like making this a class static data member:
static bool debug = 0;
void PvaClient::setDebug(bool value)
{
debug = value;
}
bool PvaClient::getDebug()
{
return debug;
}
PvaClientPtr PvaClient::get(std::string const & providerNames) PvaClientPtr PvaClient::get(std::string const & providerNames)
{ {
@@ -100,47 +111,58 @@ PvaClientPtr PvaClient::get(std::string const & providerNames)
return master; return master;
} }
PvaClientPtr PvaClient::create() {return get();}
PvaClient::PvaClient(std::string const & providerNames) PvaClient::PvaClient(std::string const & providerNames)
: pvaClientChannelCache(new PvaClientChannelCache()), : pvaClientChannelCache(new PvaClientChannelCache()),
pvaStarted(false), pvaStarted(false),
caStarted(false) caStarted(false),
channelRegistry(ChannelProviderRegistry::clients())
{ {
stringstream ss(providerNames); stringstream ss(providerNames);
string providerName; string providerName;
if(getDebug()) {
cout<< "PvaClient::PvaClient()\n";
}
while (getline(ss, providerName, ' ')) while (getline(ss, providerName, ' '))
{ {
ChannelProviderRegistry::shared_pointer registry(getChannelProviderRegistry());
if(providerName=="pva") { if(providerName=="pva") {
if(getDebug()) {
cout<< "calling ClientFactory::start()\n";
}
ClientFactory::start(); ClientFactory::start();
pvaStarted = true; pvaStarted = true;
} else if(providerName=="ca") { } else if(providerName=="ca") {
if(getDebug()) {
cout<< "calling CAClientFactory::start()\n";
}
CAClientFactory::start(); CAClientFactory::start();
caStarted = true; caStarted = true;
} else { } else {
if(!registry->getProvider(providerName)) { if(!channelRegistry->getProvider(providerName)) {
cerr << "PvaClient::get provider " << providerName << " not known" << endl; cerr << "PvaClient::get provider " << providerName << " not known" << endl;
} }
} }
} }
} }
PvaClient::~PvaClient() { PvaClient::~PvaClient() {
if(PvaClient::debug) { if(getDebug()) {
cout<< "PvaClient::~PvaClient()\n" cout<< "PvaClient::~PvaClient()\n"
<< "pvaChannel cache:\n"; << "pvaChannel cache:\n";
showCache(); showCache();
} }
if(pvaStarted){ if(pvaStarted){
if(PvaClient::debug) cout<< "calling ClientFactory::stop()\n"; if(getDebug()) cout<< "calling ClientFactory::stop()\n";
ClientFactory::stop(); ClientFactory::stop();
if(PvaClient::debug) cout<< "after calling ClientFactory::stop()\n"; if(getDebug()) cout<< "after calling ClientFactory::stop()\n";
} }
if(caStarted) { if(caStarted) {
if(PvaClient::debug) cout<< "calling CAClientFactory::stop()\n"; if(getDebug()) cout<< "calling CAClientFactory::stop()\n";
CAClientFactory::stop(); CAClientFactory::stop();
if(PvaClient::debug) cout<< "after calling CAClientFactory::stop()\n"; if(getDebug()) cout<< "after calling CAClientFactory::stop()\n";
} }
channelRegistry.reset();
} }
string PvaClient:: getRequesterName() string PvaClient:: getRequesterName()
+45 -80
View File
@@ -122,60 +122,12 @@ size_t PvaClientPutCache::cacheSize()
} }
class epicsShareClass ChannelRequesterImpl : public ChannelRequester
{
PvaClientChannel::weak_pointer pvaClientChannel;
PvaClient::weak_pointer pvaClient;
public:
ChannelRequesterImpl(
PvaClientChannelPtr const & pvaClientChannel,
PvaClientPtr const &pvaClient)
: pvaClientChannel(pvaClientChannel),
pvaClient(pvaClient)
{}
virtual ~ChannelRequesterImpl() {
if(PvaClient::getDebug()) std::cout << "~ChannelRequesterImpl" << std::endl;
}
virtual std::string getRequesterName() {
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return string("clientChannel is null");
return clientChannel->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->message(message,messageType);
}
virtual void channelCreated(
const epics::pvData::Status& status,
Channel::shared_pointer const & channel)
{
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->channelCreated(status,channel);
}
virtual void channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->channelStateChange(channel,connectionState);
}
};
PvaClientChannelPtr PvaClientChannel::create( PvaClientChannelPtr PvaClientChannel::create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
string const & channelName, string const & channelName,
string const & providerName) string const & providerName)
{ {
PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName)); PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName));
channel->channelRequester = ChannelRequesterImplPtr(
new ChannelRequesterImpl(channel,pvaClient));
return channel; return channel;
} }
@@ -218,6 +170,7 @@ void PvaClientChannel::channelCreated(const Status& status, Channel::shared_poin
<< endl; << endl;
} }
Lock xx(mutex); Lock xx(mutex);
this->channel = channel;
if(connectState==connected) return; if(connectState==connected) return;
if(connectState!=connectActive) { if(connectState!=connectActive) {
string message("PvaClientChannel::channelCreated"); string message("PvaClientChannel::channelCreated");
@@ -246,25 +199,28 @@ void PvaClientChannel::channelStateChange(
<< " " << Channel::ConnectionStateNames[connectionState] << " " << Channel::ConnectionStateNames[connectionState]
<< endl; << endl;
} }
bool waitingForConnect = false;
if(connectState==connectActive) waitingForConnect = true;
if(connectionState!=Channel::CONNECTED) {
Lock xx(mutex);
string mess(channelName +
" connection state " + Channel::ConnectionStateNames[connectionState]);
message(mess,errorMessage);
connectState = notConnected;
} else {
Lock xx(mutex);
this->channel = channel;
connectState = connected;
}
if(waitingForConnect) {
Lock xx(mutex);
waitForConnect.signal();
}
PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock()); PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock());
if(req) { if(req) {
bool value = (connectionState==Channel::CONNECTED ? true : false); bool value = (connectionState==Channel::CONNECTED ? true : false);
req->channelStateChange(shared_from_this(),value); req->channelStateChange(shared_from_this(),value);
} }
Lock xx(mutex);
bool waitingForConnect = false;
if(connectState==connectActive) waitingForConnect = true;
if(connectionState!=Channel::CONNECTED) {
string mess(channelName +
" connection state " + Channel::ConnectionStateNames[connectionState]);
message(mess,errorMessage);
connectState = notConnected;
return;
} else {
connectState = connected;
}
if(waitingForConnect) waitForConnect.signal();
} }
string PvaClientChannel::getRequesterName() string PvaClientChannel::getRequesterName()
@@ -297,6 +253,9 @@ void PvaClientChannel::setStateChangeRequester(
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester) PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester)
{ {
this->stateChangeRequester = stateChangeRequester; this->stateChangeRequester = stateChangeRequester;
bool isConnected = false;
if(channel) isConnected = channel->isConnected();
stateChangeRequester->channelStateChange(shared_from_this(),isConnected);
} }
void PvaClientChannel::connect(double timeout) void PvaClientChannel::connect(double timeout)
@@ -328,13 +287,13 @@ void PvaClientChannel::issueConnect()
} }
connectState = connectActive; connectState = connectActive;
} }
ChannelProviderRegistry::shared_pointer reg = getChannelProviderRegistry(); ChannelProviderRegistry::shared_pointer reg(ChannelProviderRegistry::clients());
ChannelProvider::shared_pointer provider = reg->getProvider(providerName); channelProvider = reg->getProvider(providerName);
if(!provider) { if(!channelProvider) {
throw std::runtime_error(channelName + " provider " + providerName + " not registered"); throw std::runtime_error(channelName + " provider " + providerName + " not registered");
} }
if(PvaClient::getDebug()) cout << "PvaClientChannel::issueConnect calling provider->createChannel\n"; if(PvaClient::getDebug()) cout << "PvaClientChannel::issueConnect calling provider->createChannel\n";
channel = provider->createChannel(channelName,channelRequester,ChannelProvider::PRIORITY_DEFAULT); channel = channelProvider->createChannel(channelName,shared_from_this(),ChannelProvider::PRIORITY_DEFAULT);
if(!channel) { if(!channel) {
throw std::runtime_error(channelName + " channelCreate failed "); throw std::runtime_error(channelName + " channelCreate failed ");
} }
@@ -348,6 +307,7 @@ Status PvaClientChannel::waitConnect(double timeout)
} }
{ {
Lock xx(mutex); Lock xx(mutex);
if(!channel) return Status(Status::STATUSTYPE_ERROR,"");
if(channel->isConnected()) return Status::Ok; if(channel->isConnected()) return Status::Ok;
} }
if(timeout>0.0) { if(timeout>0.0) {
@@ -355,8 +315,9 @@ Status PvaClientChannel::waitConnect(double timeout)
} else { } else {
waitForConnect.wait(); waitForConnect.wait();
} }
if(!channel) return Status(Status::STATUSTYPE_ERROR,"pvaClientChannel::waitConnect channel is null");
if(channel->isConnected()) return Status::Ok; if(channel->isConnected()) return Status::Ok;
return Status(Status::STATUSTYPE_ERROR,channelName + " not connected"); return Status(Status::STATUSTYPE_ERROR," not connected");
} }
@@ -383,17 +344,19 @@ PvaClientProcessPtr PvaClientChannel::createProcess(PVStructurePtr const & pvRe
if(connectState!=connected) connect(5.0); if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed"); if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientProcess::create(yyy,channel,pvRequest); return PvaClientProcess::create(yyy,shared_from_this(),pvRequest);
} }
PvaClientGetPtr PvaClientChannel::get(string const & request) PvaClientGetPtr PvaClientChannel::get(string const & request)
{ {
PvaClientGetPtr pvaClientGet = pvaClientGetCache->getGet(request); PvaClientGetPtr pvaClientGet = pvaClientGetCache->getGet(request);
if(pvaClientGet) return pvaClientGet; if(!pvaClientGet) {
pvaClientGet = createGet(request); pvaClientGet = createGet(request);
pvaClientGet->connect(); pvaClientGet->connect();
pvaClientGetCache->addGet(request,pvaClientGet); pvaClientGetCache->addGet(request,pvaClientGet);
}
pvaClientGet->get();
return pvaClientGet; return pvaClientGet;
} }
@@ -415,7 +378,7 @@ PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & pvRequest)
if(connectState!=connected) connect(5.0); if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed"); if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientGet::create(yyy,channel,pvRequest); return PvaClientGet::create(yyy,shared_from_this(),pvRequest);
} }
@@ -423,10 +386,12 @@ PvaClientPutPtr PvaClientChannel::put(string const & request)
{ {
PvaClientPutPtr pvaClientPut = pvaClientPutCache->getPut(request); PvaClientPutPtr pvaClientPut = pvaClientPutCache->getPut(request);
if(pvaClientPut) return pvaClientPut; if(pvaClientPut) return pvaClientPut;
pvaClientPut = createPut(request); if(!pvaClientPut) {
pvaClientPut->connect(); pvaClientPut = createPut(request);
pvaClientPut->get(); pvaClientPut->connect();
pvaClientPutCache->addPut(request,pvaClientPut); pvaClientPut->get();
pvaClientPutCache->addPut(request,pvaClientPut);
}
return pvaClientPut; return pvaClientPut;
} }
@@ -448,7 +413,7 @@ PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest)
if(connectState!=connected) connect(5.0); if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed"); if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientPut::create(yyy,channel,pvRequest); return PvaClientPut::create(yyy,shared_from_this(),pvRequest);
} }
PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request) PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
@@ -468,7 +433,7 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvReque
if(connectState!=connected) connect(5.0); if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed"); if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientPutGet::create(yyy,channel,pvRequest); return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest);
} }
@@ -532,7 +497,7 @@ PvaClientMonitorPtr PvaClientChannel::createMonitor(PVStructurePtr const & pvR
if(connectState!=connected) connect(5.0); if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock(); PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed"); if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientMonitor::create(yyy,channel,pvRequest); return PvaClientMonitor::create(yyy,shared_from_this(),pvRequest);
} }
PVStructurePtr PvaClientChannel::rpc( PVStructurePtr PvaClientChannel::rpc(
+122 -62
View File
@@ -73,29 +73,34 @@ public:
PvaClientGetPtr PvaClientGet::create( PvaClientGetPtr PvaClientGet::create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
{ {
PvaClientGetPtr epv(new PvaClientGet(pvaClient,channel,pvRequest)); if(PvaClient::getDebug()) {
epv->channelGetRequester = ChannelGetRequesterImplPtr( cout<< "PvaClientGet::create(pvaClient,channelName,pvRequest)\n"
new ChannelGetRequesterImpl(epv,pvaClient)); << " channelName " << pvaClientChannel->getChannel()->getChannelName()
return epv; << " pvRequest " << pvRequest
<< endl;
}
PvaClientGetPtr clientGet(new PvaClientGet(pvaClient,pvaClientChannel,pvRequest));
clientGet->channelGetRequester = ChannelGetRequesterImplPtr(
new ChannelGetRequesterImpl(clientGet,pvaClient));
return clientGet;
} }
PvaClientGet::PvaClientGet( PvaClientGet::PvaClientGet(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest), pvRequest(pvRequest),
connectState(connectIdle), connectState(connectIdle),
getState(getIdle) getState(getIdle)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout << "PvaClientGet::PvaClientGet::PvaClientGet" cout << "PvaClientGet::PvaClientGet::PvaClientGet"
<< " channelName " << channel->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
} }
@@ -103,20 +108,34 @@ PvaClientGet::PvaClientGet(
PvaClientGet::~PvaClientGet() PvaClientGet::~PvaClientGet()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected"); cout<< "PvaClientGet::~PvaClientGet"
Channel::shared_pointer chan(channel.lock()); << " channelName " << pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientGet::~PvaClientGet"
<< " channelName " << channelName
<< endl; << endl;
} }
if(channelGet) channelGet->destroy();
} }
void PvaClientGet::checkGetState()
void PvaClientGet::checkConnectState()
{ {
if(connectState==connectIdle) connect(); if(PvaClient::getDebug()) {
if(getState==getIdle) get(); cout << "PvaClientGet::checkConnectState"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(!pvaClientChannel->getChannel()->isConnected()) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientGet::checkConnectState channel not connected ";
throw std::runtime_error(message);
}
if(connectState==connectIdle) {
connect();
}
if(connectState==connectActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " "
+ channelGetConnectStatus.getMessage();
throw std::runtime_error(message);
}
} }
// from ChannelGetRequester // from ChannelGetRequester
@@ -140,24 +159,32 @@ void PvaClientGet::channelGetConnect(
StructureConstPtr const & structure) StructureConstPtr const & structure)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientGet::channelGetConnect" cout << "PvaClientGet::channelGetConnect"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
{ {
Lock xx(mutex); Lock xx(mutex);
channelGetConnectStatus = status;
connectState = connected;
this->channelGet = channelGet; this->channelGet = channelGet;
if(status.isOK()) { if(status.isOK()) {
channelGetConnectStatus = status;
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);
} }
} }
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) {
req->channelGetConnect(status,shared_from_this());
}
waitForConnect.signal(); waitForConnect.signal();
} }
@@ -169,57 +196,65 @@ void PvaClientGet::getDone(
BitSetPtr const & bitSet) BitSetPtr const & bitSet)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientGet::getDone" cout << "PvaClientGet::getDone"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
{ {
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);
} }
} }
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) {
req->getDone(status,shared_from_this());
}
waitForGet.signal(); waitForGet.signal();
} }
void PvaClientGet::connect() void PvaClientGet::connect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGet::connect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::connect " + status.getMessage(); + " PvaClientGet::connect " + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientGet::issueConnect() void PvaClientGet::issueConnect()
{ {
Channel::shared_pointer chan(channel.lock()); if(PvaClient::getDebug()) {
cout << "PvaClientGet::issueConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected"); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " pvaClientGet already connected "; + " pvaClientGet already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { connectState = connectActive;
connectState = connectActive; channelGetConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelGet = chan->createChannelGet(channelGetRequester,pvRequest); channelGet = pvaClientChannel->getChannel()->createChannelGet(channelGetRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientGet::issueConnect channel was destroyed");
} }
Status PvaClientGet::waitConnect() Status PvaClientGet::waitConnect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGet::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{ {
Lock xx(mutex); Lock xx(mutex);
if(connectState==connected) { if(connectState==connected) {
@@ -227,10 +262,7 @@ Status PvaClientGet::waitConnect()
return channelGetConnectStatus; return channelGetConnectStatus;
} }
if(connectState!=connectActive) { if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::waitConnect illegal connect state "; + " PvaClientGet::waitConnect illegal connect state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -242,25 +274,29 @@ Status PvaClientGet::waitConnect()
void PvaClientGet::get() void PvaClientGet::get()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGet::get"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueGet(); issueGet();
Status status = waitGet(); Status status = waitGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::get " + status.getMessage(); + " PvaClientGet::get " + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientGet::issueGet() void PvaClientGet::issueGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGet::issueGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(getState!=getIdle) { if(getState==getActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::issueGet get aleady active "; + " PvaClientGet::issueGet get aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -270,30 +306,54 @@ void PvaClientGet::issueGet()
Status PvaClientGet::waitGet() Status PvaClientGet::waitGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGet::waitGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{ {
Lock xx(mutex); Lock xx(mutex);
if(getState==getComplete) { if(getState==getComplete) {
getState =getIdle; getState = getIdle;
return channelGetStatus; return channelGetStatus;
} }
if(getState!=getActive){ if(getState!=getActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::waitGet llegal get state"; + " PvaClientGet::waitGet llegal get state";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
} }
waitForGet.wait(); waitForGet.wait();
getState = getIdle; getState = getComplete;
return channelGetStatus; return channelGetStatus;
} }
PvaClientGetDataPtr PvaClientGet::getData() PvaClientGetDataPtr PvaClientGet::getData()
{ {
checkGetState(); if(PvaClient::getDebug()) {
cout<< "PvaClientGet::getData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkConnectState();
if(getState==getIdle) get();
return pvaClientData; return pvaClientData;
} }
void PvaClientGet::setRequester(PvaClientGetRequesterPtr const & pvaClientGetRequester)
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::setRequester"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
this->pvaClientGetRequester = pvaClientGetRequester;
}
PvaClientChannelPtr PvaClientGet::getPvaClientChannel()
{
return pvaClientChannel;
}
}} }}
+16 -1
View File
@@ -42,18 +42,29 @@ static string noTimeStamp("no timeStamp");
PvaClientGetDataPtr PvaClientGetData::create(StructureConstPtr const & structure) PvaClientGetDataPtr PvaClientGetData::create(StructureConstPtr const & structure)
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGetData::create"
<< endl;
}
PvaClientGetDataPtr epv(new PvaClientGetData(structure)); PvaClientGetDataPtr epv(new PvaClientGetData(structure));
return epv; return epv;
} }
PvaClientGetData::PvaClientGetData(StructureConstPtr const & structure) PvaClientGetData::PvaClientGetData(StructureConstPtr const & structure)
: structure(structure) : structure(structure),
pvStructure(getPVDataCreate()->createPVStructure(structure)),
bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())))
{ {
messagePrefix = ""; messagePrefix = "";
pvValue = pvStructure->getSubField("value");
} }
void PvaClientGetData::checkValue() void PvaClientGetData::checkValue()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGetData::checkValue"
<< endl;
}
if(pvValue) return; if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue); throw std::runtime_error(messagePrefix + noValue);
} }
@@ -100,6 +111,10 @@ void PvaClientGetData::setData(
PVStructurePtr const & pvStructureFrom, PVStructurePtr const & pvStructureFrom,
BitSetPtr const & bitSetFrom) BitSetPtr const & bitSetFrom)
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientGetData::setData"
<< endl;
}
pvStructure = pvStructureFrom; pvStructure = pvStructureFrom;
bitSet = bitSetFrom; bitSet = bitSetFrom;
pvValue = pvStructure->getSubField("value"); pvValue = pvStructure->getSubField("value");
+190 -151
View File
@@ -80,21 +80,51 @@ public:
PvaClientMonitorPtr PvaClientMonitor::create( PvaClientMonitorPtr PvaClientMonitor::create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
{ {
PvaClientMonitorPtr epv(new PvaClientMonitor(pvaClient,channel,pvRequest)); PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
epv->monitorRequester = MonitorRequesterImplPtr( clientMonitor->monitorRequester = MonitorRequesterImplPtr(
new MonitorRequesterImpl(epv,pvaClient)); new MonitorRequesterImpl(clientMonitor,pvaClient));
return epv; return clientMonitor;
} }
PvaClientMonitorPtr PvaClientMonitor::create(
PvaClientPtr const &pvaClient,
std::string const & channelName,
std::string const & providerName,
std::string const & request,
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester,
PvaClientMonitorRequesterPtr const & monitorRequester)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::create(pvaClient,channelName,providerName,request,stateChangeRequester,monitorRequester)\n"
<< " channelName " << channelName
<< " providerName " << providerName
<< " request " << request
<< endl;
}
CreateRequest::shared_pointer createRequest(CreateRequest::create());
PVStructurePtr pvRequest(createRequest->createRequest(request));
if(!pvRequest) throw std::runtime_error(createRequest->getMessage());
PvaClientChannelPtr pvaClientChannel = pvaClient->createChannel(channelName,providerName);
PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
clientMonitor->monitorRequester = MonitorRequesterImplPtr(
new MonitorRequesterImpl(clientMonitor,pvaClient));
if(stateChangeRequester) clientMonitor->pvaClientChannelStateChangeRequester = stateChangeRequester;
if(monitorRequester) clientMonitor->pvaClientMonitorRequester = monitorRequester;
pvaClientChannel->setStateChangeRequester(clientMonitor);
pvaClientChannel->issueConnect();
return clientMonitor;
}
PvaClientMonitor::PvaClientMonitor( PvaClientMonitor::PvaClientMonitor(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest), pvRequest(pvRequest),
isStarted(false), isStarted(false),
connectState(connectIdle), connectState(connectIdle),
@@ -102,42 +132,73 @@ PvaClientMonitor::PvaClientMonitor(
userWait(false) userWait(false)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::PvaClientMonitor()" cout<< "PvaClientMonitor::PvaClientMonitor\n"
<< " channelName " << channel->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
} }
PvaClientMonitor::~PvaClientMonitor() PvaClientMonitor::~PvaClientMonitor()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientMonitor::~PvaClientMonitor\n";
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientMonitor::~PvaClientMonitor" cout<< "PvaClientMonitor::~PvaClientMonitor"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
if(monitor) { if(monitor) {
if(isStarted) monitor->stop(); if(isStarted) monitor->stop();
monitor->destroy();
} }
} }
void PvaClientMonitor::channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::channelStateChange"
<< " channelName " << channel->getChannelName()
<< " isConnected " << (isConnected ? "true" : "false")
<< endl;
}
if(isConnected&&!monitor)
{
connectState = connectActive;
monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
}
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
if(req) {
req->channelStateChange(channel,isConnected);
}
}
void PvaClientMonitor::event(PvaClientMonitorPtr const & monitor)
{
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::event"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->event(monitor);
}
void PvaClientMonitor::checkMonitorState() void PvaClientMonitor::checkMonitorState()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::checkMonitorState" cout << "PvaClientMonitor::checkMonitorState"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " connectState " << connectState << " connectState " << connectState
<< endl; << endl;
} }
if(connectState==connectIdle) connect(); if(connectState==connectIdle) {
if(connectState==connected && !isStarted) start(); connect();
if(!isStarted) start();
return;
}
if(connectState==connectActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " "
+ monitorConnectStatus.getMessage();
throw std::runtime_error(message);
}
} }
string PvaClientMonitor::getRequesterName() string PvaClientMonitor::getRequesterName()
@@ -159,50 +220,63 @@ void PvaClientMonitor::monitorConnect(
Monitor::shared_pointer const & monitor, Monitor::shared_pointer const & monitor,
StructureConstPtr const & structure) StructureConstPtr const & structure)
{ {
Channel::shared_pointer chan(channel.lock());
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorConnect" cout << "PvaClientMonitor::monitorConnect"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
connectStatus = status; {
Lock xx(mutex);
this->monitor = monitor;
if(!status.isOK()) {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientMonitor::monitorConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
return;
}
}
bool signal = (connectState==connectWait) ? true : false;
monitorConnectStatus = status;
connectState = connected; connectState = connected;
this->monitor = monitor;
if(isStarted) { if(isStarted) {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorConnect" cout << "PvaClientMonitor::monitorConnect"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " is already started " << " is already started "
<< endl; << endl;
} }
return; return;
} }
if(status.isOK() && chan) { pvaClientData = PvaClientMonitorData::create(structure);
pvaClientData = PvaClientMonitorData::create(structure); pvaClientData->setMessagePrefix(pvaClientChannel->getChannel()->getChannelName());
pvaClientData->setMessagePrefix(chan->getChannelName()); if(signal) {
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::monitorConnect calling waitForConnect.signal\n";
}
waitForConnect.signal();
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::monitorConnect calling start\n";
}
start();
} else {
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::monitorConnect calling start\n";
}
start();
} }
if(PvaClient::getDebug()) { PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
cout << "PvaClientMonitor::monitorConnect calling waitForConnect.signal\n"; if(req) req->monitorConnect(status,shared_from_this(),structure);
}
waitForConnect.signal();
} }
void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor) void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorEvent" cout << "PvaClientMonitor::monitorEvent"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock(); PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
@@ -218,10 +292,7 @@ void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
req->unlisten(); req->unlisten();
return; return;
} }
string channelName("disconnected"); cerr << pvaClientChannel->getChannel()->getChannelName() + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n";
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cerr << channelName + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n";
} }
@@ -231,11 +302,8 @@ void PvaClientMonitor::connect()
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::connect " + " PvaClientMonitor::connect "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -244,59 +312,50 @@ void PvaClientMonitor::connect()
void PvaClientMonitor::issueConnect() void PvaClientMonitor::issueConnect()
{ {
if(PvaClient::getDebug()) cout << "PvaClientMonitor::issueConnect\n"; if(PvaClient::getDebug()) cout << "PvaClientMonitor::issueConnect\n";
Channel::shared_pointer chan(channel.lock());
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientMonitor already connected "; + " pvaClientMonitor already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { connectState = connectWait;
connectState = connectActive; monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
monitor = chan->createMonitor(monitorRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientMonitor::issueConnect() but channel disconnected");
} }
Status PvaClientMonitor::waitConnect() Status PvaClientMonitor::waitConnect()
{ {
if(PvaClient::getDebug()) cout << "PvaClientMonitor::waitConnect\n";
if(connectState==connected) {
if(!connectStatus.isOK()) connectState = connectIdle;
return connectStatus;
}
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientMonitor::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::waitConnect calling waitForConnect.wait\n"; cout << "PvaClientMonitor::waitConnect "
<< pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(connectState==connected) {
if(!monitorConnectStatus.isOK()) connectState = connectIdle;
return monitorConnectStatus;
}
if(connectState!=connectWait) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
} }
waitForConnect.wait(); waitForConnect.wait();
connectState = connectStatus.isOK() ? connected : connectIdle; connectState = monitorConnectStatus.isOK() ? connected : connectIdle;
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::waitConnect" cout << "PvaClientMonitor::waitConnect"
<< " connectStatus " << (connectStatus.isOK() ? "connected" : "not connected"); << " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected")
<< endl;
} }
return connectStatus; return monitorConnectStatus;
} }
void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester) void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::setRequester" cout << "PvaClientMonitor::setRequester"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
this->pvaClientMonitorRequester = pvaClientMonitorRequester; this->pvaClientMonitorRequester = pvaClientMonitorRequester;
@@ -305,30 +364,17 @@ void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClie
void PvaClientMonitor::start() void PvaClientMonitor::start()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::start" cout << "PvaClientMonitor::start"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " connectState " << connectState << " connectState " << connectState
<< endl; << endl;
} }
if(isStarted) { if(isStarted) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cerr << "PvaClientMonitor::start"
<< " channelName " << channelName
<< " why is this called twice "
<< endl;
return; return;
} }
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(connectState!=connected) { if(connectState!=connected) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::start illegal state "; + " PvaClientMonitor::start illegal state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -336,15 +382,45 @@ void PvaClientMonitor::start()
monitor->start(); monitor->start();
} }
void PvaClientMonitor::start(string const & request)
{
if(PvaClient::getDebug()) {
cout<< "PvaMonitor::start(request)"
<< " request " << request
<< endl;
}
PvaClientPtr client(pvaClient.lock());
if(!client) throw std::runtime_error("pvaClient was deleted");
if(!pvaClientChannel->getChannel()->isConnected()) {
client->message(
"PvaClientMonitor::start(request) but not connected",
errorMessage);
return;
}
CreateRequest::shared_pointer createRequest(CreateRequest::create());
PVStructurePtr pvr(createRequest->createRequest(request));
if(!pvr) throw std::runtime_error(createRequest->getMessage());
if(monitor) {
if(isStarted) monitor->stop();
}
monitorRequester.reset();
monitor.reset();
isStarted = false;
connectState = connectIdle;
userPoll = false;
userWait = false;
monitorRequester = MonitorRequesterImplPtr(
new MonitorRequesterImpl(shared_from_this(),client));
pvRequest = pvr;
connect();
}
void PvaClientMonitor::stop() void PvaClientMonitor::stop()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::stop" cout << "PvaClientMonitor::stop"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
if(!isStarted) return; if(!isStarted) return;
@@ -355,30 +431,11 @@ void PvaClientMonitor::stop()
bool PvaClientMonitor::poll() bool PvaClientMonitor::poll()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::poll" cout << "PvaClientMonitor::poll"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
checkMonitorState(); checkMonitorState();
if(!isStarted) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::poll illegal state ";
throw std::runtime_error(message);
}
if(userPoll) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::poll did not release last";
throw std::runtime_error(message);
}
monitorElement = monitor->poll(); monitorElement = monitor->poll();
if(!monitorElement) return false; if(!monitorElement) return false;
userPoll = true; userPoll = true;
@@ -389,18 +446,12 @@ bool PvaClientMonitor::poll()
bool PvaClientMonitor::waitEvent(double secondsToWait) bool PvaClientMonitor::waitEvent(double secondsToWait)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::waitEvent" cout << "PvaClientMonitor::waitEvent"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
if(!isStarted) { if(!isStarted) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::waitEvent illegal state "; + " PvaClientMonitor::waitEvent illegal state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -418,26 +469,12 @@ bool PvaClientMonitor::waitEvent(double secondsToWait)
void PvaClientMonitor::releaseEvent() void PvaClientMonitor::releaseEvent()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::releaseEvent" cout << "PvaClientMonitor::releaseEvent"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
if(!isStarted) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::releaseEvent monitor not started ";
throw std::runtime_error(message);
}
if(!userPoll) { if(!userPoll) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientMonitor::releaseEvent did not call poll"; + " PvaClientMonitor::releaseEvent did not call poll";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -445,14 +482,16 @@ void PvaClientMonitor::releaseEvent()
monitor->release(monitorElement); monitor->release(monitorElement);
} }
PvaClientChannelPtr PvaClientMonitor::getPvaClientChannel()
{
return pvaClientChannel;
}
PvaClientMonitorDataPtr PvaClientMonitor::getData() PvaClientMonitorDataPtr PvaClientMonitor::getData()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::getData" cout << "PvaClientMonitor::getData"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
checkMonitorState(); checkMonitorState();
+1 -1
View File
@@ -145,7 +145,7 @@ void PvaClientNTMultiData::endDeltaTime()
PVStructurePtr pvst = topPVStructure[i]; PVStructurePtr pvst = topPVStructure[i];
if(!pvst) { if(!pvst) {
unionValue[i] = PVUnionPtr(); unionValue[i] = PVUnionPtr();
} else { } else if(unionValue[i]) {
unionValue[i]->set(pvst->getSubField("value")); unionValue[i]->set(pvst->getSubField("value"));
if(gotAlarm) if(gotAlarm)
{ {
+129 -30
View File
@@ -70,33 +70,46 @@ public:
PvaClientProcessPtr PvaClientProcess::create( PvaClientProcessPtr PvaClientProcess::create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
{ {
PvaClientProcessPtr epv(new PvaClientProcess(pvaClient,channel,pvRequest)); if(PvaClient::getDebug()) {
epv->channelProcessRequester = ChannelProcessRequesterImplPtr( cout<< "PvaClientProcess::create(pvaClient,channelName,pvRequest)\n"
new ChannelProcessRequesterImpl(epv,pvaClient)); << " channelName " << pvaClientChannel->getChannel()->getChannelName()
return epv; << " pvRequest " << pvRequest
<< endl;
}
PvaClientProcessPtr channelProcess(new PvaClientProcess(pvaClient,pvaClientChannel,pvRequest));
channelProcess->channelProcessRequester = ChannelProcessRequesterImplPtr(
new ChannelProcessRequesterImpl(channelProcess,pvaClient));
return channelProcess;
} }
PvaClientProcess::PvaClientProcess( PvaClientProcess::PvaClientProcess(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest), pvRequest(pvRequest),
connectState(connectIdle), connectState(connectIdle),
processState(processIdle) processState(processIdle)
{ {
if(PvaClient::getDebug()) cout<< "PvaClientProcess::PvaClientProcess()\n"; if(PvaClient::getDebug()) {
cout<< "PvaClientProcess::PvaClientProcess()"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
} }
PvaClientProcess::~PvaClientProcess() PvaClientProcess::~PvaClientProcess()
{ {
if(PvaClient::getDebug()) cout<< "PvaClientProcess::~PvaClientProcess()\n"; if(PvaClient::getDebug()) {
channelProcess->destroy(); cout<< "PvaClientProcess::~PvaClientProcess()"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
} }
// from ChannelProcessRequester // from ChannelProcessRequester
@@ -118,9 +131,31 @@ void PvaClientProcess::channelProcessConnect(
const Status& status, const Status& status,
ChannelProcess::shared_pointer const & channelProcess) ChannelProcess::shared_pointer const & channelProcess)
{ {
channelProcessConnectStatus = status; if(PvaClient::getDebug()) {
connectState = connected; cout << "PvaClientProcess::channelProcessConnect"
this->channelProcess = channelProcess; << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
this->channelProcess = channelProcess;
if(status.isOK()) {
channelProcessConnectStatus = status;
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);
}
}
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) {
req->channelProcessConnect(status,shared_from_this());
}
waitForConnect.signal(); waitForConnect.signal();
} }
@@ -129,40 +164,70 @@ void PvaClientProcess::processDone(
const Status& status, const Status& status,
ChannelProcess::shared_pointer const & channelProcess) ChannelProcess::shared_pointer const & channelProcess)
{ {
channelProcessStatus = status; if(PvaClient::getDebug()) {
processState = processComplete; cout << "PvaClientProcess::processDone"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelProcessStatus = status;
processState = processComplete;
}
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) {
req->processDone(status,shared_from_this());
}
waitForProcess.signal(); waitForProcess.signal();
} }
void PvaClientProcess::connect() void PvaClientProcess::connect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::connect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientProcess::connect " + status.getMessage(); + " PvaClientProcess::connect " + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientProcess::issueConnect() void PvaClientProcess::issueConnect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::issueConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientProcess already connected "; + " pvaClientProcess already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
connectState = connectActive; connectState = connectActive;
channelProcess = channel->createChannelProcess(channelProcessRequester,pvRequest); channelProcessConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelProcess = pvaClientChannel->getChannel()->createChannelProcess(channelProcessRequester,pvRequest);
} }
Status PvaClientProcess::waitConnect() Status PvaClientProcess::waitConnect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connected) { if(connectState==connected) {
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle; if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
return channelProcessConnectStatus; return channelProcessConnectStatus;
} }
if(connectState!=connectActive) { if(connectState!=connectActive) {
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientProcess illegal connect state "; + " pvaClientProcess illegal connect state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -173,19 +238,29 @@ Status PvaClientProcess::waitConnect()
void PvaClientProcess::process() void PvaClientProcess::process()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::process"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueProcess(); issueProcess();
Status status = waitProcess(); Status status = waitProcess();
if(status.isOK()) return; if(status.isOK()) return;
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientProcess::process" + status.getMessage(); + " PvaClientProcess::process" + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
} }
void PvaClientProcess::issueProcess() void PvaClientProcess::issueProcess()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::issueProcess"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(processState!=processIdle) { if(processState==processActive) {
string message = string("channel ") + channel->getChannelName() string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientProcess::issueProcess process aleady active "; + " PvaClientProcess::issueProcess process aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -195,18 +270,42 @@ void PvaClientProcess::issueProcess()
Status PvaClientProcess::waitProcess() Status PvaClientProcess::waitProcess()
{ {
if(processState==processComplete) { if(PvaClient::getDebug()) {
processState = processIdle; cout << "PvaClientProcess::waitProcess"
return channelProcessStatus; << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
} }
if(processState!=processActive){ {
string message = string("channel ") + channel->getChannelName() Lock xx(mutex);
+ " PvaClientProcess::waitProcess llegal process state"; if(processState==processComplete) {
throw std::runtime_error(message); 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 = processIdle; processState = processComplete;
return channelProcessStatus; return channelProcessStatus;
} }
void PvaClientProcess::setRequester(PvaClientProcessRequesterPtr const & pvaClientProcessRequester)
{
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::setRequester"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
this->pvaClientProcessRequester = pvaClientProcessRequester;
}
PvaClientChannelPtr PvaClientProcess::getPvaClientChannel()
{
return pvaClientChannel;
}
}} }}
+163 -94
View File
@@ -70,7 +70,7 @@ public:
clientPut->getDone(status,channelPut,pvStructure,bitSet); clientPut->getDone(status,channelPut,pvStructure,bitSet);
} }
virtual void putDone( virtual void putDone(
const Status& status, const Status& status,
ChannelPut::shared_pointer const & channelPut) ChannelPut::shared_pointer const & channelPut)
{ {
@@ -82,30 +82,29 @@ public:
PvaClientPutPtr PvaClientPut::create( PvaClientPutPtr PvaClientPut::create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
{ {
PvaClientPutPtr epv(new PvaClientPut(pvaClient,channel,pvRequest)); PvaClientPutPtr clientPut(new PvaClientPut(pvaClient,pvaClientChannel,pvRequest));
epv->channelPutRequester = ChannelPutRequesterImplPtr( clientPut->channelPutRequester = ChannelPutRequesterImplPtr(
new ChannelPutRequesterImpl(epv,pvaClient)); new ChannelPutRequesterImpl(clientPut,pvaClient));
return epv; return clientPut;
} }
PvaClientPut::PvaClientPut( PvaClientPut::PvaClientPut(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest), pvRequest(pvRequest),
connectState(connectIdle), connectState(connectIdle),
putState(putIdle) putState(putIdle)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout<< "PvaClientPut::PvaClientPut" cout<< "PvaClientPut::PvaClientPut"
<< " channelName " << channel->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
} }
@@ -113,21 +112,28 @@ PvaClientPut::PvaClientPut(
PvaClientPut::~PvaClientPut() PvaClientPut::~PvaClientPut()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientPut::~PvaClientPut" cout<< "PvaClientPut::~PvaClientPut"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
if(channelPut) channelPut->destroy();
} }
void PvaClientPut::checkPutState()
void PvaClientPut::checkConnectState()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPut::checkConnectState"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle){ if(connectState==connectIdle){
connect(); connect();
get(); }
if(connectState==connectActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " "
+ channelPutConnectStatus.getMessage();
throw std::runtime_error(message);
} }
} }
@@ -151,23 +157,32 @@ void PvaClientPut::channelPutConnect(
StructureConstPtr const & structure) StructureConstPtr const & structure)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::channelPutConnect" cout << "PvaClientPut::channelPutConnect"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
{ {
Lock xx(mutex); Lock xx(mutex);
channelPutConnectStatus = status;
this->channelPut = channelPut; this->channelPut = channelPut;
if(status.isOK()) { if(status.isOK()) {
channelPutConnectStatus = status;
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);
} }
} }
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->channelPutConnect(status,shared_from_this());
}
waitForConnect.signal(); waitForConnect.signal();
} }
@@ -179,21 +194,26 @@ void PvaClientPut::getDone(
BitSetPtr const & bitSet) BitSetPtr const & bitSet)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::getDone" cout << "PvaClientPut::getDone"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
channelGetPutStatus = status; {
if(status.isOK()) { Lock xx(mutex);
PVStructurePtr pvs = pvaClientData->getPVStructure(); channelGetPutStatus = status;
pvs->copyUnchecked(*pvStructure,*bitSet); if(status.isOK()) {
BitSetPtr bs = pvaClientData->getChangedBitSet(); PVStructurePtr pvs = pvaClientData->getPVStructure();
bs->clear(); pvs->copyUnchecked(*pvStructure,*bitSet);
*bs |= *bitSet; BitSetPtr bs = pvaClientData->getChangedBitSet();
bs->clear();
*bs |= *bitSet;
putState = putComplete;
}
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->getDone(status,shared_from_this());
} }
waitForGetPut.signal(); waitForGetPut.signal();
} }
@@ -203,28 +223,35 @@ void PvaClientPut::putDone(
ChannelPut::shared_pointer const & channelPut) ChannelPut::shared_pointer const & channelPut)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::putDone" cout << "PvaClientPut::putDone"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
channelGetPutStatus = status; {
Lock xx(mutex);
channelGetPutStatus = status;
putState = putComplete;
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->putDone(status,shared_from_this());
}
waitForGetPut.signal(); waitForGetPut.signal();
} }
void PvaClientPut::connect() void PvaClientPut::connect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPut::connect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::connect " + " PvaClientPut::connect "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -232,24 +259,29 @@ void PvaClientPut::connect()
void PvaClientPut::issueConnect() void PvaClientPut::issueConnect()
{ {
Channel::shared_pointer chan(channel.lock()); if(PvaClient::getDebug()) {
cout << "PvaClientPut::issueConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected"); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " pvaClientPut already connected "; + " pvaClientPut already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { connectState = connectActive;
connectState = connectActive; channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelPut = chan->createChannelPut(channelPutRequester,pvRequest); channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientPut::issueConnect() but channel disconnected");
} }
Status PvaClientPut::waitConnect() Status PvaClientPut::waitConnect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPut::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{ {
Lock xx(mutex); Lock xx(mutex);
if(connectState==connected) { if(connectState==connected) {
@@ -257,10 +289,7 @@ Status PvaClientPut::waitConnect()
return channelPutConnectStatus; return channelPutConnectStatus;
} }
if(connectState!=connectActive) { if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPut::waitConnect illegal connect state "; + " PvaClientPut::waitConnect illegal connect state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -272,14 +301,16 @@ Status PvaClientPut::waitConnect()
void PvaClientPut::get() void PvaClientPut::get()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPut::get"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueGet(); issueGet();
Status status = waitGet(); Status status = waitGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::get " + " PvaClientPut::get "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -287,13 +318,15 @@ void PvaClientPut::get()
void PvaClientPut::issueGet() void PvaClientPut::issueGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPut::issueGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putState!=putIdle) { if(putState==getActive || putState==putActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ "PvaClientPut::issueGet get or put aleady active "; + "PvaClientPut::issueGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -303,30 +336,37 @@ void PvaClientPut::issueGet()
Status PvaClientPut::waitGet() Status PvaClientPut::waitGet()
{ {
if(putState!=getActive){ if(PvaClient::getDebug()) {
Channel::shared_pointer chan(channel.lock()); cout << "PvaClientPut::waitGet"
string channelName("disconnected"); << " channelName " << pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName(); << endl;
string message = string("channel ") }
+ channelName {
+ " PvaClientPut::waitGet illegal put state"; Lock xx(mutex);
throw std::runtime_error(message); 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 = putIdle;
return channelGetPutStatus; return channelGetPutStatus;
} }
void PvaClientPut::put() void PvaClientPut::put()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPut::put"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issuePut(); issuePut();
Status status = waitPut(); Status status = waitPut();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::put " + " PvaClientPut::put "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -334,14 +374,18 @@ void PvaClientPut::put()
void PvaClientPut::issuePut() void PvaClientPut::issuePut()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPut::issuePut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " pvStructure\n" << pvaClientData->getPVStructure()
<< " bitSet " << *pvaClientData->getChangedBitSet() << endl
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putState!=putIdle) { if(putState==getActive || putState==putActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ "PvaClientPut::issueGet 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;
@@ -350,26 +394,51 @@ void PvaClientPut::issuePut()
Status PvaClientPut::waitPut() Status PvaClientPut::waitPut()
{ {
if(putState!=putActive){ if(PvaClient::getDebug()) {
Channel::shared_pointer chan(channel.lock()); cout << "PvaClientPut::waitPut"
string channelName("disconnected"); << " channelName " << pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName(); << endl;
string message = string("channel ") }
+ channelName {
+ " PvaClientPut::waitPut illegal put state"; Lock xx(mutex);
throw std::runtime_error(message); 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 = putIdle;
if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear(); if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
return channelGetPutStatus; return channelGetPutStatus;
} }
PvaClientPutDataPtr PvaClientPut::getData() PvaClientPutDataPtr PvaClientPut::getData()
{ {
checkPutState(); if(PvaClient::getDebug()) {
cout<< "PvaClientPut::getData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkConnectState();
if(putState==putIdle) get();
return pvaClientData; return pvaClientData;
} }
void PvaClientPut::setRequester(PvaClientPutRequesterPtr const & pvaClientPutRequester)
{
if(PvaClient::getDebug()) {
cout << "PvaClientPut::setRequester"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
this->pvaClientPutRequester = pvaClientPutRequester;
}
PvaClientChannelPtr PvaClientPut::getPvaClientChannel()
{
return pvaClientChannel;
}
}} }}
+200 -98
View File
@@ -96,28 +96,28 @@ public:
PvaClientPutGetPtr PvaClientPutGet::create( PvaClientPutGetPtr PvaClientPutGet::create(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
{ {
PvaClientPutGetPtr epv(new PvaClientPutGet(pvaClient,channel,pvRequest)); PvaClientPutGetPtr clientPutGet(new PvaClientPutGet(pvaClient,pvaClientChannel,pvRequest));
epv->channelPutGetRequester = ChannelPutGetRequesterImplPtr( clientPutGet->channelPutGetRequester = ChannelPutGetRequesterImplPtr(
new ChannelPutGetRequesterImpl(epv,pvaClient)); new ChannelPutGetRequesterImpl(clientPutGet,pvaClient));
return epv; return clientPutGet;
} }
PvaClientPutGet::PvaClientPutGet( PvaClientPutGet::PvaClientPutGet(
PvaClientPtr const &pvaClient, PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel, PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest) PVStructurePtr const &pvRequest)
: pvaClient(pvaClient), : pvaClient(pvaClient),
channel(channel), pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest), pvRequest(pvRequest),
connectState(connectIdle), connectState(connectIdle),
putGetState(putGetIdle) putGetState(putGetIdle)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout<< "PvaClientPutGet::PvaClientPutGet" cout<< "PvaClientPutGet::PvaClientPutGet"
<< " channelName " << channel->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
} }
@@ -125,21 +125,27 @@ PvaClientPutGet::PvaClientPutGet(
PvaClientPutGet::~PvaClientPutGet() PvaClientPutGet::~PvaClientPutGet()
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientPutGet::~PvaClientPutGet" cout<< "PvaClientPutGet::~PvaClientPutGet"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl; << endl;
} }
channelPutGet->destroy();
} }
void PvaClientPutGet::checkPutGetState() void PvaClientPutGet::checkPutGetState()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::checkPutGetState"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle){ if(connectState==connectIdle){
connect(); connect();
getPut(); }
if(connectState==connectActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " "
+ channelPutGetConnectStatus.getMessage();
throw std::runtime_error(message);
} }
} }
@@ -165,17 +171,33 @@ void PvaClientPutGet::channelPutGetConnect(
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::channelPutGetConnect" cout << "PvaClientPutGet::channelPutGetConnect"
<< " channelName " << channelPutGet->getChannel()->getChannelName() << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
channelPutGetConnectStatus = status; {
this->channelPutGet = channelPutGet; Lock xx(mutex);
if(status.isOK()) { this->channelPutGet = channelPutGet;
pvaClientPutData = PvaClientPutData::create(putStructure); if(status.isOK()) {
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); channelPutGetConnectStatus = status;
pvaClientGetData = PvaClientGetData::create(getStructure); connectState = connected;
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); pvaClientPutData = PvaClientPutData::create(putStructure);
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
pvaClientGetData = PvaClientGetData::create(getStructure);
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientPutGet::channelPutGetConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
}
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->channelPutGetConnect(status,shared_from_this());
} }
waitForConnect.signal(); waitForConnect.signal();
@@ -188,17 +210,23 @@ void PvaClientPutGet::putGetDone(
BitSetPtr const & getChangedBitSet) BitSetPtr const & getChangedBitSet)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::putGetDone" cout << "PvaClientPutGet::putGetDone"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
channelPutGetStatus = status; channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) { if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet); PVStructurePtr pvs = pvaClientGetData->getPVStructure();
pvs->copyUnchecked(*getPVStructure,*getChangedBitSet);
BitSetPtr bs = pvaClientGetData->getChangedBitSet();
bs->clear();
*bs |= *getChangedBitSet;
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->putGetDone(status,shared_from_this());
} }
waitForPutGet.signal(); waitForPutGet.signal();
} }
@@ -210,15 +238,13 @@ void PvaClientPutGet::getPutDone(
BitSetPtr const & putBitSet) BitSetPtr const & putBitSet)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::getPutDone" cout << "PvaClientPutGet::getPutDone"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
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);
@@ -226,6 +252,10 @@ void PvaClientPutGet::getPutDone(
bs->clear(); bs->clear();
*bs |= *putBitSet; *bs |= *putBitSet;
} }
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->getPutDone(status,shared_from_this());
}
waitForPutGet.signal(); waitForPutGet.signal();
} }
@@ -236,31 +266,39 @@ void PvaClientPutGet::getGetDone(
BitSetPtr const & getChangedBitSet) BitSetPtr const & getChangedBitSet)
{ {
if(PvaClient::getDebug()) { if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::getGetDone" cout << "PvaClientPutGet::getGetDone"
<< " channelName " << channelName << " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false") << " status.isOK " << (status.isOK() ? "true" : "false")
<< endl; << endl;
} }
channelPutGetStatus = status; channelPutGetStatus = status;
putGetState = putGetComplete;
if(status.isOK()) { if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet); PVStructurePtr pvs = pvaClientGetData->getPVStructure();
pvs->copyUnchecked(*getPVStructure,*getChangedBitSet);
BitSetPtr bs = pvaClientGetData->getChangedBitSet();
bs->clear();
*bs |= *getChangedBitSet;
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->getGetDone(status,shared_from_this());
} }
waitForPutGet.signal(); waitForPutGet.signal();
} }
void PvaClientPutGet::connect() void PvaClientPutGet::connect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::connect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueConnect(); issueConnect();
Status status = waitConnect(); Status status = waitConnect();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::connect " + " PvaClientPutGet::connect "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -268,24 +306,29 @@ void PvaClientPutGet::connect()
void PvaClientPutGet::issueConnect() void PvaClientPutGet::issueConnect()
{ {
Channel::shared_pointer chan(channel.lock()); if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issueConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState!=connectIdle) { if(connectState!=connectIdle) {
string channelName("disconnected"); string message = string("channel ")
if(chan) channelName = chan->getChannelName(); + pvaClientChannel->getChannel()->getChannelName()
string message = string("channel ") + channelName
+ " pvaClientPutGet already connected "; + " pvaClientPutGet already connected ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
if(chan) { connectState = connectActive;
connectState = connectActive; channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelPutGet = chan->createChannelPutGet(channelPutGetRequester,pvRequest); channelPutGet = pvaClientChannel->getChannel()->createChannelPutGet(channelPutGetRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientPutGet::issueConnect() but channel disconnected");
} }
Status PvaClientPutGet::waitConnect() Status PvaClientPutGet::waitConnect()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{ {
Lock xx(mutex); Lock xx(mutex);
if(connectState==connected) { if(connectState==connected) {
@@ -293,30 +336,30 @@ Status PvaClientPutGet::waitConnect()
return channelPutGetConnectStatus; return channelPutGetConnectStatus;
} }
if(connectState!=connectActive) { if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ")
string channelName("disconnected"); + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitConnect illegal connect state "; + " PvaClientPutGet::waitConnect illegal connect state ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
} }
waitForConnect.wait(); waitForConnect.wait();
connectState = channelPutGetConnectStatus.isOK() ? connected : connectIdle; if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle;
return channelPutGetConnectStatus; return channelPutGetConnectStatus;
} }
void PvaClientPutGet::putGet() void PvaClientPutGet::putGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::putGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issuePutGet(); issuePutGet();
Status status = waitPutGet(); Status status = waitPutGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::putGet " + " PvaClientPut::putGet "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -324,12 +367,15 @@ void PvaClientPutGet::putGet()
void PvaClientPutGet::issuePutGet() void PvaClientPutGet::issuePutGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issuePutGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) { if(putGetState==putGetActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ")
string channelName("disconnected"); + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::issuePutGet get or put aleady active "; + " PvaClientPutGet::issuePutGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -340,29 +386,35 @@ void PvaClientPutGet::issuePutGet()
Status PvaClientPutGet::waitPutGet() Status PvaClientPutGet::waitPutGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitPutGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(putGetState==putGetComplete) return channelPutGetStatus;
if(putGetState!=putGetActive){ if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ")
string channelName("disconnected"); + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitPutGet get or put aleady active "; + " PvaClientPutGet::waitPutGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForPutGet.wait(); waitForPutGet.wait();
putGetState = putGetIdle; if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear();
return channelPutGetStatus; return channelPutGetStatus;
} }
void PvaClientPutGet::getGet() void PvaClientPutGet::getGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::getGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueGetGet(); issueGetGet();
Status status = waitGetGet(); Status status = waitGetGet();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::getGet " + " PvaClientPut::getGet "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -370,12 +422,15 @@ void PvaClientPutGet::getGet()
void PvaClientPutGet::issueGetGet() void PvaClientPutGet::issueGetGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issueGetGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) { if(putGetState==putGetActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ")
string channelName("disconnected"); + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::issueGetGet get or put aleady active "; + " PvaClientPutGet::issueGetGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -385,29 +440,34 @@ void PvaClientPutGet::issueGetGet()
Status PvaClientPutGet::waitGetGet() Status PvaClientPutGet::waitGetGet()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitGetGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(putGetState==putGetComplete) return channelPutGetStatus;
if(putGetState!=putGetActive){ if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ")
string channelName("disconnected"); + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitGetGet get or put aleady active "; + " PvaClientPutGet::waitGetGet get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForPutGet.wait(); waitForPutGet.wait();
putGetState = putGetIdle;
return channelPutGetStatus; return channelPutGetStatus;
} }
void PvaClientPutGet::getPut() void PvaClientPutGet::getPut()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::getGetPut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueGetPut(); issueGetPut();
Status status = waitGetPut(); Status status = waitGetPut();
if(status.isOK()) return; if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") string message = string("channel ")
+ channelName + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::getPut " + " PvaClientPut::getPut "
+ status.getMessage(); + status.getMessage();
throw std::runtime_error(message); throw std::runtime_error(message);
@@ -415,12 +475,15 @@ void PvaClientPutGet::getPut()
void PvaClientPutGet::issueGetPut() void PvaClientPutGet::issueGetPut()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issueGetPut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect(); if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) { if(putGetState==putGetActive) {
Channel::shared_pointer chan(channel.lock()); string message = string("channel ")
string channelName("disconnected"); + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::issueGetPut get or put aleady active "; + " PvaClientPutGet::issueGetPut get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
@@ -430,29 +493,68 @@ void PvaClientPutGet::issueGetPut()
Status PvaClientPutGet::waitGetPut() Status PvaClientPutGet::waitGetPut()
{ {
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitGetPut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(putGetState==putGetComplete) return channelPutGetStatus;
if(putGetState!=putGetActive){ if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock()); string message = string("channel ")
string channelName("disconnected"); + pvaClientChannel->getChannel()->getChannelName()
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitGetPut get or put aleady active "; + " PvaClientPutGet::waitGetPut get or put aleady active ";
throw std::runtime_error(message); throw std::runtime_error(message);
} }
waitForPutGet.wait(); waitForPutGet.wait();
putGetState = putGetIdle;
return channelPutGetStatus; return channelPutGetStatus;
} }
PvaClientGetDataPtr PvaClientPutGet::getGetData() PvaClientGetDataPtr PvaClientPutGet::getGetData()
{ {
if(PvaClient::getDebug()) {
cout<< "PvaClientPutGet::getGetData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkPutGetState(); checkPutGetState();
if(putGetState==putGetIdle){
getGet();
getPut();
}
return pvaClientGetData; return pvaClientGetData;
} }
PvaClientPutDataPtr PvaClientPutGet::getPutData() PvaClientPutDataPtr PvaClientPutGet::getPutData()
{ {
if(PvaClient::getDebug()) {
cout<< "PvaClientPutGet::getPutData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkPutGetState(); checkPutGetState();
if(putGetState==putGetIdle){
getGet();
getPut();
}
return pvaClientPutData; return pvaClientPutData;
} }
void PvaClientPutGet::setRequester(PvaClientPutGetRequesterPtr const & pvaClientPutGetRequester)
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::setRequester"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
this->pvaClientPutGetRequester = pvaClientPutGetRequester;
}
PvaClientChannelPtr PvaClientPutGet::getPvaClientChannel()
{
return pvaClientChannel;
}
}} }}