131 Commits

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

I still want to do more testing, especially on connection management.
Also relese notes and documentation needs work.
2021-02-26 12:32:15 -05:00
mrkraimer b665dac669 The following changes were made:
1) PvaClientChannel::channelCreated no longer declares channel connected.
   PvaClientChannel::channelStateChange does this.
2) PvaClientNTMultiData::endDeltaTime no longer calls unionValue[i] = PVUnionPtr()
2021-02-23 09:25:19 -05:00
mrkraimer 65a69a8901 Changes include:
1) Added method PvaClientNTMultiData::getChannelChangeFlags.
2) In pvaClientMultiChannel made methods not intended for client protected.
3) Fixed many connection related problems.
4) Cleaned up doxygen.
2021-02-17 11:10:41 -05:00
Andrew Johnson 7722fdf353 Set next development version 2020-05-28 16:26:01 -05:00
Andrew Johnson bc9ac8422c Update version numbers for release 2020-05-28 15:49:41 -05:00
mrkraimer c3aec4e27b get ready for next epics7 release 2020-05-20 14:01:16 -04:00
Marty Kraimer 0abfeef5ed Merge pull request #65 from dirk-zimoch/CleanupWhitespace
Cleanup whitespace
2020-05-20 08:50:14 -04:00
zimoch 745119cf77 removed empty lines at end of file 2020-04-15 17:51:17 +02:00
zimoch 9f794721ab removed spaces at end of line 2020-04-15 17:49:54 +02:00
zimoch 8f21ac8b9d replaced tabs with spaces 2020-04-15 17:45:02 +02:00
Marty Kraimer 9add9daf85 Merge pull request #64 from epics-base/issue#63
fix issue 63; add PvaClientData::getSinglePVField; simplify getDouble…
2019-12-04 05:46:44 -05:00
mrkraimer aaacadb42d fix issue 63; add PvaClientData::getSinglePVField; simplify getDouble, putDouble, etc 2019-12-02 10:32:48 -05:00
Andrew Johnson 5961c83477 Incr version and set development flag after release 2019-11-01 12:28:27 -05:00
Andrew Johnson b724b72624 Clear development flag for 4.7.0 release 2019-11-01 12:20:59 -05:00
Andrew Johnson fc42cf798e Release notes for 4.7.0 2019-11-01 11:09:28 -05:00
Marty Kraimer 71181afc93 Update .travis.yml 2019-09-13 09:15:35 -04:00
Ralph Lange b92a3ddaa4 rtd-ci: add read-the-docs integration 2019-09-06 14:18:19 +02:00
Andrew Johnson 246cceae3e Update version number to 4.7.0 DEVELOPMENT 2019-08-13 10:46:37 -05:00
mrkraimer 3f4df39ee0 fix issue #62 PvaClientData::parse bug 2019-08-12 06:03:55 -04:00
Marty Kraimer 837924af2e Update RELEASE_NOTES.md 2019-08-02 08:45:10 -04:00
Marty Kraimer 7b0e2b5986 Merge pull request #61 from mrkraimer/master
add JSON support
2019-08-02 08:42:29 -04:00
mrkraimer c84b24bb30 Merge https://github.com/epics-base/pvaClientCPP
merge to get latest hanges from epics-base
2019-08-02 05:44:42 -04:00
Andrew Johnson aba40922e6 Release notes for 4.6.0 2019-07-29 11:47:36 -05:00
Andrew Johnson 2c1cb03cd0 Use new CONFIG_PVACLIENT_VERSION file for SHRLIB_VERSION 2019-07-29 11:46:54 -05:00
mrkraimer f58c5159fc add streamJSON 2019-07-19 09:49:40 -04:00
mrkraimer a91ba8ef9e fixed a bug 2019-07-17 10:43:13 -04:00
mrkraimer ddb36536fe add zeroArrayLength 2019-07-16 10:33:39 -04:00
mrkraimer 9153036ccc added JSON support 2019-07-16 09:42:08 -04:00
Marty Kraimer 4c56116827 Merge pull request #60 from mrkraimer/master
working on issue #56; still problems with monitor
2019-04-26 12:51:02 -04:00
mrkraimer 81f5e25276 working on issue #56; still problems with monitor 2019-04-26 10:09:56 -04:00
Marty Kraimer 703b2224ce Merge pull request #59 from mrkraimer/master
fix issue #57
2019-04-25 05:07:20 -04:00
mrkraimer ed0b1cbf08 fix issue #57 2019-04-24 14:53:18 -04:00
Marty Kraimer 914e382dea Merge pull request #58 from mrkraimer/master
address issue #54
2019-04-24 05:18:19 -04:00
mrkraimer fd77d35b20 address issue #54 2019-04-23 14:04:13 -04:00
Andrew Johnson 428adb270e Update version numbers to 4.5.0 for EPICS 7.0.2.2 release 2019-04-15 11:27:27 -05:00
Marty Kraimer 3111e90de8 Merge pull request #55 from mrkraimer/master
address issue #53 plus more for getDouble, putDouble, getString, putDouble, etc
2019-04-11 14:50:03 -04:00
mrkraimer 365a0b846f update RELEASE_NOTES 2019-04-11 14:13:53 -04:00
mrkraimer 440c8fa496 update RELEASE_NOTES 2019-04-11 14:11:03 -04:00
mrkraimer 150ac45de3 bug in pvaClientData; fix doxygen warning; update doc 2019-04-09 11:15:00 -04:00
mrkraimer fb6f4355f3 getDoubleArray and putDoubleArray now work for all numeric scalar arrays 2019-04-09 06:19:14 -04:00
mrkraimer 0bb17d5b09 make them work if not top level value field 2019-04-08 14:23:58 -04:00
mrkraimer 00103f8207 getStringArray and putStringArray support all numeric array types 2019-04-08 14:11:27 -04:00
mrkraimer 522a050945 add double and string methods to pvaClientChannel 2019-04-07 14:34:56 -04:00
mrkraimer 99a7e3b0b5 more changes 2019-04-06 11:30:10 -04:00
mrkraimer 763c41caa3 setElementData=>setData 2019-04-05 14:37:05 -04:00
mrkraimer 9ffeffd23f mistake 2019-04-04 16:27:53 -04:00
mrkraimer 3f6d93b22f lots of minor changes 2019-04-04 16:02:47 -04:00
mrkraimer d650865a6f address issue #53; reorganize Client*Data 2019-04-03 10:32:45 -04:00
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
39 changed files with 2598 additions and 2105 deletions
+16 -12
View File
@@ -1,13 +1,17 @@
bin/
lib/
doc/
include/
db/
dbd/
documentation/html
documentation/*.tag
/cfg/
/bin/
/lib/
/db/
/dbd/
/html/
/include/
/templates/
/configure/*.local
/documentation/html
/documentation/*.tag
O.*/
/QtC-*
envPaths
configure/*.local
!configure/ExampleRELEASE.local
**/O.*
QtC-*
*.orig
*.log
.*.swp
+17
View File
@@ -0,0 +1,17 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the documentation/ directory with Sphinx
sphinx:
configuration: documentation/conf.py
# Build documentation with MkDocs
#mkdocs:
# configuration: mkdocs.yml
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
+7 -6
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = pvaClientCPP
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
PROJECT_NUMBER = 4.8.2-dev
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH =
STRIP_FROM_PATH = src
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
@@ -161,7 +161,7 @@ STRIP_FROM_PATH =
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
STRIP_FROM_INC_PATH = src
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
@@ -765,7 +765,8 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = include
INPUT = src \
src/pv
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -796,7 +797,7 @@ FILE_PATTERNS =
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
RECURSIVE = NO
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
@@ -1035,7 +1036,7 @@ GENERATE_HTML = YES
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = documentation/html
HTML_OUTPUT = html/doxygen
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
+11 -43
View File
@@ -1,49 +1,17 @@
pvaClientCPP
============
# pvaClientCPP
pvaClient is a synchronous client interface to pvAccess,
which is callback based.
pvaClient is thus easier to use than pvAccess itself.
The **pvaClient** API provides a synchronous client interface that was designed to be easier to use than the original basic pvAccess client API.
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
then just type:
- General information about EPICS can be found at the
[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:
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.
This module is included as a submodule of a full EPICS 7 release and will be compiled during builds of that software.
+12
View File
@@ -0,0 +1,12 @@
# Version number for the PVA Client API and shared library
EPICS_PVACLIENT_MAJOR_VERSION = 4
EPICS_PVACLIENT_MINOR_VERSION = 8
EPICS_PVACLIENT_MAINTENANCE_VERSION = 2
# Development flag, set to zero for release versions
EPICS_PVACLIENT_DEVELOPMENT_FLAG = 1
# Immediately after a release the MAINTENANCE_VERSION
# will be incremented and the DEVELOPMENT_FLAG set to 1
-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
+2
View File
@@ -2,6 +2,8 @@ TOP=..
include $(TOP)/configure/CONFIG
CFG += CONFIG_PVACLIENT_VERSION
TARGETS = $(CONFIG_TARGETS)
CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS)))
+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
# subsequently do a "gnumake rebuild" in the application's
# top level directory.
# IF YOU CHANGE ANY PATHS in this file or make API changes to
# any modules it refers to, you should do a "make rebuild" in
# this application's top level directory.
#
# The build process does not check dependencies against files
# that are outside this application, thus you should also do a
# "gnumake rebuild" in the top level directory after EPICS_BASE
# or any other external module pointed to below is rebuilt.
# The EPICS build process does not check dependencies against
# any files from outside the application, so it is safest to
# rebuild it completely if any modules it depends on change.
#
# Host- or target-specific settings can be given in files named
# RELEASE.$(EPICS_HOST_ARCH).Common
# RELEASE.Common.$(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
# EPICS_BASE=/home/install/epics/base
# EPICS4_DIR=/home/epicsv4
# PVCOMMON=${EPICS4_DIR}/pvCommonCPP
# PVDATA=${EPICS4_DIR}/pvDataCPP
# NORMATIVETYPES=${EPICSV4}/normativeTypesCPP
# PVACCESS=${EPICS4_DIR}/pvAccessCPP
#Either create a RELEASE.local one level above the TOP for this module
#OR copy ExampleRELEASE.local to RELEASE.local and edit it.
# This file is parsed by both GNUmake and an EPICS Perl script,
# so it may ONLY contain definititions of paths to other support
# modules, variable definitions that are used in module paths,
# and include statements that pull in other RELEASE files.
# Variables may be used before their values have been set.
# Build variables that are NOT used in paths should be set in
# the CONFIG_SITE file.
# 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.$(EPICS_HOST_ARCH).local
-include $(TOP)/configure/RELEASE.local
+115 -8
View File
@@ -1,19 +1,126 @@
EPICS V4 release 4.6
==========================
# pvaClientCPP Module
This document summarizes the changes to the module between releases.
## Release 4.8.1 (EPICS 7.0.10, Dec 2025)
* Fix error message generation code.
## Release 4.8.0 (EPICS 7.0.6 Jul 2021)
* PvaClientNTMultiData::getChannelChangeFlags is a new method. It fixes issue #66.
* Fix for issue #68. Both PvaClientArray and PvaClientField are not longer present. Neither was previously implemented.
* Several public methods are now protected. They were never meant to be called by clients.
* Issue #70 has been fixed.
* Changes was made to increase the performance of pvaMultiChannel.
* doxygen changes were made.
## Release 4.7.1 (EPICS 7.0.3.2 May 2020)
* support access to a union field that is a scalar or scalarArray
* fixed issues #62 and #63
## Release 4.7.0 (EPICS 7.0.3.1, Nov 2019)
* added JSON support for put and putGet
* Fix for
[GitHub issue #62](https://github.com/epics-base/pvaClientCPP/issues/62)
* Doxygen updates and read-the-docs integration.
## Release 4.6.0 (EPICS 7.0.3, Jul 2019)
* pvaClient now handles exceptions from the server properly (issue #54).
* MultiChannel classes now properly handle PV structures that don't have a top-level `value` field (issue #56), and are more tolerant of other missing fields (issue #57).
## Release 4.5.0 (EPICS 7.0.2.2, Apr 2019)
Changes have been made for getDouble, putDouble, getDoubleArray, putDoubleArray, getString, putString, getStringArray, and putStringArray.
1) Previously each only had support for a top level field named value.
Each now allows access to a single sub field that has the correct type.
Thus pvRequest must select a single field. For example
pva->channel("PVRdumbPowerSupply")->putDouble(1.0,"power.value" );
2) PvaChannel now has a method for each of the above.
For example instead of
PvaClientChannelPtr channel = pva->channel("PVRdouble");
PvaClientPutPtr clientPut = channel->put();
PvaClientPutDataPtr putData = clientPut->getData();
putData->putDouble(1.0); clientPut->put();
now it can be
pva->channel("PVRdouble")->putDouble(1.0 );
3) getDoubleArray and putDoubleArray work with any numeric scalar array
4) getStringArray and putStringArray work with any scalar array.
## 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.
* Support for channelRPC is now available.
* In PvaClientMultiChannel checkConnected() now throws an exception if connect fails.
EPICS V4 release 4.5
==========================
## Release 4.1 (EPICS V4.5, Oct 2015)
pvaClient is a synchronous API for pvAccess.
This is the first release of pvaClientCPP.
It provides an API that is similar to pvaClientJava.
+7
View File
@@ -0,0 +1,7 @@
.wy-side-nav-search {
background-color: #18334B;
}
.wy-side-nav-search input[type="text"] {
border-color: #18334b;
}
+80
View File
@@ -0,0 +1,80 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'normativeTypes (C++)'
copyright = '2019, EPICS Controls.'
author = 'EPICS'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.intersphinx',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# Intersphinx links to subprojects
intersphinx_mapping = {
}
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = [
'css/custom.css',
]
master_doc = 'index'
html_theme_options = {
'logo_only': True,
}
html_logo = "images/EPICS_white_logo_v02.png"
html_extra_path = [
'../html',
'pvaClientCPP.html',
]
# -- Run Doxygen ------------------------------------------------------------
import subprocess
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

+17
View File
@@ -0,0 +1,17 @@
pvaClient (C++) Library
========================
.. toctree::
:hidden:
EPICS Website <https://epics-controls.org>
EPICS Documentation Home <https://docs.epics-controls.org>
.. toctree::
:maxdepth: 1
:caption: pvaClientCPP
Reference Manual <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/pvaClientCPP.html>
API Documentation <https://docs.epics-controls.org/projects/pvaclient-cpp/en/latest/doxygen>
Source Code Repository on GitHub <https://github.com/epics-base/pvaClientCPP>
+27 -28
View File
@@ -4,11 +4,11 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<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"
href="http://epics-pvdata.sourceforge.net/base.css" />
href="https://mrkraimer.github.io/website/css/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
href="https://mrkraimer.github.io/website/css/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
@@ -18,7 +18,7 @@
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript" src="http://epics-pvdata.sourceforge.net/script/tocgen.js"></script>
<script type="text/javascript" src="https://mrkraimer.github.io/website/css/tocgen.js"></script>
</head>
@@ -26,13 +26,13 @@
<div class="head">
<h1>EPICS pvaClientCPP</h1>
<h2 class="nocount">Release 4.2.0-SNAPSHOT - 2016-07-14</h2>
<h2 class="nocount">Release 4.8 - March 2021</h2>
<h2 class="nocount">Abstract</h2>
<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
for such uses as rapid development of ad hoc programs by controls engineers, or to provide
<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
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>
<p>Specifically, pvaClient provides a synchronous interface for pvAccess, which is the
@@ -41,7 +41,7 @@ pvAccess provides a callback based interface, which can be hard to use.
pvaClient provides an interface that does not require callbacks even for monitors.
</p>
<p>
pvaClientChannel provides many "convenience" methods to directly get and put
pvaClientChannel provides many "convenience" methods to directly get and put
scalar and scalarArray data types.
Additional methods provide access to the full features of pvAccess.
</p>
@@ -62,40 +62,39 @@ The data for the channels is presented via normative type NTMultiChannel.
</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 />
<h2>Overview</h2>
<p>
pvaClientCPP is one of the components of
<a href="http://epics-pvdata.sourceforge.net">
EPICS Version 4
Documentation for pvaClientCPP is available at:
<a
href="https://mrkraimer.github.io/website/developerGuide/pvaClient/pvaClientCPP.html">
pvaClient
</a>
</p>
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP
<p>
pvaClientCPP is one of the components of
<a href="https://epics-controls.org/resources-and-support/base/epics-7/">
EPICS-7
</a>
</p>
<p>This document is only a guide to help locate code and documentation related to pvaClientCPP
</p>
<p>
It is intended for developers that want to use pvDatabaseCPP.
It is intended for developers that want to use pvaClientCPP.
</p>
<h2>Developer Guide</h2>
<p>A guide for developers is available at
<a
href="http://epics-pvdata.sourceforge.net/informative/developerGuide/developerGuide.html">
href="https://mrkraimer.github.io/website/developerGuide/developerGuide.html">
developerGuide
</a>
</p>
<p>This guide discusses all the components that are part of an <b>EPICS V4</b> release.
<p>This guide provides an overview of the components that are part of an <b>EPICS V4</b> release.
Some understanding of the components and how they are related is necessary in order to
develop code that uses pvDatabaseCPP.
develop code that uses pvaClientCPP.
In particular read everything related to pvaClient.
</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>
<p>doxygen documentation is available at
@@ -104,9 +103,9 @@ href="./html/index.html">doxygen</a>
</p>
<h2>exampleCPP</h2>
<p>Example code is available as part of this release.
<p>Example code is available at
<a
href="http://epics-pvdata.sourceforge.net/docbuild/exampleCPP/tip/documentation/exampleCPP.html">
href="https://github.com/epics-base/exampleCPP">
exampleCPP
</a>
</p>
+2 -12
View File
@@ -21,28 +21,19 @@ installE4 () {
local module=$1
local branch=$2
# If microbench version does not exist, try without
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
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${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
BASE=${BASE:-${DEFAULT_BASE}}
MB=${MB:-"NO_MICROBENCH"}
###########################################
# Dependent module branches
PVCOMMON_BRANCH="master"
PVDATA_BRANCH="master"
PVACCESS_BRANCH="master"
NORMATIVETYPES_BRANCH="master"
@@ -59,7 +50,6 @@ cd ${STUFF}
installTool Boost 1.61.0
installTool Base ${BASE}
installE4 pvCommon ${PVCOMMON_BRANCH}
installE4 pvData ${PVDATA_BRANCH}
installE4 pvAccess ${PVACCESS_BRANCH}
installE4 normativeTypes ${NORMATIVETYPES_BRANCH}
+1 -8
View File
@@ -21,14 +21,7 @@ installE4 () {
local module=$1
local branch=$2
# If microbench version does not exist, try without
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
wget -nv https://openepics.ci.cloudbees.com/job/e4-cpp-${module}-${branch}-build/BASE=${BASE}/lastSuccessfulBuild/artifact/${module}.CB-dist.tar.gz
tar -xzf ${module}.CB-dist.tar.gz
}
+5 -4
View File
@@ -6,12 +6,13 @@ include $(TOP)/configure/CONFIG
LIBRARY += pvaClient
# shared library ABI version.
SHRLIB_VERSION ?= 4.2.0
SHRLIB_VERSION ?= $(EPICS_PVACLIENT_MAJOR_VERSION).$(EPICS_PVACLIENT_MINOR_VERSION).$(EPICS_PVACLIENT_MAINTENANCE_VERSION)
INC += pv/pvaClient.h
INC += pv/pvaClientMultiChannel.h
LIBSRCS += pvaClient.cpp
LIBSRCS += pvaClientData.cpp
LIBSRCS += pvaClientPutData.cpp
LIBSRCS += pvaClientGetData.cpp
LIBSRCS += pvaClientMonitorData.cpp
@@ -31,8 +32,8 @@ LIBSRCS += pvaClientNTMultiGet.cpp
LIBSRCS += pvaClientNTMultiMonitor.cpp
LIBSRCS += pvaClientRPC.cpp
pvaClient_LIBS += pvAccess nt pvData Com
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
pvaClient_LIBS += nt
pvaClient_LIBS += $(EPICS_BASE_PVA_CORE_LIBS)
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES
+532 -395
View File
File diff suppressed because it is too large Load Diff
+84 -169
View File
@@ -21,14 +21,14 @@
#ifdef pvaClientMultiChannelEpicsExportSharedSymbols
# define epicsExportSharedSymbols
# undef pvaClientMultiChannelEpicsExportSharedSymbols
# undef pvaClientMultiChannelEpicsExportSharedSymbols
#endif
#include <pv/pvaClient.h>
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
class PvaClientMultiChannel;
@@ -66,14 +66,19 @@ public:
* @param pvaClient The interface to pvaClient.
* @param channelNames The names of the channel..
* @param providerName The name of the provider.
* This is also used for the provider for all channels
* with providerNames.size less than channelNames.size()
* @param maxNotConnected The maximum number of channels that can be disconnected.
* @param providerNames The providerName for each Channells
* @return The interface to the PvaClientMultiChannel
*/
static PvaClientMultiChannelPtr create(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelNames,
std::string const & providerName = "pva",
size_t maxNotConnected=0
size_t maxNotConnected=0,
epics::pvData::shared_vector<const std::string> const & providerNames
= epics::pvData::shared_vector<const std::string>()
);
/**
* @brief Destructor
@@ -115,7 +120,7 @@ public:
* @brief create a pvaClientMultiGetDouble
* @return The interface.
*/
PvaClientMultiGetDoublePtr createGet();
PvaClientMultiGetDoublePtr createGet();
/**
* @brief Create a pvaClientMultiPutDouble.
* @return The interface.
@@ -145,27 +150,27 @@ public:
*/
PvaClientNTMultiMonitorPtr createNTMonitor(
std::string const &request= "field(value,alarm,timeStamp)");
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientMultiChannel(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const std::string> const & channelName,
epics::pvData::shared_vector<const std::string> const & channelNames,
std::string const & providerName,
size_t maxNotConnected);
size_t maxNotConnected,
epics::pvData::shared_vector<const std::string> const & providerNames);
void checkConnected();
PvaClientPtr pvaClient;
epics::pvData::shared_vector<const std::string> channelName;
epics::pvData::shared_vector<const std::string> channelNames;
std::string providerName;
size_t maxNotConnected;
epics::pvData::shared_vector<const std::string> const & providerNames;
size_t numChannel;
size_t numProviderNames;
epics::pvData::Mutex mutex;
size_t numConnected;
bool firstConnect;
PvaClientChannelArray pvaClientChannelArray;
epics::pvData::shared_vector<epics::pvData::boolean> isConnected;
epics::pvData::CreateRequest::shared_pointer createRequest;
@@ -180,19 +185,16 @@ class epicsShareClass PvaClientMultiGetDouble :
public:
POINTER_DEFINITIONS(PvaClientMultiGetDouble);
/**
* @brief Create a PvaClientMultiGetDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientMultiGetDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiGetDouble();
/**
* @brief Create a channelGet for each channel.
*/
@@ -202,17 +204,6 @@ public:
* @return The double[] where each element is the value field of the corresponding channel.
*/
epics::pvData::shared_vector<double> get();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiGetDoublePtr getPtrSelf()
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientMultiGetDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -222,7 +213,7 @@ private:
PvaClientChannelArray pvaClientChannelArray;
size_t nchannel;
epics::pvData::Mutex mutex;
epics::pvData::shared_vector<double> doubleValue;
std::vector<PvaClientGetPtr> pvaClientGet;
bool isGetConnected;
@@ -237,15 +228,15 @@ class epicsShareClass PvaClientMultiPutDouble :
public:
POINTER_DEFINITIONS(PvaClientMultiPutDouble);
/** @brief Create a PvaClientMultiPutDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientMultiPutDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiPutDouble();
/**
* @brief Create a channelPut for each channel.
@@ -255,17 +246,7 @@ public:
* @param data The array of data for each channel.
*/
void put(epics::pvData::shared_vector<double> const &data);
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiPutDoublePtr getPtrSelf()
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientMultiPutDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -289,15 +270,15 @@ class epicsShareClass PvaClientMultiMonitorDouble :
public:
POINTER_DEFINITIONS(PvaClientMultiMonitorDouble);
/** @brief Create a PvaClientMultiMonitorDouble.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientMultiMonitorDoublePtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientMultiMonitorDouble();
/**
* @brief Connect a channel monitor for each channel.
@@ -322,17 +303,7 @@ public:
* @return The double[] where each element is the value field of the corresponding channel.
*/
epics::pvData::shared_vector<double> get();
/** @brief Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientMultiMonitorDoublePtr getPtrSelf()
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientMultiMonitorDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -357,18 +328,16 @@ class epicsShareClass PvaClientNTMultiGet :
public:
POINTER_DEFINITIONS(PvaClientNTMultiGet);
/**
* @brief Create a PvaClientNTMultiGet.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
* @return The interface.
*/
protected:
static PvaClientNTMultiGetPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiGet();
/**
* @brief Connect a channelGet for each channel.
@@ -376,24 +345,16 @@ public:
void connect();
/**
* @brief Get each channel.
*
* @param valueOnly use only value for union.
*/
void get();
void get(bool valueOnly = true);
/**
* @brief Get the data from the last get.
* @return the pvaClientNTMultiData.
*/
PvaClientNTMultiDataPtr getData();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiGetPtr getPtrSelf()
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientNTMultiGet(
epics::pvData::UnionConstPtr const & u,
@@ -406,8 +367,7 @@ private:
epics::pvData::PVStructurePtr pvRequest;
size_t nchannel;
epics::pvData::Mutex mutex;
PvaClientNTMultiDataPtr pvaClientNTMultiData;
std::vector<PvaClientGetPtr> pvaClientGet;
bool isConnected;
@@ -422,16 +382,15 @@ class epicsShareClass PvaClientNTMultiPut :
public:
POINTER_DEFINITIONS(PvaClientNTMultiPut);
/**
* @brief Create a PvaClientNTMultiPut.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @return The interface.
*/
protected:
static PvaClientNTMultiPutPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiPut();
/**
* @brief Connect a channelPut for each channel.
@@ -444,19 +403,9 @@ public:
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> getValues();
/**
* @brief Issue a put for each channel.
' */
*/
void put();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiPutPtr getPtrSelf()
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientNTMultiPut(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -482,16 +431,16 @@ class epicsShareClass PvaClientNTMultiMonitor :
public:
POINTER_DEFINITIONS(PvaClientNTMultiMonitor);
/** @brief Create a PvaClientNTMultiMonitor.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
* @return The interface.
*/
protected:
static PvaClientNTMultiMonitorPtr create(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
friend class PvaClientMultiChannel;
public:
/**
* @brief Destructor
*/
~PvaClientNTMultiMonitor();
/**
* @brief Connect to a channel monitor for each channel.
@@ -500,10 +449,11 @@ public:
/**
* @brief Poll each channel.
*
* @param valueOnly use only value for union.
* If any has new data it is used to update the double[].
* @return (false,true) if (no, at least one) value was updated.
*/
bool poll();
bool poll(bool valueOnly = true);
/**
* @brief Wait until poll returns true.
* @param secondsToWait The time to keep trying.
@@ -516,17 +466,7 @@ public:
* @return the pvaClientNTMultiData.
*/
PvaClientNTMultiDataPtr getData();
/** Monitor the shared pointer to self.
* @return The shared pointer.
*/
PvaClientNTMultiMonitorPtr getPtrSelf()
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientNTMultiMonitor(
epics::pvData::UnionConstPtr const & u,
@@ -553,65 +493,43 @@ class epicsShareClass PvaClientNTMultiData :
public:
POINTER_DEFINITIONS(PvaClientNTMultiData);
/**
* @brief Create a PvaClientNTMultiData.
*
* Normally only called by PvaClientNTMultiGet and PvaClientNTMultiMonitor.
* @param u The union interface for the value field of each channel.
* @param pvaClientMultiChannel The interface to PvaClientMultiChannel.
* @param pvaClientChannelArray The PvaClientChannel array.
* @param pvRequest The pvRequest for each channel.
*/
static PvaClientNTMultiDataPtr create(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
~PvaClientNTMultiData();
/**
/**
* @brief Get the number of channels.
* @return The number of channels.
*/
size_t getNumber();
/**
* @brief Set the timeStamp base for computing deltaTimes.
*/
void startDeltaTime();
/**
* @brief Update NTMultiChannel fields.
*/
void endDeltaTime();
/**
/**
* @brief Get the time when the last get was made.
* @return The timeStamp.
*/
epics::pvData::TimeStamp getTimeStamp();
epics::pvData::TimeStamp getTimeStamp();
/**
* @brief Get the NTMultiChannel.
* @return The value.
*/
epics::nt::NTMultiChannelPtr getNTMultiChannel();
/** @brief Get the shared pointer to self.
* @return The shared pointer.
/**
* @brief Get channel change flags.
* @return Array of boolean fields that are set to true if corresponding channel changed
*/
PvaClientNTMultiDataPtr getPtrSelf()
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
epics::pvData::shared_vector<epics::pvData::boolean> getChannelChangeFlags();
protected:
static PvaClientNTMultiDataPtr create(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
void startDeltaTime();
void endDeltaTime(bool valueOnly = true);
friend class PvaClientNTMultiGet;
friend class PvaClientNTMultiMonitor;
private:
PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaNTMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest);
void setStructure(epics::pvData::StructureConstPtr const & structure,size_t index);
void setPVStructure(
epics::pvData::PVStructurePtr const &pvStructure,size_t index);
@@ -624,6 +542,7 @@ private:
bool gotAlarm;
bool gotTimeStamp;
epics::pvData::shared_vector<epics::pvData::boolean> changeFlags;
epics::pvData::StructureConstPtr ntMultiChannelStructure;
epics::pvData::shared_vector<epics::pvData::PVUnionPtr> unionValue;
epics::pvData::shared_vector<epics::pvData::int32> severity;
@@ -635,13 +554,9 @@ private:
epics::pvData::Alarm alarm;
epics::pvData::TimeStamp timeStamp;;
epics::pvData::PVTimeStamp pvTimeStamp;
friend class PvaClientNTMultiGet;
friend class PvaClientNTMultiPut;
friend class PvaClientNTMultiMonitor;
};
}}
#endif /* PVACLIENTMULTICHANNEL_H */
+36 -16
View File
@@ -18,13 +18,12 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvAccess::ca;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
class epicsShareClass PvaClientChannelCache
@@ -43,7 +42,7 @@ public:
private:
map<string,PvaClientChannelPtr> pvaClientChannelMap;
};
PvaClientChannelPtr PvaClientChannelCache::getChannel(
string const & channelName,
string const & providerName)
@@ -78,7 +77,7 @@ void PvaClientChannelCache::showCache()
string providerName = channel->getProvider()->getProviderName();
cout << "channel " << channelName << " provider " << providerName << endl;
pvaChannel->showCache();
}
}
}
size_t PvaClientChannelCache::cacheSize()
@@ -87,7 +86,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)
{
@@ -100,47 +110,58 @@ PvaClientPtr PvaClient::get(std::string const & providerNames)
return master;
}
PvaClientPtr PvaClient::create() {return get();}
PvaClient::PvaClient(std::string const & providerNames)
: pvaClientChannelCache(new PvaClientChannelCache()),
pvaStarted(false),
caStarted(false)
caStarted(false),
channelRegistry(ChannelProviderRegistry::clients())
{
stringstream ss(providerNames);
string providerName;
if(getDebug()) {
cout<< "PvaClient::PvaClient()\n";
}
while (getline(ss, providerName, ' '))
{
ChannelProviderRegistry::shared_pointer registry(getChannelProviderRegistry());
if(providerName=="pva") {
if(getDebug()) {
cout<< "calling ClientFactory::start()\n";
}
ClientFactory::start();
pvaStarted = true;
} else if(providerName=="ca") {
if(getDebug()) {
cout<< "calling CAClientFactory::start()\n";
}
CAClientFactory::start();
caStarted = true;
} else {
if(!registry->getProvider(providerName)) {
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
if(!channelRegistry->getProvider(providerName)) {
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
}
}
}
}
PvaClient::~PvaClient() {
if(PvaClient::debug) {
if(getDebug()) {
cout<< "PvaClient::~PvaClient()\n"
<< "pvaChannel cache:\n";
showCache();
}
if(pvaStarted){
if(PvaClient::debug) cout<< "calling ClientFactory::stop()\n";
if(getDebug()) cout<< "calling ClientFactory::stop()\n";
ClientFactory::stop();
if(PvaClient::debug) cout<< "after calling ClientFactory::stop()\n";
if(getDebug()) cout<< "after calling ClientFactory::stop()\n";
}
if(caStarted) {
if(PvaClient::debug) cout<< "calling CAClientFactory::stop()\n";
if(getDebug()) cout<< "calling CAClientFactory::stop()\n";
CAClientFactory::stop();
if(PvaClient::debug) cout<< "after calling CAClientFactory::stop()\n";
if(getDebug()) cout<< "after calling CAClientFactory::stop()\n";
}
channelRegistry.reset();
}
string PvaClient:: getRequesterName()
@@ -170,7 +191,7 @@ PvaClientChannelPtr PvaClient::channel(
std::string const & providerName,
double timeOut)
{
PvaClientChannelPtr pvaClientChannel =
PvaClientChannelPtr pvaClientChannel =
pvaClientChannelCache->getChannel(channelName,providerName);
if(pvaClientChannel) return pvaClientChannel;
pvaClientChannel = createChannel(channelName,providerName);
@@ -210,4 +231,3 @@ size_t PvaClient::cacheSize()
}
}}
+108 -120
View File
@@ -18,7 +18,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -122,60 +121,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(
PvaClientPtr const &pvaClient,
string const & channelName,
string const & providerName)
{
PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName));
channel->channelRequester = ChannelRequesterImplPtr(
new ChannelRequesterImpl(channel,pvaClient));
return channel;
}
@@ -218,6 +169,7 @@ void PvaClientChannel::channelCreated(const Status& status, Channel::shared_poin
<< endl;
}
Lock xx(mutex);
this->channel = channel;
if(connectState==connected) return;
if(connectState!=connectActive) {
string message("PvaClientChannel::channelCreated");
@@ -227,13 +179,10 @@ void PvaClientChannel::channelCreated(const Status& status, Channel::shared_poin
}
if(!status.isOK()) {
string message("PvaClientChannel::channelCreated");
message += " channel " + channelName
+ " status " + status.getMessage() + " why??";
throw std::runtime_error(message);
}
if(channel->isConnected()) {
connectState = connected;
waitForConnect.signal();
}
}
void PvaClientChannel::channelStateChange(
@@ -246,25 +195,25 @@ void PvaClientChannel::channelStateChange(
<< " " << Channel::ConnectionStateNames[connectionState]
<< endl;
}
bool waitingForConnect = false;
if(connectState==connectActive) waitingForConnect = true;
if(connectionState!=Channel::CONNECTED) {
Lock xx(mutex);
connectState = notConnected;
} else {
Lock xx(mutex);
this->channel = channel;
connectState = connected;
}
if(waitingForConnect) {
Lock xx(mutex);
waitForConnect.signal();
}
PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock());
if(req) {
bool value = (connectionState==Channel::CONNECTED ? true : false);
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()
@@ -297,6 +246,9 @@ void PvaClientChannel::setStateChangeRequester(
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester)
{
this->stateChangeRequester = stateChangeRequester;
bool isConnected = false;
if(channel) isConnected = channel->isConnected();
stateChangeRequester->channelStateChange(shared_from_this(),isConnected);
}
void PvaClientChannel::connect(double timeout)
@@ -309,7 +261,7 @@ void PvaClientChannel::connect(double timeout)
Status status = waitConnect(timeout);
if(status.isOK()) return;
if(PvaClient::getDebug()) cout << "PvaClientChannel::connect waitConnect failed\n";
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::connect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -328,13 +280,13 @@ void PvaClientChannel::issueConnect()
}
connectState = connectActive;
}
ChannelProviderRegistry::shared_pointer reg = getChannelProviderRegistry();
ChannelProvider::shared_pointer provider = reg->getProvider(providerName);
if(!provider) {
ChannelProviderRegistry::shared_pointer reg(ChannelProviderRegistry::clients());
channelProvider = reg->getProvider(providerName);
if(!channelProvider) {
throw std::runtime_error(channelName + " provider " + providerName + " not registered");
}
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) {
throw std::runtime_error(channelName + " channelCreate failed ");
}
@@ -348,6 +300,7 @@ Status PvaClientChannel::waitConnect(double timeout)
}
{
Lock xx(mutex);
if(!channel) return Status(Status::STATUSTYPE_ERROR,"");
if(channel->isConnected()) return Status::Ok;
}
if(timeout>0.0) {
@@ -355,22 +308,16 @@ Status PvaClientChannel::waitConnect(double timeout)
} else {
waitForConnect.wait();
}
if(!channel) return Status(Status::STATUSTYPE_ERROR,"pvaClientChannel::waitConnect channel is null");
if(channel->isConnected()) return Status::Ok;
return Status(Status::STATUSTYPE_ERROR,channelName + " not connected");
}
PvaClientFieldPtr PvaClientChannel::createField(string const & subField)
{
if(connectState!=connected) connect(5.0);
throw std::runtime_error("PvaClientChannel::createField not implemented");
return Status(Status::STATUSTYPE_ERROR," not connected");
}
PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createProcess invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -383,17 +330,19 @@ PvaClientProcessPtr PvaClientChannel::createProcess(PVStructurePtr const & pvRe
if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock();
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 pvaClientGet = pvaClientGetCache->getGet(request);
if(pvaClientGet) return pvaClientGet;
pvaClientGet = createGet(request);
pvaClientGet->connect();
pvaClientGetCache->addGet(request,pvaClientGet);
if(!pvaClientGet) {
pvaClientGet = createGet(request);
pvaClientGet->connect();
pvaClientGetCache->addGet(request,pvaClientGet);
}
pvaClientGet->get();
return pvaClientGet;
}
@@ -402,7 +351,7 @@ PvaClientGetPtr PvaClientChannel::createGet(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createGet invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -415,7 +364,27 @@ PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & pvRequest)
if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientGet::create(yyy,channel,pvRequest);
return PvaClientGet::create(yyy,shared_from_this(),pvRequest);
}
double PvaClientChannel::getDouble(string const & request)
{
return get(request)->getData()->getDouble();
}
string PvaClientChannel::getString(string const & request)
{
return get(request)->getData()->getString();
}
shared_vector<const double> PvaClientChannel::getDoubleArray(string const & request)
{
return get(request)->getData()->getDoubleArray();
}
shared_vector<const std::string> PvaClientChannel::getStringArray(string const & request)
{
return get(request)->getData()->getStringArray();
}
@@ -423,10 +392,12 @@ PvaClientPutPtr PvaClientChannel::put(string const & request)
{
PvaClientPutPtr pvaClientPut = pvaClientPutCache->getPut(request);
if(pvaClientPut) return pvaClientPut;
pvaClientPut = createPut(request);
pvaClientPut->connect();
pvaClientPut->get();
pvaClientPutCache->addPut(request,pvaClientPut);
if(!pvaClientPut) {
pvaClientPut = createPut(request);
pvaClientPut->connect();
pvaClientPut->get();
pvaClientPutCache->addPut(request,pvaClientPut);
}
return pvaClientPut;
}
@@ -435,7 +406,7 @@ PvaClientPutPtr PvaClientChannel::createPut(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createPut invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -448,14 +419,52 @@ PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest)
if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientPut::create(yyy,channel,pvRequest);
return PvaClientPut::create(yyy,shared_from_this(),pvRequest);
}
void PvaClientChannel::putDouble(double value,string const & request)
{
PvaClientPutPtr clientPut = put(request);
PvaClientPutDataPtr putData = clientPut->getData();
putData->putDouble(value); clientPut->put();
}
void PvaClientChannel::putString(std::string const & value,string const & request)
{
PvaClientPutPtr clientPut = put(request);
PvaClientPutDataPtr putData = clientPut->getData();
putData->putString(value); clientPut->put();
}
void PvaClientChannel::putDoubleArray(
shared_vector<const double> const & value,
string const & request)
{
PvaClientPutPtr clientPut = put(request);
PvaClientPutDataPtr putData = clientPut->getData();
size_t n = value.size();
shared_vector<double> valueArray(n);
for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
putData->putDoubleArray(freeze(valueArray)); clientPut->put();
}
void PvaClientChannel::putStringArray(
shared_vector<const string> const & value,
string const & request)
{
PvaClientPutPtr clientPut = put(request);
PvaClientPutDataPtr putData = clientPut->getData();
size_t n = value.size();
shared_vector<string> valueArray(n);
for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
putData->putStringArray(freeze(valueArray)); clientPut->put();
}
PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createPutGet invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -468,30 +477,9 @@ PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvReque
if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("PvaClient was destroyed");
return PvaClientPutGet::create(yyy,channel,pvRequest);
return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest);
}
PvaClientArrayPtr PvaClientChannel::createArray(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
+ " PvaClientChannel::createArray invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
}
return createArray(pvRequest);
}
PvaClientArrayPtr PvaClientChannel::createArray(PVStructurePtr const & pvRequest)
{
if(connectState!=connected) connect(5.0);
throw std::runtime_error("PvaClientChannel::createArray not implemented");
}
PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
{
PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
@@ -519,7 +507,7 @@ PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request)
{
PVStructurePtr pvRequest = createRequest->createRequest(request);
if(!pvRequest) {
string message = string("channel ") + channelName
string message = string("channel ") + channelName
+ " PvaClientChannel::createMonitor invalid pvRequest: "
+ createRequest->getMessage();
throw std::runtime_error(message);
@@ -532,14 +520,14 @@ PvaClientMonitorPtr PvaClientChannel::createMonitor(PVStructurePtr const & pvR
if(connectState!=connected) connect(5.0);
PvaClientPtr yyy = pvaClient.lock();
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 const & pvRequest,
PVStructurePtr const & pvArgument)
{
PvaClientRPCPtr rpc = createRPC(pvRequest);
return rpc->request(pvArgument);
}
+440
View File
@@ -0,0 +1,440 @@
/* pvaClientData.cpp */
/**
* Copyright - See the COPYRIGHT that is included with this distribution.
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2019.04
*/
#include <typeinfo>
#include <sstream>
#include <istream>
#include <ostream>
#include <pv/createRequest.h>
#include <pv/convert.h>
#include <pv/pvEnumerated.h>
#if EPICS_VERSION_INT>=VERSION_INT(3,15,0,1)
# include <pv/json.h>
# define USE_JSON
#endif
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace pvaClient {
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
static ConvertPtr convert = getConvert();
static string noStructure("no pvStructure ");
static string noValue("no value field");
static string noScalar("value is not a scalar");
static string noArray("value is not an array");
static string noScalarArray("value is not a scalarArray");
static string noAlarm("no alarm");
static string noTimeStamp("no timeStamp");
PvaClientDataPtr PvaClientData::create(StructureConstPtr const & structure)
{
if(PvaClient::getDebug()) cout << "PvaClientData::create\n";
PvaClientDataPtr epv(new PvaClientData(structure));
return epv;
}
PvaClientData::PvaClientData(StructureConstPtr const & structure)
: structure(structure)
{
}
PVFieldPtr PvaClientData::getSinglePVField()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getSinglePVField\n";
PVStructurePtr pvStructure = getPVStructure();
while(true) {
const PVFieldPtrArray fieldPtrArray(pvStructure->getPVFields());
if(fieldPtrArray.size()==0) {
throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for empty structure");
}
if(fieldPtrArray.size()!=1) {
PVFieldPtr pvValue = pvStructure->getSubField("value");
if(pvValue) {
Type type = pvValue->getField()->getType();
if(type!=epics::pvData::structure) return pvValue;
}
throw std::logic_error("PvaClientData::getSinglePVField() pvRequest for multiple fields");
}
PVFieldPtr pvField(fieldPtrArray[0]);
Type type = pvField->getField()->getType();
if(type!=epics::pvData::structure) return pvField;
pvStructure = static_pointer_cast<PVStructure>(pvField);
}
}
void PvaClientData::checkValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::checkValue\n";
if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue);
}
void PvaClientData::setMessagePrefix(std::string const & value)
{
messagePrefix = value + " ";
}
StructureConstPtr PvaClientData::getStructure()
{
return structure;
}
PVStructurePtr PvaClientData::getPVStructure()
{
if(pvStructure) return pvStructure;
throw std::runtime_error(messagePrefix + noStructure);
}
BitSetPtr PvaClientData::getChangedBitSet()
{
if(bitSet)return bitSet;
throw std::runtime_error(messagePrefix + noStructure);
}
std::ostream & PvaClientData::showChanged(std::ostream & out)
{
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t nextSet = bitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = bitSet->nextSetBit(nextSet+1);
}
return out;
}
void PvaClientData::setData(
PVStructurePtr const & pvStructureFrom,
BitSetPtr const & bitSetFrom)
{
if(PvaClient::getDebug()) cout << "PvaClientData::setData\n";
pvStructure = pvStructureFrom;
bitSet = bitSetFrom;
pvValue = pvStructure->getSubField("value");
}
bool PvaClientData::hasValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::hasValue\n";
if(!pvValue) return false;
return true;
}
bool PvaClientData::isValueScalar()
{
if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalar\n";
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool PvaClientData::isValueScalarArray()
{
if(PvaClient::getDebug()) cout << "PvaClientData::isValueScalarArray\n";
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
PVFieldPtr PvaClientData::getValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getValue\n";
checkValue();
return pvValue;
}
PVScalarPtr PvaClientData::getScalarValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getScalarValue\n";
checkValue();
if(pvValue->getField()->getType()!=scalar) {
throw std::runtime_error(messagePrefix + noScalar);
}
return pvStructure->getSubField<PVScalar>("value");
}
PVArrayPtr PvaClientData::getArrayValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getArrayValue\n";
checkValue();
Type type = pvValue->getField()->getType();
if(type!=scalarArray && type!=structureArray && type!=unionArray) {
throw std::runtime_error(messagePrefix + noArray);
}
return pvStructure->getSubField<PVArray>("value");
}
PVScalarArrayPtr PvaClientData::getScalarArrayValue()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getScalarArrayValue\n";
checkValue();
Type type = pvValue->getField()->getType();
if(type!=scalarArray) {
throw std::runtime_error(messagePrefix + noScalarArray);
}
return pvStructure->getSubField<PVScalarArray>("value");
}
double PvaClientData::getDouble()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getDouble\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::getDouble() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::logic_error(
"PvaClientData::getDouble() did not find a numeric scalar field");
}
return convert->toDouble(pvScalar);
}
string PvaClientData::getString()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getString\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::getString() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
return convert->toString(pvScalar);
}
shared_vector<const double> PvaClientData::getDoubleArray()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getDoubleArray\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::getDoubleArray() did not find a scalarArray field");
}
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::logic_error(
"PvaClientData::getDoubleArray() did not find a numeric scalarArray field");
}
shared_vector<const double> retValue;
pvScalarArray->getAs<const double>(retValue);
return retValue;
}
shared_vector<const string> PvaClientData::getStringArray()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getStringArray\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::getStringArray() did not find a scalarArray field");
}
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
shared_vector<const string> retValue;
pvScalarArray->getAs<const string>(retValue);
return retValue;
}
Alarm PvaClientData::getAlarm()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getAlarm\n";
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm");
if(!pvs) throw std::runtime_error(messagePrefix + noAlarm);
pvAlarm.attach(pvs);
if(pvAlarm.isAttached()) {
Alarm alarm;
pvAlarm.get(alarm);
pvAlarm.detach();
return alarm;
}
throw std::runtime_error(messagePrefix + noAlarm);
}
TimeStamp PvaClientData::getTimeStamp()
{
if(PvaClient::getDebug()) cout << "PvaClientData::getTimeStamp\n";
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp");
if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp);
pvTimeStamp.attach(pvs);
if(pvTimeStamp.isAttached()) {
TimeStamp timeStamp;
pvTimeStamp.get(timeStamp);
pvTimeStamp.detach();
return timeStamp;
}
throw std::runtime_error(messagePrefix + noTimeStamp);
}
void PvaClientData::zeroArrayLength()
{
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
zeroArrayLength(pvStructure);
}
void PvaClientData::parse(
const std::string &arg,const PVFieldPtr &dest,BitSetPtr & bitSet)
{
#ifdef USE_JSON
std::istringstream strm(arg);
parseJSON(strm, dest,&(*bitSet));
#else
throw std::runtime_error("JSON support not built");
#endif
}
void PvaClientData::parse(
const std::string &arg,const PVUnionPtr &pvUnion)
{
if(pvUnion->getUnion()->isVariant()) {
throw std::runtime_error(messagePrefix + "varient union not implemented");
}
size_t iequals = arg.find_first_of('=');
string field;
string rest;
if(iequals==std::string::npos) {
string mess(arg);
mess += " was expected to start with field=";
throw std::runtime_error(messagePrefix + mess);
}
field = arg.substr(0,iequals);
rest = arg.substr(iequals+1);
PVFieldPtr pvField(pvUnion->select(field));
if(pvField->getField()->getType()==epics::pvData::union_) {
PVUnionPtr pvu = static_pointer_cast<PVUnion>(pvField);
parse(rest,pvu);
return;
}
BitSetPtr bs;
parse(rest,pvField,bs);
return;
}
void PvaClientData::parse(const std::vector<std::string> &args)
{
if(!pvStructure) throw std::runtime_error(messagePrefix + noStructure);
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t num = args.size();
if(num<1) throw std::runtime_error(messagePrefix + " no arguments");
for(size_t i=0; i<num; ++i)
{
string val = args[i];
size_t iequals = val.find_first_of('=');
string field;
string rest(val);
if(iequals==std::string::npos) {
parse(rest,pvStructure,bitSet);
continue;
}
field = val.substr(0,iequals);
rest = val.substr(iequals+1);
if(field.size()==std::string::npos) {
parse(rest,pvStructure,bitSet);
continue;
}
PVFieldPtr pvField(pvStructure->getSubField(field));
if(!pvField) throw std::runtime_error(messagePrefix + field +" does not exist");
// look for enumerated structure
PVEnumerated pvEnumerated;
bool result = pvEnumerated.attach(pvField);
if(result) {
PVStringArray::const_svector choices(pvEnumerated.getChoices());
for(size_t i=0; i<choices.size(); ++i) {
if(choices[i]==rest) {
pvEnumerated.setIndex(i);
return;
}
}
}
// look for union
PVUnionPtr pvUnion(pvStructure->getSubField<PVUnion>(field));
if(pvUnion) {
parse(rest,pvUnion);
bitSet->set(pvUnion->getFieldOffset());
return;
}
parse(rest,pvField,bitSet);
}
}
void PvaClientData::streamJSON(
std::ostream& strm,
bool ignoreUnprintable,
bool multiLine)
{
#ifdef USE_JSON
JSONPrintOptions opts;
opts.ignoreUnprintable = ignoreUnprintable;
opts.multiLine = multiLine;
printJSON(strm,*pvStructure,*bitSet,opts);
#else
throw std::runtime_error("JSON support not built");
#endif
}
void PvaClientData::zeroArrayLength(const PVStructurePtr &pvStructure)
{
const PVFieldPtrArray pvFields(pvStructure->getPVFields());
for(size_t i=0; i<pvFields.size(); ++i) {
PVFieldPtr pvField = pvFields[i];
Type type(pvField->getField()->getType());
switch(type) {
case scalarArray:
{
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
pvScalarArray->setLength(0);
}
break;
case structureArray:
{
PVStructureArrayPtr pvStructureArray = static_pointer_cast<PVStructureArray>(pvField);
pvStructureArray->setLength(0);
}
break;
case epics::pvData::structure:
{
PVStructurePtr pvStructure = static_pointer_cast<PVStructure>(pvField);
zeroArrayLength(pvStructure);
}
break;
default:
break;
}
}
}
}}
+112 -103
View File
@@ -15,7 +15,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -43,7 +42,7 @@ public:
return clientGet->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return;
clientGet->message(message,messageType);
@@ -56,7 +55,7 @@ public:
{
PvaClientGetPtr clientGet(pvaClientGet.lock());
if(!clientGet) return;
clientGet->channelGetConnect(status,channelGet,structure);
clientGet->channelGetConnect(status,channelGet,structure);
}
virtual void getDone(
@@ -73,65 +72,76 @@ public:
PvaClientGetPtr PvaClientGet::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
{
PvaClientGetPtr epv(new PvaClientGet(pvaClient,channel,pvRequest));
epv->channelGetRequester = ChannelGetRequesterImplPtr(
new ChannelGetRequesterImpl(epv,pvaClient));
return epv;
if(PvaClient::getDebug()) {
cout<< "PvaClientGet::create(pvaClient,channelName,pvRequest)\n"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " pvRequest " << pvRequest
<< endl;
}
PvaClientGetPtr clientGet(new PvaClientGet(pvaClient,pvaClientChannel,pvRequest));
clientGet->channelGetRequester = ChannelGetRequesterImplPtr(
new ChannelGetRequesterImpl(clientGet,pvaClient));
return clientGet;
}
PvaClientGet::PvaClientGet(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
: pvaClient(pvaClient),
channel(channel),
pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest),
connectState(connectIdle),
getState(getIdle)
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::PvaClientGet::PvaClientGet"
<< " channelName " << channel->getChannelName()
<< endl;
cout << "PvaClientGet::PvaClientGet channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
}
PvaClientGet::~PvaClientGet()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientGet::~PvaClientGet"
<< " channelName " << channelName
<< endl;
cout<< "PvaClientGet::~PvaClientGet channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
if(channelGet) channelGet->destroy();
}
void PvaClientGet::checkGetState()
void PvaClientGet::checkConnectState()
{
if(connectState==connectIdle) connect();
if(getState==getIdle) get();
if(PvaClient::getDebug()) {
cout << "PvaClientGet::checkConnectState channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
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
string PvaClientGet::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientGet::getRequesterName PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientGet::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientGet::channelGetConnect(
@@ -140,26 +150,26 @@ void PvaClientGet::channelGetConnect(
StructureConstPtr const & structure)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientGet::channelGetConnect"
<< " channelName " << channelName
cout << "PvaClientGet::channelGetConnect channelName "
<< pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
<< "\n";
}
{
Lock xx(mutex);
channelGetConnectStatus = status;
connectState = connected;
this->channelGet = channelGet;
if(status.isOK()) {
this->channelGet = channelGet;
connectState = connected;
pvaClientData = PvaClientGetData::create(structure);
pvaClientData->setMessagePrefix(channelGet->getChannel()->getChannelName());
}
}
waitForConnect.signal();
}
waitForConnect.signal();
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) {
req->channelGetConnect(status,shared_from_this());
}
}
void PvaClientGet::getDone(
@@ -169,13 +179,10 @@ void PvaClientGet::getDone(
BitSetPtr const & bitSet)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientGet::getDone"
<< " channelName " << channelName
cout << "PvaClientGet::getDone channelName "
<< pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
<< "\n";
}
{
Lock xx(mutex);
@@ -183,84 +190,78 @@ void PvaClientGet::getDone(
if(status.isOK()) {
pvaClientData->setData(pvStructure,bitSet);
}
getState = getComplete;
waitForGet.signal();
}
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) {
req->getDone(status,shared_from_this());
}
waitForGet.signal();
}
void PvaClientGet::connect()
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::connect channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientGet::connect " + status.getMessage();
throw std::runtime_error(message);
}
void PvaClientGet::issueConnect()
{
Channel::shared_pointer chan(channel.lock());
if(PvaClient::getDebug()) {
cout << "PvaClientGet::issueConnect channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
if(connectState!=connectIdle) {
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientGet already connected ";
throw std::runtime_error(message);
}
if(chan) {
connectState = connectActive;
channelGet = chan->createChannelGet(channelGetRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientGet::issueConnect channel was destroyed");
connectState = connectActive;
channelGetConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelGet = pvaClientChannel->getChannel()->createChannelGet(channelGetRequester,pvRequest);
}
Status PvaClientGet::waitConnect()
{
{
Lock xx(mutex);
if(connectState==connected) {
if(!channelGetConnectStatus.isOK()) connectState = connectIdle;
return channelGetConnectStatus;
}
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
if(PvaClient::getDebug()) {
cout << "PvaClientGet::waitConnect channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
waitForConnect.wait();
if(!channelGetConnectStatus.isOK()) connectState = connectIdle;
return channelGetConnectStatus;
}
void PvaClientGet::get()
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::get channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
issueGet();
Status status = waitGet();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientGet::get " + status.getMessage();
throw std::runtime_error(message);
}
void PvaClientGet::issueGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::issueGet channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
if(connectState==connectIdle) connect();
if(getState!=getIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
if(getState==getActive) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientGet::issueGet get aleady active ";
throw std::runtime_error(message);
}
@@ -270,30 +271,38 @@ void PvaClientGet::issueGet()
Status PvaClientGet::waitGet()
{
{
Lock xx(mutex);
if(getState==getComplete) {
getState =getIdle;
return channelGetStatus;
}
if(getState!=getActive){
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientGet::waitGet llegal get state";
throw std::runtime_error(message);
}
if(PvaClient::getDebug()) {
cout << "PvaClientGet::waitGet channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
waitForGet.wait();
getState = getIdle;
return channelGetStatus;
}
PvaClientGetDataPtr PvaClientGet::getData()
{
checkGetState();
if(PvaClient::getDebug()) {
cout<< "PvaClientGet::getData channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
checkConnectState();
if(getState==getIdle) get();
return pvaClientData;
}
void PvaClientGet::setRequester(PvaClientGetRequesterPtr const & pvaClientGetRequester)
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::setRequester channelName "
<< pvaClientChannel->getChannel()->getChannelName() << "\n";
}
this->pvaClientGetRequester = pvaClientGetRequester;
}
PvaClientChannelPtr PvaClientGet::getPvaClientChannel()
{
return pvaClientChannel;
}
}}
+3 -188
View File
@@ -19,7 +19,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -27,199 +26,15 @@ using namespace std;
namespace epics { namespace pvaClient {
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
static ConvertPtr convert = getConvert();
static string noStructure("no pvStructure ");
static string noValue("no value field");
static string noScalar("value is not a scalar");
static string notCompatibleScalar("value is not a compatible scalar");
static string noArray("value is not an array");
static string noScalarArray("value is not a scalarArray");
static string notDoubleArray("value is not a doubleArray");
static string notStringArray("value is not a stringArray");
static string noAlarm("no alarm");
static string noTimeStamp("no timeStamp");
PvaClientGetDataPtr PvaClientGetData::create(StructureConstPtr const & structure)
{
if(PvaClient::getDebug()) cout << "PvaClientGetData::create\n";
PvaClientGetDataPtr epv(new PvaClientGetData(structure));
return epv;
}
PvaClientGetData::PvaClientGetData(StructureConstPtr const & structure)
: structure(structure)
{
messagePrefix = "";
}
void PvaClientGetData::checkValue()
{
if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue);
}
void PvaClientGetData::setMessagePrefix(std::string const & value)
{
messagePrefix = value + " ";
}
StructureConstPtr PvaClientGetData::getStructure()
{return structure;}
PVStructurePtr PvaClientGetData::getPVStructure()
{
if(pvStructure) return pvStructure;
throw std::runtime_error(messagePrefix + noStructure);
}
BitSetPtr PvaClientGetData::getChangedBitSet()
{
if(bitSet)return bitSet;
throw std::runtime_error(messagePrefix + noStructure);
}
std::ostream & PvaClientGetData::showChanged(std::ostream & out)
{
if(!bitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t nextSet = bitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = bitSet->nextSetBit(nextSet+1);
}
return out;
}
void PvaClientGetData::setData(
PVStructurePtr const & pvStructureFrom,
BitSetPtr const & bitSetFrom)
{
pvStructure = pvStructureFrom;
bitSet = bitSetFrom;
pvValue = pvStructure->getSubField("value");
}
bool PvaClientGetData::hasValue()
{
if(!pvValue) return false;
return true;
}
bool PvaClientGetData::isValueScalar()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool PvaClientGetData::isValueScalarArray()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
PVFieldPtr PvaClientGetData::getValue()
{
checkValue();
return pvValue;
}
PVScalarPtr PvaClientGetData::getScalarValue()
{
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) throw std::runtime_error(messagePrefix + noScalar);
return pv;
}
PVArrayPtr PvaClientGetData::getArrayValue()
{
checkValue();
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
if(!pv) throw std::runtime_error(messagePrefix + noArray);
return pv;
}
PVScalarArrayPtr PvaClientGetData::getScalarArrayValue()
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) throw std::runtime_error(messagePrefix + noScalarArray);
return pv;
}
double PvaClientGetData::getDouble()
{
PVScalarPtr pvScalar = getScalarValue();
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(messagePrefix + notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
string PvaClientGetData::getString()
{
PVScalarPtr pvScalar = getScalarValue();
return convert->toString(pvScalar);
}
shared_vector<const double> PvaClientGetData::getDoubleArray()
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) throw std::runtime_error(messagePrefix + notDoubleArray);
return pv->view();
}
shared_vector<const string> PvaClientGetData::getStringArray()
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) throw std::runtime_error(messagePrefix + notStringArray);
return pv->view();
}
Alarm PvaClientGetData::getAlarm()
{
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm");
if(!pvs) throw std::runtime_error(messagePrefix + noAlarm);
pvAlarm.attach(pvs);
if(pvAlarm.isAttached()) {
Alarm alarm;
pvAlarm.get(alarm);
pvAlarm.detach();
return alarm;
}
throw std::runtime_error(messagePrefix + noAlarm);
}
TimeStamp PvaClientGetData::getTimeStamp()
{
if(!pvStructure) throw new std::runtime_error(messagePrefix + noStructure);
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp");
if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp);
pvTimeStamp.attach(pvs);
if(pvTimeStamp.isAttached()) {
TimeStamp timeStamp;
pvTimeStamp.get(timeStamp);
pvTimeStamp.detach();
return timeStamp;
}
throw std::runtime_error(messagePrefix + noTimeStamp);
}
: PvaClientData(structure)
{}
}}
+195 -169
View File
@@ -17,8 +17,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -46,7 +44,7 @@ public:
return clientMonitor->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->message(message,messageType);
@@ -59,42 +57,72 @@ public:
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->monitorConnect(status,monitor,structure);
clientMonitor->monitorConnect(status,monitor,structure);
}
virtual void unlisten(epics::pvData::MonitorPtr const & monitor)
virtual void unlisten(MonitorPtr const & monitor)
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->unlisten(monitor);
clientMonitor->unlisten(monitor);
}
virtual void monitorEvent(epics::pvData::MonitorPtr const & monitor)
virtual void monitorEvent(MonitorPtr const & monitor)
{
PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
if(!clientMonitor) return;
clientMonitor->monitorEvent(monitor);
clientMonitor->monitorEvent(monitor);
}
};
PvaClientMonitorPtr PvaClientMonitor::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
{
PvaClientMonitorPtr epv(new PvaClientMonitor(pvaClient,channel,pvRequest));
epv->monitorRequester = MonitorRequesterImplPtr(
new MonitorRequesterImpl(epv,pvaClient));
return epv;
PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
clientMonitor->monitorRequester = MonitorRequesterImplPtr(
new MonitorRequesterImpl(clientMonitor,pvaClient));
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(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
: pvaClient(pvaClient),
channel(channel),
pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest),
isStarted(false),
connectState(connectIdle),
@@ -102,56 +130,83 @@ PvaClientMonitor::PvaClientMonitor(
userWait(false)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::PvaClientMonitor()"
<< " channelName " << channel->getChannelName()
cout<< "PvaClientMonitor::PvaClientMonitor\n"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
PvaClientMonitor::~PvaClientMonitor()
{
if(PvaClient::getDebug()) cout<< "PvaClientMonitor::~PvaClientMonitor\n";
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientMonitor::~PvaClientMonitor"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(monitor) {
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()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::checkMonitorState"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " connectState " << connectState
<< endl;
}
if(connectState==connectIdle) connect();
if(connectState==connected && !isStarted) start();
if(connectState==connectIdle) {
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()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientMonitor::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientMonitor::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientMonitor::monitorConnect(
@@ -159,52 +214,73 @@ void PvaClientMonitor::monitorConnect(
Monitor::shared_pointer const & monitor,
StructureConstPtr const & structure)
{
Channel::shared_pointer chan(channel.lock());
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorConnect"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
connectStatus = status;
{
Lock xx(mutex);
monitorConnectStatus = status;
if(status.isOK()) {
this->monitor = monitor;
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientMonitor::monitorConnect)")
+ "\nchannelName=" + pvaClientChannel->getChannel()->getChannelName()
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
waitForConnect.signal();
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->monitorConnect(status,shared_from_this(),structure);
return;
}
}
bool signal = (connectState==connectWait) ? true : false;
connectState = connected;
this->monitor = monitor;
if(isStarted) {
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorConnect"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " is already started "
<< endl;
}
waitForConnect.signal();
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->monitorConnect(status,shared_from_this(),structure);
return;
}
if(status.isOK() && chan) {
pvaClientData = PvaClientMonitorData::create(structure);
pvaClientData->setMessagePrefix(chan->getChannelName());
pvaClientData = PvaClientMonitorData::create(structure);
pvaClientData->setMessagePrefix(pvaClientChannel->getChannel()->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()) {
cout << "PvaClientMonitor::monitorConnect calling waitForConnect.signal\n";
}
waitForConnect.signal();
PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
if(req) req->monitorConnect(status,shared_from_this(),structure);
}
void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::monitorEvent"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
if(req) req->event(shared_from_this());
if(userWait) waitForEvent.signal();
@@ -216,12 +292,7 @@ void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
if(req) {
req->unlisten();
return;
}
string channelName("disconnected");
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();
Status status = waitConnect();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::connect "
+ status.getMessage();
throw std::runtime_error(message);
@@ -244,59 +312,37 @@ void PvaClientMonitor::connect()
void PvaClientMonitor::issueConnect()
{
if(PvaClient::getDebug()) cout << "PvaClientMonitor::issueConnect\n";
Channel::shared_pointer chan(channel.lock());
if(connectState!=connectIdle) {
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientMonitor already connected ";
throw std::runtime_error(message);
}
if(chan) {
connectState = connectActive;
monitor = chan->createMonitor(monitorRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientMonitor::issueConnect() but channel disconnected");
connectState = connectWait;
monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
}
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()) {
cout << "PvaClientMonitor::waitConnect calling waitForConnect.wait\n";
cout << "PvaClientMonitor::waitConnect "
<< pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForConnect.wait();
connectState = connectStatus.isOK() ? connected : connectIdle;
if(PvaClient::getDebug()) {
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)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::setRequester"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
this->pvaClientMonitorRequester = pvaClientMonitorRequester;
@@ -305,30 +351,17 @@ void PvaClientMonitor::setRequester(PvaClientMonitorRequesterPtr const & pvaClie
void PvaClientMonitor::start()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::start"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " connectState " << connectState
<< endl;
}
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;
}
if(connectState==connectIdle) connect();
if(connectState!=connected) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::start illegal state ";
throw std::runtime_error(message);
}
@@ -336,15 +369,45 @@ void PvaClientMonitor::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()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::stop"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(!isStarted) return;
@@ -355,52 +418,27 @@ void PvaClientMonitor::stop()
bool PvaClientMonitor::poll()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::poll"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
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();
if(!monitorElement) return false;
userPoll = true;
pvaClientData->setData(monitorElement);
return true;
return true;
}
bool PvaClientMonitor::waitEvent(double secondsToWait)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::waitEvent"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(!isStarted) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::waitEvent illegal state ";
throw std::runtime_error(message);
}
@@ -418,26 +456,12 @@ bool PvaClientMonitor::waitEvent(double secondsToWait)
void PvaClientMonitor::releaseEvent()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::releaseEvent"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< 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) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::releaseEvent did not call poll";
throw std::runtime_error(message);
}
@@ -445,14 +469,16 @@ void PvaClientMonitor::releaseEvent()
monitor->release(monitorElement);
}
PvaClientChannelPtr PvaClientMonitor::getPvaClientChannel()
{
return pvaClientChannel;
}
PvaClientMonitorDataPtr PvaClientMonitor::getData()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientMonitor::getData"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkMonitorState();
+6 -183
View File
@@ -19,7 +19,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -53,43 +52,16 @@ PvaClientMonitorDataPtr PvaClientMonitorData::create(StructureConstPtr const & s
}
PvaClientMonitorData::PvaClientMonitorData(StructureConstPtr const & structure)
: structure(structure)
: PvaClientData(structure)
{
messagePrefix = "";
}
void PvaClientMonitorData::setData(MonitorElementPtr const & monitorElement)
{
pvStructure = monitorElement->pvStructurePtr;
changedBitSet = monitorElement->changedBitSet;
PVStructurePtr pvStructure = monitorElement->pvStructurePtr;
BitSetPtr changedBitSet = monitorElement->changedBitSet;
PvaClientData::setData(pvStructure,changedBitSet);
overrunBitSet = monitorElement->overrunBitSet;
pvValue = pvStructure->getSubField("value");
}
void PvaClientMonitorData::checkValue()
{
if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue);
}
void PvaClientMonitorData::setMessagePrefix(std::string const & value)
{
messagePrefix = value + " ";
}
StructureConstPtr PvaClientMonitorData::getStructure()
{return structure;}
PVStructurePtr PvaClientMonitorData::getPVStructure()
{
if(pvStructure) return pvStructure;
throw std::runtime_error(messagePrefix + noStructure);
}
BitSetPtr PvaClientMonitorData::getChangedBitSet()
{
if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure);
return changedBitSet;
}
BitSetPtr PvaClientMonitorData::getOverrunBitSet()
@@ -98,24 +70,6 @@ BitSetPtr PvaClientMonitorData::getOverrunBitSet()
return overrunBitSet;
}
std::ostream & PvaClientMonitorData::showChanged(std::ostream & out)
{
if(!changedBitSet) throw std::runtime_error(messagePrefix + noStructure);
size_t nextSet = changedBitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = changedBitSet->nextSetBit(nextSet+1);
}
return out;
}
std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
{
if(!overrunBitSet) throw std::runtime_error(messagePrefix + noStructure);
@@ -123,9 +77,9 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
pvField = getPVStructure();
} else {
pvField = pvStructure->getSubField(nextSet);
pvField = getPVStructure()->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
@@ -134,135 +88,4 @@ std::ostream & PvaClientMonitorData::showOverrun(std::ostream & out)
return out;
}
bool PvaClientMonitorData::hasValue()
{
if(!pvValue) return false;
return true;
}
bool PvaClientMonitorData::isValueScalar()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool PvaClientMonitorData::isValueScalarArray()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
PVFieldPtr PvaClientMonitorData::getValue()
{
checkValue();
return pvValue;
}
PVScalarPtr PvaClientMonitorData::getScalarValue()
{
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalar);
}
return pv;
}
PVArrayPtr PvaClientMonitorData::getArrayValue()
{
checkValue();
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noArray);
}
return pv;
}
PVScalarArrayPtr PvaClientMonitorData::getScalarArrayValue()
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + noScalarArray);
}
return pv;
}
double PvaClientMonitorData::getDouble()
{
PVScalarPtr pvScalar = getScalarValue();
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(messagePrefix + notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
string PvaClientMonitorData::getString()
{
PVScalarPtr pvScalar = getScalarValue();
return convert->toString(pvScalar);
}
shared_vector<const double> PvaClientMonitorData::getDoubleArray()
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notDoubleArray);
}
return pv->view();
}
shared_vector<const string> PvaClientMonitorData::getStringArray()
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notStringArray);
}
return pv->view();
}
Alarm PvaClientMonitorData::getAlarm()
{
if(!pvStructure) {
throw std::runtime_error(messagePrefix + noAlarm);
}
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("alarm");
if(!pvs) throw std::runtime_error(messagePrefix + noAlarm);
pvAlarm.attach(pvs);
if(pvAlarm.isAttached()) {
Alarm alarm;
pvAlarm.get(alarm);
pvAlarm.detach();
return alarm;
}
throw std::runtime_error(messagePrefix + noAlarm);
}
TimeStamp PvaClientMonitorData::getTimeStamp()
{
if(!pvStructure) {
throw std::runtime_error(messagePrefix + noTimeStamp);
}
PVStructurePtr pvs = pvStructure->getSubField<PVStructure>("timeStamp");
if(!pvs) throw std::runtime_error(messagePrefix + noTimeStamp);
pvTimeStamp.attach(pvs);
if(pvTimeStamp.isAttached()) {
TimeStamp timeStamp;
pvTimeStamp.get(timeStamp);
pvTimeStamp.detach();
return timeStamp;
}
throw std::runtime_error(messagePrefix + noTimeStamp);
}
}}
+32 -21
View File
@@ -17,9 +17,6 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -31,26 +28,32 @@ static CreateRequest::shared_pointer createRequestPvt = CreateRequest::create()
PvaClientMultiChannelPtr PvaClientMultiChannel::create(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const string> const & channelNames,
shared_vector<const string> const & channelNames,
string const & providerName,
size_t maxNotConnected)
size_t maxNotConnected,
shared_vector<const string> const & providerNames)
{
return PvaClientMultiChannelPtr(
new PvaClientMultiChannel(pvaClient,channelNames,providerName,maxNotConnected));
new PvaClientMultiChannel(
pvaClient,channelNames,providerName,maxNotConnected,providerNames));
}
PvaClientMultiChannel::PvaClientMultiChannel(
PvaClientPtr const &pvaClient,
epics::pvData::shared_vector<const string> const & channelName,
shared_vector<const string> const & channelNames,
string const & providerName,
size_t maxNotConnected)
size_t maxNotConnected,
shared_vector<const string> const & providerNames)
: pvaClient(pvaClient),
channelName(channelName),
channelNames(channelNames),
providerName(providerName),
maxNotConnected(maxNotConnected),
numChannel(channelName.size()),
providerNames(providerNames),
numChannel(channelNames.size()),
numProviderNames(providerNames.size()),
numConnected(0),
firstConnect(true),
pvaClientChannelArray(PvaClientChannelArray(numChannel,PvaClientChannelPtr())),
isConnected(shared_vector<epics::pvData::boolean>(numChannel,false)),
createRequest(CreateRequest::create())
@@ -65,25 +68,34 @@ PvaClientMultiChannel::~PvaClientMultiChannel()
void PvaClientMultiChannel::checkConnected()
{
if(numConnected==0) connect();
if(firstConnect) {
connect();
firstConnect = false;
}
}
epics::pvData::shared_vector<const string> PvaClientMultiChannel::getChannelNames()
shared_vector<const string> PvaClientMultiChannel::getChannelNames()
{
return channelName;
return channelNames;
}
Status PvaClientMultiChannel::connect(double timeout)
{
if(!firstConnect) return Status::Ok;
firstConnect = false;
for(size_t i=0; i< numChannel; ++i) {
pvaClientChannelArray[i] = pvaClient->createChannel(channelName[i],providerName);
if(numProviderNames<=i) {
pvaClientChannelArray[i] = pvaClient->createChannel(channelNames[i],providerName);
} else {
pvaClientChannelArray[i] = pvaClient->createChannel(channelNames[i],providerNames[i]);
}
pvaClientChannelArray[i]->issueConnect();
}
Status returnStatus = Status::Ok;
Status status = Status::Ok;
size_t numBad = 0;
for(size_t i=0; i< numChannel; ++i) {
if(numBad==0) {
if(numBad==0) {
status = pvaClientChannelArray[i]->waitConnect(timeout);
} else {
status = pvaClientChannelArray[i]->waitConnect(.001);
@@ -91,11 +103,10 @@ Status PvaClientMultiChannel::connect(double timeout)
if(status.isOK()) {
++numConnected;
isConnected[i] = true;
continue;
} else {
if(returnStatus.isOK()) returnStatus = status;
++numBad;
}
if(returnStatus.isOK()) returnStatus = status;
++numBad;
if(numBad>maxNotConnected) break;
}
return numBad>maxNotConnected ? returnStatus : Status::Ok;
}
@@ -118,7 +129,7 @@ bool PvaClientMultiChannel::connectionChange()
return false;
}
epics::pvData::shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
shared_vector<epics::pvData::boolean> PvaClientMultiChannel::getIsConnected()
{
for(size_t i=0; i<numChannel; ++i) {
PvaClientChannelPtr pvaClientChannel = pvaClientChannelArray[i];
@@ -143,7 +154,7 @@ PvaClientPtr PvaClientMultiChannel::getPvaClient()
return pvaClient;
}
PvaClientMultiGetDoublePtr PvaClientMultiChannel::createGet()
{
+16 -8
View File
@@ -16,13 +16,12 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientMultiGetDoublePtr PvaClientMultiGetDouble::create(
@@ -40,7 +39,7 @@ PvaClientMultiGetDouble::PvaClientMultiGetDouble(
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()),
doubleValue(shared_vector<double>(nchannel)),
doubleValue( shared_vector<double>(nchannel)),
pvaClientGet(std::vector<PvaClientGetPtr>(nchannel,PvaClientGetPtr())),
isGetConnected(false)
{
@@ -54,7 +53,7 @@ PvaClientMultiGetDouble::~PvaClientMultiGetDouble()
void PvaClientMultiGetDouble::connect()
{
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
shared_vector<epics::pvData::boolean>isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
for(size_t i=0; i<nchannel; ++i)
{
@@ -76,14 +75,14 @@ void PvaClientMultiGetDouble::connect()
isGetConnected = true;
}
epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
shared_vector<double> PvaClientMultiGetDouble::get()
{
if(!isGetConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientGet[i]) pvaClientGet[i]=pvaClientChannelArray[i]->createGet("value");
pvaClientGet[i]->issueGet();
}
}
@@ -97,13 +96,22 @@ epics::pvData::shared_vector<double> PvaClientMultiGetDouble::get()
throw std::runtime_error(message);
}
}
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i])
{
PVStructurePtr pvStructure = pvaClientGet[i]->getData()->getPVStructure();
doubleValue[i] = getConvert()->toDouble(pvStructure->getSubField<PVScalar>("value"));
PVScalarPtr pvScalar(pvStructure->getSubField<PVScalar>("value"));
if(pvScalar) {
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(ScalarTypeFunc::isNumeric(scalarType)) {
doubleValue[i] = getConvert()->toDouble(pvScalar);
} else {
doubleValue[i] = epicsNAN;
}
} else {
doubleValue[i] = epicsNAN;
}
} else {
doubleValue[i] = epicsNAN;
}
+13 -3
View File
@@ -16,13 +16,12 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientMultiMonitorDoublePtr PvaClientMultiMonitorDouble::create(
@@ -91,6 +90,17 @@ bool PvaClientMultiMonitorDouble::poll()
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientMonitor[i]){
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor("value");
pvaClientMonitor[i]->issueConnect();
Status status = pvaClientMonitor[i]->waitConnect();
if(!status.isOK()) {
string message = string("channel ") + pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
pvaClientMonitor[i]->start();
}
if(pvaClientMonitor[i]->poll()) {
doubleValue[i] = pvaClientMonitor[i]->getData()->getDouble();
pvaClientMonitor[i]->releaseEvent();
@@ -117,7 +127,7 @@ bool PvaClientMultiMonitorDouble::waitEvent(double waitForEvent)
return false;
}
epics::pvData::shared_vector<double> PvaClientMultiMonitorDouble::get()
shared_vector<double> PvaClientMultiMonitorDouble::get()
{
return doubleValue;
}
+13 -6
View File
@@ -16,13 +16,12 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientMultiPutDoublePtr PvaClientMultiPutDouble::create(
@@ -77,7 +76,7 @@ void PvaClientMultiPutDouble::connect()
isPutConnected = true;
}
void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &data)
void PvaClientMultiPutDouble::put(shared_vector<double> const &data)
{
if(!isPutConnected) connect();
if(data.size()!=nchannel) {
@@ -87,10 +86,18 @@ void PvaClientMultiPutDouble::put(epics::pvData::shared_vector<double> const &da
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientPut[i]) pvaClientPut[i]=pvaClientChannelArray[i]->createPut("value");
PVStructurePtr pvTop = pvaClientPut[i]->getData()->getPVStructure();
PVScalarPtr pvValue = pvTop->getSubField<PVScalar>("value");
getConvert()->fromDouble(pvValue,data[i]);
pvaClientPut[i]->issuePut();
PVScalarPtr pvScalar= pvTop->getSubField<PVScalar>("value");
if(pvScalar && ScalarTypeFunc::isNumeric(pvScalar->getScalar()->getScalarType())) {
getConvert()->fromDouble(pvScalar,data[i]);
pvaClientPut[i]->issuePut();
} else {
string message = string("channel ")
+ pvaClientChannelArray[i]->getChannelName()
+ " is not a numeric scalar";
throw std::runtime_error(message);
}
}
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut();
+48 -35
View File
@@ -15,16 +15,15 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
epics::pvData::UnionConstPtr const & u,
UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
PVStructurePtr const & pvRequest)
@@ -34,22 +33,21 @@ PvaClientNTMultiDataPtr PvaClientNTMultiData::create(
}
PvaClientNTMultiData::PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u,
UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest)
PVStructurePtr const & pvRequest)
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()),
gotAlarm(false),
gotTimeStamp(false)
{
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::PvaClientNTMultiData()\n";
PVFieldPtr pvValue = pvRequest->getSubField("field.value");
if(!pvValue) {
throw std::runtime_error("pvRequest did not specify value");
}
changeFlags = shared_vector<epics::pvData::boolean>(nchannel);
topPVStructure.resize(nchannel);
unionValue.resize(nchannel);
PVDataCreatePtr pvDataCreate = getPVDataCreate();
for(size_t i=0; i< nchannel; ++i) {
@@ -68,7 +66,7 @@ PvaClientNTMultiData::PvaClientNTMultiData(
severity.resize(nchannel);
status.resize(nchannel);
message.resize(nchannel);
}
if(pvRequest->getSubField("field.timeStamp")) {
gotTimeStamp = true;
@@ -89,30 +87,24 @@ PvaClientNTMultiData::~PvaClientNTMultiData()
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiData::~PvaClientNTMultiData()\n";
}
void PvaClientNTMultiData::setStructure(StructureConstPtr const & structure,size_t index)
{
FieldConstPtr field = structure->getField("value");
if(!field) {
string message = "channel "
+ pvaClientChannelArray[index]->getChannel()->getChannelName()
+ " does not have top level value field";
throw std::runtime_error(message);
}
}
void PvaClientNTMultiData::setPVStructure(
PVStructurePtr const &pvStructure,size_t index)
{
topPVStructure[index] = pvStructure;
}
shared_vector<epics::pvData::boolean> PvaClientNTMultiData::getChannelChangeFlags()
{
return changeFlags;
}
size_t PvaClientNTMultiData::getNumber()
{
return nchannel;
}
void PvaClientNTMultiData::startDeltaTime()
{
for(size_t i=0; i<nchannel; ++i)
@@ -138,28 +130,49 @@ void PvaClientNTMultiData::startDeltaTime()
}
void PvaClientNTMultiData::endDeltaTime()
void PvaClientNTMultiData::endDeltaTime(bool valueOnly)
{
for(size_t i=0; i<nchannel; ++i)
{
PVStructurePtr pvst = topPVStructure[i];
if(!pvst) {
unionValue[i] = PVUnionPtr();
} else {
unionValue[i]->set(pvst->getSubField("value"));
changeFlags[i] = false;
if(pvst&&unionValue[i]) {
changeFlags[i] = true;
if(valueOnly) {
PVFieldPtr pvValue = pvst->getSubField("value");
if(pvValue) {
unionValue[i]->set(pvst->getSubField("value"));
}
} else {
unionValue[i]->set(pvst);
}
if(gotAlarm)
{
severity[i] = pvst->getSubField<PVInt>("alarm.severity")->get();
status[i] = pvst->getSubField<PVInt>("alarm.status")->get();
message[i] = pvst->getSubField<PVString>("alarm.message")->get();
PVIntPtr pvSeverity = pvst->getSubField<PVInt>("alarm.severity");
PVIntPtr pvStatus = pvst->getSubField<PVInt>("alarm.status");
PVStringPtr pvMessage = pvst->getSubField<PVString>("alarm.message");
if(pvSeverity&&pvStatus&&pvMessage) {
severity[i] = pvSeverity->get();
status[i] = pvStatus->get();
message[i] = pvMessage->get();
} else {
severity[i] = undefinedAlarm;
status[i] = undefinedStatus;
message[i] = "no alarm field";
}
}
if(gotTimeStamp)
{
secondsPastEpoch[i] = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch")->get();
nanoseconds[i] = pvst->getSubField<PVInt>("timeStamp.nanoseconds")->get();
userTag[i] = pvst->getSubField<PVInt>("timeStamp.userTag")->get();
PVLongPtr pvEpoch = pvst->getSubField<PVLong>("timeStamp.secondsPastEpoch");
PVIntPtr pvNano = pvst->getSubField<PVInt>("timeStamp.nanoseconds");
PVIntPtr pvTag = pvst->getSubField<PVInt>("timeStamp.userTag");
if(pvEpoch&&pvNano&&pvTag) {
secondsPastEpoch[i] = pvEpoch->get();
nanoseconds[i] = pvNano->get();
userTag[i] = pvTag->get();
}
}
}
}
}
}
@@ -174,7 +187,7 @@ NTMultiChannelPtr PvaClientNTMultiData::getNTMultiChannel()
PVStructurePtr pvStructure = getPVDataCreate()->createPVStructure(ntMultiChannelStructure);
NTMultiChannelPtr ntMultiChannel = NTMultiChannel::wrap(pvStructure);
ntMultiChannel->getChannelName()->replace(pvaClientMultiChannel->getChannelNames());
shared_vector<epics::pvData::PVUnionPtr> val(nchannel);
shared_vector<PVUnionPtr> val(nchannel);
for(size_t i=0; i<nchannel; ++i) val[i] = unionValue[i];
ntMultiChannel->getValue()->replace(freeze(val));
shared_vector<epics::pvData::boolean> connected = pvaClientMultiChannel->getIsConnected();
+12 -12
View File
@@ -15,13 +15,12 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiGetPtr PvaClientNTMultiGet::create(
@@ -39,7 +38,7 @@ PvaClientNTMultiGet::PvaClientNTMultiGet(
UnionConstPtr const & u,
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest)
PVStructurePtr const & pvRequest)
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
pvRequest(pvRequest),
@@ -64,13 +63,10 @@ void PvaClientNTMultiGet::connect()
{
pvaClientGet.resize(nchannel);
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(request);
pvaClientGet[i] = pvaClientChannelArray[i]->createGet(pvRequest);
pvaClientGet[i]->issueConnect();
}
}
@@ -79,7 +75,7 @@ void PvaClientNTMultiGet::connect()
if(isConnected[i]) {
Status status = pvaClientGet[i]->waitConnect();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelGet::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -87,14 +83,18 @@ void PvaClientNTMultiGet::connect()
this->isConnected = true;
}
void PvaClientNTMultiGet::get()
void PvaClientNTMultiGet::get(bool valueOnly)
{
if(!isConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientGet[i]){
pvaClientGet[i]=pvaClientChannelArray[i]->createGet(pvRequest);
pvaClientGet[i]->connect();
}
pvaClientGet[i]->issueGet();
}
}
@@ -103,7 +103,7 @@ void PvaClientNTMultiGet::get()
if(isConnected[i]) {
Status status = pvaClientGet[i]->waitGet();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelGet::waitGet " + status.getMessage();
throw std::runtime_error(message);
}
@@ -115,7 +115,7 @@ void PvaClientNTMultiGet::get()
pvaClientNTMultiData->setPVStructure(pvaClientGet[i]->getData()->getPVStructure(),i);
}
}
pvaClientNTMultiData->endDeltaTime();
pvaClientNTMultiData->endDeltaTime(valueOnly);
}
PvaClientNTMultiDataPtr PvaClientNTMultiGet::getData()
+16 -15
View File
@@ -18,18 +18,17 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiMonitorPtr PvaClientNTMultiMonitor::create(
PvaClientMultiChannelPtr const &pvaMultiChannel,
PvaClientChannelArray const &pvaClientChannelArray,
epics::pvData::PVStructurePtr const & pvRequest)
PVStructurePtr const & pvRequest)
{
UnionConstPtr u = getFieldCreate()->createVariantUnion();
PvaClientNTMultiMonitorPtr pvaClientNTMultiMonitor(
@@ -68,13 +67,10 @@ void PvaClientNTMultiMonitor::connect()
{
pvaClientMonitor.resize(nchannel);
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
string request = "value";
if(pvRequest->getSubField("field.alarm")) request += ",alarm";
if(pvRequest->getSubField("field.timeStamp")) request += ",timeStamp";
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(request);
pvaClientMonitor[i] = pvaClientChannelArray[i]->createMonitor(pvRequest);
pvaClientMonitor[i]->issueConnect();
}
}
@@ -83,7 +79,7 @@ void PvaClientNTMultiMonitor::connect()
if(isConnected[i]) {
Status status = pvaClientMonitor[i]->waitConnect();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelMonitor::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -95,24 +91,29 @@ void PvaClientNTMultiMonitor::connect()
this->isConnected = true;
}
bool PvaClientNTMultiMonitor::poll()
bool PvaClientNTMultiMonitor::poll(bool valueOnly)
{
if(!isConnected) connect();
bool result = false;
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
pvaClientNTMultiData->startDeltaTime();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
pvaClientNTMultiData->startDeltaTime();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(pvaClientMonitor[i]->poll()) {
if(!pvaClientMonitor[i]){
pvaClientMonitor[i]=pvaClientChannelArray[i]->createMonitor(pvRequest);
pvaClientMonitor[i]->connect();
pvaClientMonitor[i]->start();
}
if(pvaClientMonitor[i]->poll()) {
pvaClientNTMultiData->setPVStructure(
pvaClientMonitor[i]->getData()->getPVStructure(),i);
pvaClientMonitor[i]->getData()->getPVStructure(),i);
pvaClientMonitor[i]->releaseEvent();
result = true;
}
}
}
if(result) pvaClientNTMultiData->endDeltaTime();
}
if(result) pvaClientNTMultiData->endDeltaTime(valueOnly);
return result;
}
+43 -13
View File
@@ -17,13 +17,12 @@
#include <pv/pvaClientMultiChannel.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::nt;
using namespace std;
namespace epics { namespace pvaClient {
namespace epics { namespace pvaClient {
PvaClientNTMultiPutPtr PvaClientNTMultiPut::create(
PvaClientMultiChannelPtr const &pvaMultiChannel,
@@ -39,8 +38,8 @@ PvaClientNTMultiPut::PvaClientNTMultiPut(
: pvaClientMultiChannel(pvaClientMultiChannel),
pvaClientChannelArray(pvaClientChannelArray),
nchannel(pvaClientChannelArray.size()),
unionValue(shared_vector<epics::pvData::PVUnionPtr>(nchannel,PVUnionPtr())),
value(shared_vector<epics::pvData::PVFieldPtr>(nchannel,PVFieldPtr())),
unionValue(shared_vector<PVUnionPtr>(nchannel,PVUnionPtr())),
value(shared_vector<PVFieldPtr>(nchannel,PVFieldPtr())),
isConnected(false)
{
if(PvaClient::getDebug()) cout<< "PvaClientNTMultiPut::PvaClientNTMultiPut()\n";
@@ -68,7 +67,7 @@ void PvaClientNTMultiPut::connect()
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitConnect();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitConnect " + status.getMessage();
throw std::runtime_error(message);
}
@@ -84,7 +83,7 @@ void PvaClientNTMultiPut::connect()
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitGet();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitGet " + status.getMessage();
throw std::runtime_error(message);
}
@@ -103,9 +102,26 @@ void PvaClientNTMultiPut::connect()
this->isConnected = true;
}
shared_vector<epics::pvData::PVUnionPtr> PvaClientNTMultiPut::getValues()
shared_vector<PVUnionPtr> PvaClientNTMultiPut::getValues()
{
if(!isConnected) connect();
shared_vector<epics::pvData::boolean> isConnected = pvaClientMultiChannel->getIsConnected();
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientPut[i]){
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
pvaClientPut[i]->connect();
pvaClientPut[i]->get();
value[i] = pvaClientPut[i]->getData()->getValue();
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
builder->add("value",value[i]->getField());
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
}
}
}
return unionValue;
}
@@ -116,15 +132,29 @@ void PvaClientNTMultiPut::put()
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
if(!pvaClientPut[i]){
pvaClientPut[i] = pvaClientChannelArray[i]->createPut();
pvaClientPut[i]->connect();
pvaClientPut[i]->get();
value[i] = pvaClientPut[i]->getData()->getValue();
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
FieldBuilderPtr builder = fieldCreate->createFieldBuilder();
builder->add("value",value[i]->getField());
unionValue[i] = pvDataCreate->createPVUnion(builder->createUnion());
}
value[i]->copy(*unionValue[i]->get());
pvaClientPut[i]->issuePut();
}
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitPut " + status.getMessage();
throw std::runtime_error(message);
}
for(size_t i=0; i<nchannel; ++i)
{
if(isConnected[i]) {
Status status = pvaClientPut[i]->waitPut();
if(status.isOK()) continue;
string message = string("channel ") +pvaClientChannelArray[i]->getChannelName()
+ " PvaChannelPut::waitPut " + status.getMessage();
throw std::runtime_error(message);
}
}
}
+114 -52
View File
@@ -15,7 +15,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -43,7 +42,7 @@ public:
return clientProcess->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return;
clientProcess->message(message,messageType);
@@ -55,7 +54,7 @@ public:
{
PvaClientProcessPtr clientProcess(pvaClientProcess.lock());
if(!clientProcess) return;
clientProcess->channelProcessConnect(status,channelProcess);
clientProcess->channelProcessConnect(status,channelProcess);
}
virtual void processDone(
@@ -70,122 +69,173 @@ public:
PvaClientProcessPtr PvaClientProcess::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
{
PvaClientProcessPtr epv(new PvaClientProcess(pvaClient,channel,pvRequest));
epv->channelProcessRequester = ChannelProcessRequesterImplPtr(
new ChannelProcessRequesterImpl(epv,pvaClient));
return epv;
if(PvaClient::getDebug()) {
cout<< "PvaClientProcess::create(pvaClient,channelName,pvRequest)\n"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " pvRequest " << pvRequest
<< endl;
}
PvaClientProcessPtr channelProcess(new PvaClientProcess(pvaClient,pvaClientChannel,pvRequest));
channelProcess->channelProcessRequester = ChannelProcessRequesterImplPtr(
new ChannelProcessRequesterImpl(channelProcess,pvaClient));
return channelProcess;
}
PvaClientProcess::PvaClientProcess(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
: pvaClient(pvaClient),
channel(channel),
pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest),
connectState(connectIdle),
processState(processIdle)
{
if(PvaClient::getDebug()) cout<< "PvaClientProcess::PvaClientProcess()\n";
if(PvaClient::getDebug()) {
cout<< "PvaClientProcess::PvaClientProcess()"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
PvaClientProcess::~PvaClientProcess()
{
if(PvaClient::getDebug()) cout<< "PvaClientProcess::~PvaClientProcess()\n";
channelProcess->destroy();
if(PvaClient::getDebug()) {
cout<< "PvaClientProcess::~PvaClientProcess()"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
// from ChannelProcessRequester
string PvaClientProcess::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientProcess::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) throw std::runtime_error("pvaClient was destroyed");
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientProcess::channelProcessConnect(
const Status& status,
ChannelProcess::shared_pointer const & channelProcess)
{
channelProcessConnectStatus = status;
connectState = connected;
this->channelProcess = channelProcess;
waitForConnect.signal();
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::channelProcessConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelProcessConnectStatus = status;
if(status.isOK()) {
this->channelProcess = channelProcess;
connectState = connected;
}
waitForConnect.signal();
}
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) {
req->channelProcessConnect(status,shared_from_this());
}
}
void PvaClientProcess::processDone(
const Status& status,
ChannelProcess::shared_pointer const & channelProcess)
{
channelProcessStatus = status;
processState = processComplete;
waitForProcess.signal();
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::processDone"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelProcessStatus = status;
processState = processComplete;
waitForProcess.signal();
}
PvaClientProcessRequesterPtr req(pvaClientProcessRequester.lock());
if(req) {
req->processDone(status,shared_from_this());
}
}
void PvaClientProcess::connect()
{
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::connect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
string message = string("channel ") + channel->getChannelName()
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientProcess::connect " + status.getMessage();
throw std::runtime_error(message);
}
void PvaClientProcess::issueConnect()
{
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::issueConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState!=connectIdle) {
string message = string("channel ") + channel->getChannelName()
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientProcess already connected ";
throw std::runtime_error(message);
}
connectState = connectActive;
channelProcess = channel->createChannelProcess(channelProcessRequester,pvRequest);
channelProcessConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelProcess = pvaClientChannel->getChannel()->createChannelProcess(channelProcessRequester,pvRequest);
}
Status PvaClientProcess::waitConnect()
{
if(connectState==connected) {
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
return channelProcessConnectStatus;
}
if(connectState!=connectActive) {
string message = string("channel ") + channel->getChannelName()
+ " pvaClientProcess illegal connect state ";
throw std::runtime_error(message);
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForConnect.wait();
if(!channelProcessConnectStatus.isOK()) connectState = connectIdle;
return channelProcessConnectStatus;
}
void PvaClientProcess::process()
{
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::process"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueProcess();
Status status = waitProcess();
if(status.isOK()) return;
string message = string("channel ") + channel->getChannelName()
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientProcess::process" + status.getMessage();
throw std::runtime_error(message);
}
void PvaClientProcess::issueProcess()
{
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::issueProcess"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect();
if(processState!=processIdle) {
string message = string("channel ") + channel->getChannelName()
if(processState==processActive) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientProcess::issueProcess process aleady active ";
throw std::runtime_error(message);
}
@@ -195,18 +245,30 @@ void PvaClientProcess::issueProcess()
Status PvaClientProcess::waitProcess()
{
if(processState==processComplete) {
processState = processIdle;
return channelProcessStatus;
}
if(processState!=processActive){
string message = string("channel ") + channel->getChannelName()
+ " PvaClientProcess::waitProcess llegal process state";
throw std::runtime_error(message);
if(PvaClient::getDebug()) {
cout << "PvaClientProcess::waitProcess"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForProcess.wait();
processState = processIdle;
processState = processComplete;
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;
}
}}
+144 -121
View File
@@ -15,7 +15,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -43,7 +42,7 @@ public:
return clientPut->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return;
clientPut->message(message,messageType);
@@ -56,7 +55,7 @@ public:
{
PvaClientPutPtr clientPut(pvaClientPut.lock());
if(!clientPut) return;
clientPut->channelPutConnect(status,channelPut,structure);
clientPut->channelPutConnect(status,channelPut,structure);
}
virtual void getDone(
@@ -70,7 +69,7 @@ public:
clientPut->getDone(status,channelPut,pvStructure,bitSet);
}
virtual void putDone(
virtual void putDone(
const Status& status,
ChannelPut::shared_pointer const & channelPut)
{
@@ -82,30 +81,29 @@ public:
PvaClientPutPtr PvaClientPut::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
{
PvaClientPutPtr epv(new PvaClientPut(pvaClient,channel,pvRequest));
epv->channelPutRequester = ChannelPutRequesterImplPtr(
new ChannelPutRequesterImpl(epv,pvaClient));
return epv;
PvaClientPutPtr clientPut(new PvaClientPut(pvaClient,pvaClientChannel,pvRequest));
clientPut->channelPutRequester = ChannelPutRequesterImplPtr(
new ChannelPutRequesterImpl(clientPut,pvaClient));
return clientPut;
}
PvaClientPut::PvaClientPut(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
: pvaClient(pvaClient),
channel(channel),
pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest),
connectState(connectIdle),
putState(putIdle)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientPut::PvaClientPut"
<< " channelName " << channel->getChannelName()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
@@ -113,36 +111,39 @@ PvaClientPut::PvaClientPut(
PvaClientPut::~PvaClientPut()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientPut::~PvaClientPut"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< 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){
connect();
get();
}
if(connectState==connectActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " "
+ channelPutConnectStatus.getMessage();
throw std::runtime_error(message);
}
}
string PvaClientPut::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientPut::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientPut::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientPut::channelPutConnect(
@@ -151,25 +152,26 @@ void PvaClientPut::channelPutConnect(
StructureConstPtr const & structure)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::channelPutConnect"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelPutConnectStatus = status;
this->channelPut = channelPut;
if(status.isOK()) {
this->channelPut = channelPut;
connectState = connected;
pvaClientData = PvaClientPutData::create(structure);
pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName());
}
}
waitForConnect.signal();
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->channelPutConnect(status,shared_from_this());
}
waitForConnect.signal();
}
void PvaClientPut::getDone(
@@ -179,23 +181,28 @@ void PvaClientPut::getDone(
BitSetPtr const & bitSet)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::getDone"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelGetPutStatus = status;
if(status.isOK()) {
PVStructurePtr pvs = pvaClientData->getPVStructure();
pvs->copyUnchecked(*pvStructure,*bitSet);
BitSetPtr bs = pvaClientData->getChangedBitSet();
bs->clear();
*bs |= *bitSet;
{
Lock xx(mutex);
channelGetPutStatus = status;
if(status.isOK()) {
PVStructurePtr pvs = pvaClientData->getPVStructure();
pvs->copyUnchecked(*pvStructure,*bitSet);
BitSetPtr bs = pvaClientData->getChangedBitSet();
bs->clear();
*bs |= *bitSet;
}
putState = putComplete;
waitForGetPut.signal();
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->getDone(status,shared_from_this());
}
waitForGetPut.signal();
}
void PvaClientPut::putDone(
@@ -203,28 +210,33 @@ void PvaClientPut::putDone(
ChannelPut::shared_pointer const & channelPut)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPut::putDone"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelGetPutStatus = status;
waitForGetPut.signal();
{
Lock xx(mutex);
channelGetPutStatus = status;
putState = putComplete;
waitForGetPut.signal();
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) { req->putDone(status,shared_from_this());}
}
void PvaClientPut::connect()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPut::connect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::connect "
+ status.getMessage();
throw std::runtime_error(message);
@@ -232,54 +244,45 @@ void PvaClientPut::connect()
void PvaClientPut::issueConnect()
{
Channel::shared_pointer chan(channel.lock());
if(PvaClient::getDebug()) {
cout << "PvaClientPut::issueConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState!=connectIdle) {
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientPut already connected ";
throw std::runtime_error(message);
}
if(chan) {
connectState = connectActive;
channelPut = chan->createChannelPut(channelPutRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientPut::issueConnect() but channel disconnected");
connectState = connectActive;
channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
}
Status PvaClientPut::waitConnect()
{
{
Lock xx(mutex);
if(connectState==connected) {
if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
return channelPutConnectStatus;
}
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPut::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
if(PvaClient::getDebug()) {
cout << "PvaClientPut::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForConnect.wait();
if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
return channelPutConnectStatus;
}
void PvaClientPut::get()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPut::get"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueGet();
Status status = waitGet();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::get "
+ status.getMessage();
throw std::runtime_error(message);
@@ -287,13 +290,15 @@ void PvaClientPut::get()
void PvaClientPut::issueGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPut::issueGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect();
if(putState!=putIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
if(putState==getActive || putState==putActive) {
string message = string("channel ")
+ channelName
+ pvaClientChannel->getChannel()->getChannelName()
+ "PvaClientPut::issueGet get or put aleady active ";
throw std::runtime_error(message);
}
@@ -303,30 +308,28 @@ void PvaClientPut::issueGet()
Status PvaClientPut::waitGet()
{
if(putState!=getActive){
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::waitGet illegal put state";
throw std::runtime_error(message);
if(PvaClient::getDebug()) {
cout << "PvaClientPut::waitGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForGetPut.wait();
putState = putIdle;
putState = putComplete;
return channelGetPutStatus;
}
void PvaClientPut::put()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPut::put"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issuePut();
Status status = waitPut();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::put "
+ status.getMessage();
throw std::runtime_error(message);
@@ -334,14 +337,18 @@ void PvaClientPut::put()
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(putState!=putIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
if(putState==getActive || putState==putActive) {
string message = string("channel ")
+ channelName
+ "PvaClientPut::issueGet get or put aleady active ";
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::issuePut get or put aleady active ";
throw std::runtime_error(message);
}
putState = putActive;
@@ -350,26 +357,42 @@ void PvaClientPut::issuePut()
Status PvaClientPut::waitPut()
{
if(putState!=putActive){
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ " PvaClientPut::waitPut illegal put state";
throw std::runtime_error(message);
if(PvaClient::getDebug()) {
cout << "PvaClientPut::waitPut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForGetPut.wait();
putState = putIdle;
putState = putComplete;
if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
return channelGetPutStatus;
}
PvaClientPutDataPtr PvaClientPut::getData()
{
checkPutState();
if(PvaClient::getDebug()) {
cout<< "PvaClientPut::getData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkConnectState();
if(putState==putIdle) get();
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;
}
}}
+59 -168
View File
@@ -25,6 +25,10 @@ using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace pvaClient {
static ConvertPtr convert = getConvert();
static string notCompatibleScalar("value is not a compatible scalar");
static string notDoubleArray("value is not a doubleArray");
static string notStringArray("value is not a stringArray");
class PvaClientPostHandlerPvt: public PostHandler
{
@@ -36,28 +40,21 @@ public:
void postPut() { putData->postPut(fieldNumber);}
};
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
static ConvertPtr convert = getConvert();
static string noValue("no value field");
static string notScalar("value is not a scalar");
static string notCompatibleScalar("value is not a compatible scalar");
static string notArray("value is not an array");
static string notScalarArray("value is not a scalarArray");
static string notDoubleArray("value is not a doubleArray");
static string notStringArray("value is not a stringArray");
PvaClientPutDataPtr PvaClientPutData::create(StructureConstPtr const & structure)
{
if(PvaClient::getDebug()) cout << "PvaClientPutData::create\n";
PvaClientPutDataPtr epv(new PvaClientPutData(structure));
return epv;
}
PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
: structure(structure),
pvStructure(getPVDataCreate()->createPVStructure(structure)),
bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())))
: PvaClientData(structure)
{
messagePrefix = "";
if(PvaClient::getDebug()) cout << "PvaClientPutData::PvaClientPutData\n";
PVStructurePtr pvStructure(getPVDataCreate()->createPVStructure(structure));
BitSetPtr bitSet(BitSetPtr(new BitSet(pvStructure->getNumberFields())));
setData(pvStructure,bitSet);
size_t nfields = pvStructure->getNumberFields();
postHandler.resize(nfields);
PVFieldPtr pvField;
@@ -71,145 +68,18 @@ PvaClientPutData::PvaClientPutData(StructureConstPtr const & structure)
}
pvField->setPostHandler(postHandler[i]);
}
pvValue = pvStructure->getSubField("value");
}
void PvaClientPutData::checkValue()
{
if(pvValue) return;
throw std::runtime_error(messagePrefix + noValue);
}
void PvaClientPutData::postPut(size_t fieldNumber)
{
bitSet->set(fieldNumber);
}
void PvaClientPutData::setMessagePrefix(std::string const & value)
{
messagePrefix = value + " ";
}
StructureConstPtr PvaClientPutData::getStructure()
{return structure;}
PVStructurePtr PvaClientPutData::getPVStructure()
{return pvStructure;}
BitSetPtr PvaClientPutData::getChangedBitSet()
{return bitSet;}
std::ostream & PvaClientPutData::showChanged(std::ostream & out)
{
size_t nextSet = bitSet->nextSetBit(0);
PVFieldPtr pvField;
while(nextSet!=string::npos) {
if(nextSet==0) {
pvField = pvStructure;
} else {
pvField = pvStructure->getSubField(nextSet);
}
string name = pvField->getFullName();
out << name << " = " << pvField << endl;
nextSet = bitSet->nextSetBit(nextSet+1);
}
return out;
}
bool PvaClientPutData::hasValue()
{
if(!pvValue) return false;
return true;
}
bool PvaClientPutData::isValueScalar()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalar) return true;
return false;
}
bool PvaClientPutData::isValueScalarArray()
{
if(!pvValue) return false;
if(pvValue->getField()->getType()==scalarArray) return true;
return false;
}
PVFieldPtr PvaClientPutData::getValue()
{
checkValue();
return pvValue;
}
PVScalarPtr PvaClientPutData::getScalarValue()
{
checkValue();
PVScalarPtr pv = pvStructure->getSubField<PVScalar>("value");
if(!pv) throw std::runtime_error(messagePrefix + notScalar);
return pv;
}
PVArrayPtr PvaClientPutData::getArrayValue()
{
checkValue();
PVArrayPtr pv = pvStructure->getSubField<PVArray>("value");
if(!pv) throw std::runtime_error(messagePrefix + notArray);
return pv;
}
PVScalarArrayPtr PvaClientPutData::getScalarArrayValue()
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) throw std::runtime_error(messagePrefix + notScalarArray);
return pv;
}
double PvaClientPutData::getDouble()
{
PVScalarPtr pvScalar = getScalarValue();
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
return pvDouble->get();
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(messagePrefix + notCompatibleScalar);
}
return convert->toDouble(pvScalar);
}
string PvaClientPutData::getString()
{
PVScalarPtr pvScalar = getScalarValue();
return convert->toString(pvScalar);
}
shared_vector<const double> PvaClientPutData::getDoubleArray()
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notDoubleArray);
}
return pv->view();
}
shared_vector<const string> PvaClientPutData::getStringArray()
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notStringArray);
}
return pv->view();
}
void PvaClientPutData::putDouble(double value)
{
PVScalarPtr pvScalar = getScalarValue();
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDouble\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::putDouble() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
ScalarType scalarType = pvScalar->getScalar()->getScalarType();
if(scalarType==pvDouble) {
PVDoublePtr pvDouble = static_pointer_cast<PVDouble>(pvScalar);
@@ -217,47 +87,68 @@ void PvaClientPutData::putDouble(double value)
return;
}
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::runtime_error(messagePrefix + notCompatibleScalar);
throw std::logic_error(
"PvaClientData::putDouble() did not find a numeric scalar field");
}
convert->fromDouble(pvScalar,value);
}
void PvaClientPutData::putString(std::string const & value)
{
PVScalarPtr pvScalar = getScalarValue();
if(PvaClient::getDebug()) cout << "PvaClientPutData::putString\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalar) {
throw std::logic_error("PvaClientData::putString() did not find a scalar field");
}
PVScalarPtr pvScalar = static_pointer_cast<PVScalar>(pvField);
convert->fromString(pvScalar,value);
}
void PvaClientPutData::putDoubleArray(shared_vector<const double> const & value)
{
checkValue();
PVDoubleArrayPtr pv = pvStructure->getSubField<PVDoubleArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notDoubleArray);
if(PvaClient::getDebug()) cout << "PvaClientPutData::putDoubleArray\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::putDoubleArray() did not find a scalarArray field");
}
pv->replace(value);
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
ScalarType scalarType = pvScalarArray->getScalarArray()->getElementType();
if(!ScalarTypeFunc::isNumeric(scalarType)) {
throw std::logic_error(
"PvaClientData::putDoubleArray() did not find a numeric scalarArray field");
}
pvScalarArray->putFrom<const double>(value);
}
void PvaClientPutData::putStringArray(shared_vector<const std::string> const & value)
{
checkValue();
PVStringArrayPtr pv = pvStructure->getSubField<PVStringArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notStringArray);
if(PvaClient::getDebug()) cout << "PvaClientPutData::putStringArray\n";
PVFieldPtr pvField = getSinglePVField();
Type type = pvField->getField()->getType();
if(type!=scalarArray) {
throw std::logic_error("PvaClientData::putStringArray() did not find a scalarArray field");
}
pv->replace(value);
PVScalarArrayPtr pvScalarArray = static_pointer_cast<PVScalarArray>(pvField);
pvScalarArray->putFrom<const string>(value);
return;
}
void PvaClientPutData::putStringArray(std::vector<std::string> const & value)
void PvaClientPutData::putStringArray(std::vector<string> const & value)
{
checkValue();
PVScalarArrayPtr pv = pvStructure->getSubField<PVScalarArray>("value");
if(!pv) {
throw std::runtime_error(messagePrefix + notScalarArray);
}
convert->fromStringArray(pv,0,value.size(),value,0);
size_t length = value.size();
shared_vector<string> val(length);
for(size_t i=0; i < length; ++i) val[i] = value[i];
putStringArray(freeze(val));
return;
}
void PvaClientPutData::postPut(size_t fieldNumber)
{
if(PvaClient::getDebug()) cout << "PvaClientPutData::postPut\n";
getChangedBitSet()->set(fieldNumber);
}
}}
+198 -146
View File
@@ -14,7 +14,6 @@
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -42,7 +41,7 @@ public:
return clientPutGet->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
if(!clientPutGet) return;
clientPutGet->message(message,messageType);
@@ -56,7 +55,7 @@ public:
{
PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock());
if(!clientPutGet) return;
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure);
}
virtual void putGetDone(
@@ -96,28 +95,28 @@ public:
PvaClientPutGetPtr PvaClientPutGet::create(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
{
PvaClientPutGetPtr epv(new PvaClientPutGet(pvaClient,channel,pvRequest));
epv->channelPutGetRequester = ChannelPutGetRequesterImplPtr(
new ChannelPutGetRequesterImpl(epv,pvaClient));
return epv;
PvaClientPutGetPtr clientPutGet(new PvaClientPutGet(pvaClient,pvaClientChannel,pvRequest));
clientPutGet->channelPutGetRequester = ChannelPutGetRequesterImplPtr(
new ChannelPutGetRequesterImpl(clientPutGet,pvaClient));
return clientPutGet;
}
PvaClientPutGet::PvaClientPutGet(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
PVStructurePtr const &pvRequest)
: pvaClient(pvaClient),
channel(channel),
pvaClientChannel(pvaClientChannel),
pvRequest(pvRequest),
connectState(connectIdle),
putGetState(putGetIdle)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientPutGet::PvaClientPutGet"
<< " channelName " << channel->getChannelName()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
@@ -125,36 +124,38 @@ PvaClientPutGet::PvaClientPutGet(
PvaClientPutGet::~PvaClientPutGet()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientPutGet::~PvaClientPutGet"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
channelPutGet->destroy();
}
void PvaClientPutGet::checkPutGetState()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::checkPutGetState"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle){
connect();
getPut();
connect();
}
if(connectState==connectActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " "
+ channelPutGetConnectStatus.getMessage();
throw std::runtime_error(message);
}
}
string PvaClientPutGet::getRequesterName()
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return string("PvaClientPutGet::getRequesterName() PvaClient isDestroyed");
return yyy->getRequesterName();
return pvaClientChannel->getRequesterName();
}
void PvaClientPutGet::message(string const & message,MessageType messageType)
{
PvaClientPtr yyy = pvaClient.lock();
if(!yyy) return;
yyy->message(message, messageType);
pvaClientChannel->message(message,messageType);
}
void PvaClientPutGet::channelPutGetConnect(
@@ -165,20 +166,27 @@ void PvaClientPutGet::channelPutGetConnect(
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::channelPutGetConnect"
<< " channelName " << channelPutGet->getChannel()->getChannelName()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetConnectStatus = status;
this->channelPutGet = channelPutGet;
if(status.isOK()) {
pvaClientPutData = PvaClientPutData::create(putStructure);
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
pvaClientGetData = PvaClientGetData::create(getStructure);
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
{
Lock xx(mutex);
channelPutGetConnectStatus = status;
if(status.isOK()) {
this->channelPutGet = channelPutGet;
connectState = connected;
pvaClientPutData = PvaClientPutData::create(putStructure);
pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
pvaClientGetData = PvaClientGetData::create(getStructure);
pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName());
}
waitForConnect.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->channelPutGetConnect(status,shared_from_this());
}
waitForConnect.signal();
}
void PvaClientPutGet::putGetDone(
@@ -188,19 +196,24 @@ void PvaClientPutGet::putGetDone(
BitSetPtr const & getChangedBitSet)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::putGetDone"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetStatus = status;
if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
{
Lock xx(mutex);
channelPutGetStatus = status;
if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
}
putGetState = putGetComplete;
waitForPutGet.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->putGetDone(status,shared_from_this());
}
waitForPutGet.signal();
}
void PvaClientPutGet::getPutDone(
@@ -210,23 +223,28 @@ void PvaClientPutGet::getPutDone(
BitSetPtr const & putBitSet)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::getPutDone"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetStatus = status;
if(status.isOK()) {
PVStructurePtr pvs = pvaClientPutData->getPVStructure();
pvs->copyUnchecked(*putPVStructure,*putBitSet);
BitSetPtr bs = pvaClientPutData->getChangedBitSet();
bs->clear();
*bs |= *putBitSet;
{
Lock xx(mutex);
channelPutGetStatus = status;
if(status.isOK()) {
PVStructurePtr pvs = pvaClientPutData->getPVStructure();
pvs->copyUnchecked(*putPVStructure,*putBitSet);
BitSetPtr bs = pvaClientPutData->getChangedBitSet();
bs->clear();
*bs |= *putBitSet;
}
putGetState = putGetComplete;
waitForPutGet.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->getPutDone(status,shared_from_this());
}
waitForPutGet.signal();
}
void PvaClientPutGet::getGetDone(
@@ -236,31 +254,38 @@ void PvaClientPutGet::getGetDone(
BitSetPtr const & getChangedBitSet)
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout << "PvaClientPutGet::getGetDone"
<< " channelName " << channelName
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
channelPutGetStatus = status;
if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
{
Lock xx(mutex);
channelPutGetStatus = status;
if(status.isOK()) {
pvaClientGetData->setData(getPVStructure,getChangedBitSet);
}
putGetState = putGetComplete;
waitForPutGet.signal();
}
PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock());
if(req) {
req->getGetDone(status,shared_from_this());
}
waitForPutGet.signal();
}
void PvaClientPutGet::connect()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::connect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueConnect();
Status status = waitConnect();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::connect "
+ status.getMessage();
throw std::runtime_error(message);
@@ -268,55 +293,46 @@ void PvaClientPutGet::connect()
void PvaClientPutGet::issueConnect()
{
Channel::shared_pointer chan(channel.lock());
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issueConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState!=connectIdle) {
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " pvaClientPutGet already connected ";
throw std::runtime_error(message);
}
if(chan) {
connectState = connectActive;
channelPutGet = chan->createChannelPutGet(channelPutGetRequester,pvRequest);
return;
}
throw std::runtime_error("PvaClientPutGet::issueConnect() but channel disconnected");
connectState = connectActive;
channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
channelPutGet = pvaClientChannel->getChannel()->createChannelPutGet(channelPutGetRequester,pvRequest);
}
Status PvaClientPutGet::waitConnect()
{
{
Lock xx(mutex);
if(connectState==connected) {
if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle;
return channelPutGetConnectStatus;
}
if(connectState!=connectActive) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForConnect.wait();
connectState = channelPutGetConnectStatus.isOK() ? connected : connectIdle;
return channelPutGetConnectStatus;
}
void PvaClientPutGet::putGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::putGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issuePutGet();
Status status = waitPutGet();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::putGet "
+ status.getMessage();
throw std::runtime_error(message);
@@ -324,12 +340,15 @@ void PvaClientPutGet::putGet()
void PvaClientPutGet::issuePutGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issuePutGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
if(putGetState==putGetActive) {
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::issuePutGet get or put aleady active ";
throw std::runtime_error(message);
}
@@ -340,29 +359,28 @@ void PvaClientPutGet::issuePutGet()
Status PvaClientPutGet::waitPutGet()
{
if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitPutGet get or put aleady active ";
throw std::runtime_error(message);
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitPutGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForPutGet.wait();
putGetState = putGetIdle;
if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear();
return channelPutGetStatus;
}
void PvaClientPutGet::getGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::getGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueGetGet();
Status status = waitGetGet();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::getGet "
+ status.getMessage();
throw std::runtime_error(message);
@@ -370,12 +388,15 @@ void PvaClientPutGet::getGet()
void PvaClientPutGet::issueGetGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issueGetGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
if(putGetState==putGetActive) {
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::issueGetGet get or put aleady active ";
throw std::runtime_error(message);
}
@@ -385,29 +406,27 @@ void PvaClientPutGet::issueGetGet()
Status PvaClientPutGet::waitGetGet()
{
if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitGetGet get or put aleady active ";
throw std::runtime_error(message);
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitGetGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForPutGet.wait();
putGetState = putGetIdle;
return channelPutGetStatus;
}
void PvaClientPutGet::getPut()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::getGetPut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
issueGetPut();
Status status = waitGetPut();
if(status.isOK()) return;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::getPut "
+ status.getMessage();
throw std::runtime_error(message);
@@ -415,12 +434,15 @@ void PvaClientPutGet::getPut()
void PvaClientPutGet::issueGetPut()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::issueGetPut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect();
if(putGetState!=putGetIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
if(putGetState==putGetActive) {
string message = string("channel ")
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPutGet::issueGetPut get or put aleady active ";
throw std::runtime_error(message);
}
@@ -430,29 +452,59 @@ void PvaClientPutGet::issueGetPut()
Status PvaClientPutGet::waitGetPut()
{
if(putGetState!=putGetActive){
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ") + channelName
+ " PvaClientPutGet::waitGetPut get or put aleady active ";
throw std::runtime_error(message);
if(PvaClient::getDebug()) {
cout << "PvaClientPutGet::waitGetPut"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
waitForPutGet.wait();
putGetState = putGetIdle;
return channelPutGetStatus;
}
PvaClientGetDataPtr PvaClientPutGet::getGetData()
{
if(PvaClient::getDebug()) {
cout<< "PvaClientPutGet::getGetData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkPutGetState();
if(putGetState==putGetIdle){
getGet();
getPut();
}
return pvaClientGetData;
}
PvaClientPutDataPtr PvaClientPutGet::getPutData()
{
if(PvaClient::getDebug()) {
cout<< "PvaClientPutGet::getPutData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkPutGetState();
if(putGetState==putGetIdle){
getGet();
getPut();
}
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;
}
}}
+22 -14
View File
@@ -12,13 +12,12 @@
#include <sstream>
#include <pv/event.h>
#include <pv/bitSetUtil.h>
#include <pv/rpcService.h>
#define epicsExportSharedSymbols
#include <pv/pvaClient.h>
using std::tr1::static_pointer_cast;
using std::tr1::dynamic_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
@@ -46,14 +45,14 @@ public:
return clientRPC->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
virtual void message(std::string const & message, MessageType messageType) {
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
if(!clientRPC) return;
clientRPC->message(message,messageType);
}
virtual void channelRPCConnect(
const epics::pvData::Status& status,
const Status& status,
ChannelRPC::shared_pointer const & channelRPC)
{
PvaClientRPCPtr clientRPC(pvaClientRPC.lock());
@@ -95,7 +94,7 @@ PvaClientRPC::PvaClientRPC(
PvaClientPtr const &pvaClient,
Channel::shared_pointer const & channel,
PVStructurePtr const &pvRequest)
:
:
connectState(connectIdle),
pvaClient(pvaClient),
channel(channel),
@@ -105,7 +104,7 @@ PvaClientRPC::PvaClientRPC(
{
if(PvaClient::getDebug()) {
cout<< "PvaClientRPC::PvaClientRPC()"
<< " channelName " << channel->getChannelName()
<< " channelName " << channel->getChannelName()
<< endl;
}
}
@@ -171,7 +170,7 @@ void PvaClientRPC::rpcConnect(
cout << "PvaClientRPC::rpcConnect calling waitForConnect.signal\n";
}
waitForConnect.signal();
}
void PvaClientRPC::requestDone(
@@ -182,6 +181,7 @@ void PvaClientRPC::requestDone(
PvaClientRPCRequesterPtr req = pvaClientRPCRequester.lock();
{
Lock xx(mutex);
requestStatus = status;
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
@@ -195,7 +195,7 @@ void PvaClientRPC::requestDone(
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ channelName
+" PvaClientRPC::requestDone"
+ " but not active";
throw std::runtime_error(message);
@@ -222,11 +222,11 @@ void PvaClientRPC::connect()
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
string message = string("channel ")
+ channelName
+ " PvaClientRPC::connect "
+ status.getMessage();
throw std::runtime_error(message);
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
}
void PvaClientRPC::issueConnect()
@@ -237,7 +237,7 @@ void PvaClientRPC::issueConnect()
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ channelName
+ " pvaClientRPC already connected ";
throw std::runtime_error(message);
}
@@ -307,10 +307,18 @@ PVStructure::shared_pointer PvaClientRPC::request(PVStructure::shared_pointer co
string message = "channel "
+ channelName
+ " PvaClientRPC::request request timeout ";
throw std::runtime_error(message);
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
}
rpcState = rpcIdle;
return pvResponse;
if(requestStatus.isOK()) return pvResponse;
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = "channel "
+ channelName
+ " PvaClientRPC::request status ";
message += requestStatus.getMessage();
throw RPCRequestException(Status::STATUSTYPE_ERROR,message);
}
@@ -318,7 +326,7 @@ void PvaClientRPC::request(
PVStructure::shared_pointer const & pvArgument,
PvaClientRPCRequesterPtr const & pvaClientRPCRequester)
{
checkRPCState();
checkRPCState();
this->pvaClientRPCRequester = pvaClientRPCRequester;
if(responseTimeout<=0.0) {
{