Merge pull request #43 from mrkraimer/new-pva-api

New pva api
This commit is contained in:
Marty Kraimer
2017-07-18 13:36:04 -04:00
committed by GitHub
28 changed files with 2038 additions and 496 deletions

View File

@@ -21,29 +21,3 @@ It can also be built by:
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.

View File

@@ -1,5 +1,49 @@
EPICS V4 release 4.7
====================
Works with release/7.0 of pvDataCPP and release/6.0 of pvAccessCPP
------------------------------------------------------------------
Will not work with older versions.
destroy methods removed
-----------------------
All the destroy methods are removed since 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
);
EPICS V4 release 4.6
==========================
====================
* The examples are moved to exampleCPP.
* Support for channelRPC is now available.
@@ -8,7 +52,7 @@ EPICS V4 release 4.6
EPICS V4 release 4.5
==========================
====================
pvaClient is a synchronous API for pvAccess.

View File

@@ -0,0 +1,5 @@
NOT FOR DIRECT USE
==================
This directory holds files that are used by doxygen.
The files are not meant to be read except via the doxygen documention.

View File

@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClient</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClient</h1>
<h2>Overview</h2>
<p>
pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API.
Thus it is easier to use than pvAccess itself.
In addition pvaClient provides many convenience methods.
</p>
<p>
Class <b>PvaClient</b> is a class that is used by all the other pvaClient classes.
An application that uses pvaClient must call:</p>
<pre>
PvaClientPtr pvaClient = PvaClient::get(providers);
</pre>
<p>
before it uses any other pvaClient classes.
</p>
<p>
This is a singleton method, i. e. only one instance of PvaClient is created.
</p>
<p>
<b>pvaClient</b> must not be deleted until the client no longer wants to use any part
of pvaClient.
</p>
<p>
<b>providers</b> is a blank separated set of provider names.
For example:</p>
<pre>
PvaClientPtr pvaClient = PvaClient::get("ca pva");
</pre>
<p>
The providers <b>ca</b> and <b>pva</b> are special.
For each of these a client context is created when the <b>PvaClient</b>
is constructed and the context destroyed when <b>PvaClient</b> is deleted.
</p>
<h2>Channel Caching</h2>
<p>
<b>PvaClient</b> has a method:
</p>
<pre>
PvaClientChannelPtr channel(
string const &amp; channelName,
string const &amp;providerName = "pva",
double timeOut = 5.0);
</pre>
<p>
This method creates a
<b>PvaClientChannel</b> and then connects to the channel.
</p>
<p>
If a call is successful then multiple calls to the same channelName and providerName
share the same PvaClientChannel, i. e. the PvaClientChannel is cached.
</p>
<p>
<b>pvaClientChannelGet</b> and <b>pvaClientChannelPut</b> also implement caching.
</p>
<p>
For example consider a client that makes multiple calls like:
</p>
<pre>
double value;
value = pva->channel(channelName)->get()->getData()->getDouble();
...
value = pva->channel(channelName)->get()->getData()->getDouble();
</pre>
<p>
Only the first call creates a new PvaClientChannel and a new PvaClientGet.
The second call reuses the cached PvaClientChannel and PvaClientGet.
</p>
<h2>Non Cached Channels</h2>
<p>
<b>PvaClient</b> has a method:
</p>
<pre>
PvaClientChannelPtr createChannel(
string const &amp; channelName,
string const &amp;providerName = "pva");
</pre>
<p>
This method is just creates a new PvaClientChannel and returns it to the caller.
The caller must call the PvaClientChannel connect methods.
</p>
<h2>Blocking vs Non-Blocking Methods</h2>
<p>Each component of pvaClient provides a set of blocking and non-blocking calls.
For example several components (examples are <b>PvaClientChannel</b> and <b>PvaChannelGet</b>)
have methods:</p>
<dl>
<dt>connect</dt>
<dd>
This calls issueConnect and then waitConnect.
If waitConnect fails an exception is thrown.
Since waitConnect is a blocking method so is this.
</dd>
<dt>issueConnect</dt>
<dd>
This is a request to connect, i. e. issue a request to the server to create something
on the server. This is a non blocking call.
</dd>
<dt>waitConnect</dt>
<dd>
This waits for the server to respond to issueConnect.
It blocks until the server responds or a timeout occurs.
</dd>
</dl>
</body>
</html>

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientChannel</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientChannel</h1>
<h2>Overview</h2>
<p>
pvaClientChannel is a synchronous wrapper for the pvAccess::Channel API, which is a callback based API.
Thus it is easier to use than pvAccess::Channel itself.
</p>
<p>An instance of <b>PvaClientChannel</b> connects to a single channel.
An instance can only be created via class <b>PvaClient</b> which has both synchronous methods, which block, and non blocking methods.
The synchrouous methods block until a connection is made to the channel and throw an exception if a
timeout occurs while trying to make a connection.
The non blocking methods leave connection to the caller.
</p>
<p><b>PvaClientChannel</b> has methods:</p>
<dl>
<dt>Connect to channel</dt>
<dd>These can be called indirectly by a blocking request to <b>PvaClient</b>
or by the client if a non blocking request is made to <b>PvaClient</b>.
</dd>
<dt>Channel state change requester</dt>
<dd>The client can provide a callback that is called each time the connection state
of the channel changes.
</dd>
<dt>Creating all of the following</dt>
<dd>
<pre>
PvaClientField NOT IMPLEMENTED
PvaClientProcess
PvaClientGet
PvaClientPut
PvaClientPutGet
PvaClientMonitor
PvaClientArray NOT IMPLEMENTED
PvaClientRPC
</pre>
</dd>
</dl>
<h2>Connect: Blocking vs Non-Blocking </h2>
<p><b>PvaClientChannel</b> has methods:</p>
<dl>
<dt>connect</dt>
<dd>
This calls issueConnect and then waitConnect.
If waitConnect fails an exception is thrown.
Since waitConnect is a blocking method so is this.
</dd>
<dt>issueConnect</dt>
<dd>
This is a request to connect to the channel. This is a non blocking call.
</dd>
<dt>waitConnect</dt>
<dd>
This waits for the server to respond to issueConnect.
It blocks until the server responds or a timeout occurs.
</dd>
</dl>
<h2>Get and Put Caching</h2>
<p>
<b>PvaClientChannel</b> has methods:
</p>
<pre>
PvaClientGetPtr get(std::string const &amp; request);
PvaClientPutPtr put(std::string const &amp; request);
</pre>
<p>
Each of these caches.
For example all calls to <b>get</b> with the same <b>request</b> will share the same
<b>PvaChannelGet</b>
</p>
<p>
For example consider a client that makes multiple calls like:
</p>
<pre>
double value;
value = pva->channel(channelName)->get()->getData()->getDouble();
...
value = pva->channel(channelName)->get()->getData()->getDouble();
</pre>
<p>
Only the first call creates a new PvaClientChannel and a new PvaClientGet.
The second call reuses the cached PvaClientChannel and PvaClientGet.
</p>
</body>
</html>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientChannelStateChangeRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientChannelStateChangeRequester</h1>
<p>This class has the single method <b>channelStateChange</b>.
It is called each time the channel connection status changes.
</p>
<p>
<b>NOTE:</b>
The implementation must not call a method that blocks waiting for a response from the server.
It it does the client may be blocked forever.
</p>
<p>
An example of illegal code is:
</p>
<pre>
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
{
if(isConnected&&!pvaClientPut)
{
pvaClientPut = pvaClientChannel->createPut(request);
pvaClientPut->connect();
}
}
</pre>
<p>
This is illegal because the call to <b>connect</b> blocks.
</p>
<p>The following is an example of legal code:
</p>
<pre>
virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
{
if(isConnected&&!pvaClientPut)
{
pvaClientPut = pvaClientChannel->createPut(request);
pvaClientPut->issueConnect();
}
}
</pre>
<p>This is legal code because neither <b>createPut</b> or <b>issueConnect</b>
blocks.
</p>
</body>
</html>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientGet</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientGet</h1>
<p>
pvaClientGet is a synchronous wrapper for the pvAccess::ChannelGet API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelGet itself.
</p>
<p>An instance of PvaClientGet is created via a call to one of the following:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientGetPtr get(std::string const &amp; request = "field(value,alarm,timeStamp)");
PvaClientGetPtr createGet(std::string const &amp; request = "");
PvaClientGetPtr createGet(epics::pvData::PVStructurePtr const &amp; pvRequest);
...
};
<p>An instance of <b>PvaClientGet</b> connects to a single channel.
<b>PvaClientGet</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientChannel</b> has methods:</p>
<pre>
connect Calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
get Calls issueGet and then waitGet.
issueGet issues a get request to the server.
waitGet waits until the server send a message that the get is complete.
getData get the data.
</pre>
<p>
<b>issueConnect</b> and <b>issueGet</b> do not block.
All other methods can block.
</p>
</body>
</html>

View File

@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientGetData</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientGetData</h1>
<p>This class provides access to the data returned by calls to get data via <b>PvaChannelGet</b>
It provides methods:</p>
<pre>
getStructure Get the introspection interface for data returned from server
getPVStructure Get the complete set of data returned from the server.
getChangedBitSet Get the bitSet that shows which fields have a new value since last get.
showChanged Show all the fields that have changed value since the last get,
getAlarm If a alarm field is available get it.
getTimeStamp If a timeStamp field is available get it.
hasValue Does the PVStructure have a top level field named value
NOTE: The following only apply if hasValue is true.
isValueScalar Is the value field a scalar?
isValueScalarArray Is the value field a scalar array?
getValue Get the value field.
getScalarValue Get a scalar value field.
getArrayValue Get an array value field.
getScalarArrayValue Get a scalar array value field.
getDouble Get scalar value field as a double.
getString Get value field as a string.
getDoubleArray Get value field as a double array.
getStringArray Get value field as a string array.
</pre>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientGetRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientGetRequester</h1>
<p>
<b>Not Yet Written</b>
</p>
</body>
</html>

View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientMonitor</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientMonitor</h1>
<p>
<b>NOTE:</b> This is a work in progress.
</p>
<h2>Overview</h2>
<p>
This provides an easier way to create a monitor on a channel than to use pvAccessCPP itself.
It provides two main ways to create a monitor:
</p>
<h3>The client first creates a PvaClientMonitorChannel and then creates a monitor</h3>
The client calls:
<pre>
static PvaClientMonitorPtr create(
PvaClientMonitorPtr const &amp;PvaClientMonitor,
PvaClientMonitorChannelPtr const &amp; PvaClientMonitorChannel,
epics::pvData::PVStructurePtr const &amp;pvRequest
);
where
PvaClientMonitor
The PvaClientMonitor.
PvaClientMonitorChannel
The PvaClientMonitorChannel that has already been created by the client.
pvRequest
The pvRequest for creating the monitor.
</pre>
With this method the monitor is created and started.
This method blocks while the monitor is created.
<h3>The client provides names for a channel and a provider</h3>
The client calls:
<pre>
static PvaClientMonitorPtr create(
PvaClientMonitorPtr const &amp;PvaClientMonitor,
std::string const &amp; channelName,
std::string const &amp; providerName,
std::string const &amp; request,
PvaClientMonitorChannelStateChangeRequesterPtr const &amp; stateChangeRequester,
PvaClientMonitorRequesterPtr const &amp; monitorRequester
);
where
PvaClientMonitor
The PvaClientMonitor.
channelName
The name of the channel.
providerName
The name of the provider
request
The request for creating the monitor
stateChangeRequester
The client supplied state change requester.
This will be called each time a state change for the channel occurs.
monitorRequester
The client supplied monitor requester.
This is called each time a new monitor event is available.
</pre>
With this method a pvaChannel is created and after it connects a pvaMonitor is created and started.
This method never blocks.
</body>
</html>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientMonitorData</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientMonitorData</h1>
<p>This class provides access to the data returned by calls to get data via <b>PvaChannelGet</b>
It provides methods:</p>
<pre>
getStructure Get the introspection interface for data returned from server
getPVStructure Get the complete set of data returned from the server.
getChangedBitSet Get the bitSet that shows which fields have a new value since last monitor event.
getOverrunBitSet Get the bitSet that shows which fields have changed more than once since last monitor event.
showChanged Show all the fields that have changed value since the last monitor event,
showChanged Show all the fields that have changed value more than once since last monitor event.
getAlarm If a alarm field is available get it.
getTimeStamp If a timeStamp field is available get it.
hasValue Does the PVStructure have a top level field named value
NOTE: The following only apply if hasValue is true.
isValueScalar Is the value field a scalar?
isValueScalarArray Is the value field a scalar array?
getValue Get the value field.
getScalarValue Get a scalar value field.
getArrayValue Get an array value field.
getScalarArrayValue Get a scalar array value field.
getDouble Get scalar value field as a double.
getString Get value field as a string.
getDoubleArray Get value field as a double array.
getStringArray Get value field as a string array.
</pre>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientMonitorRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientMonitorRequester</h1>
<p>
<b>Not Yet Written</b>
</p>
</body>
</html>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientProcess</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientProcess</h1>
<p>
pvaClientProcess is a synchronous wrapper for the pvAccess::ChannelProcess API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelProcess itself.
</p>
<p>An instance of PvaClientProcess is created via a call to one of the followimg:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientProcessPtr createProcess(std::string const &amp; request = "");
PvaClientProcessPtr createProcess(epics::pvData::PVStructurePtr const &amp; pvRequest);
...
};
<p>An instance of <b>PvaClientProcess</b> connects to a single channel.
<b>PvaClientProcess</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientChannel</b> has methods:</p>
<pre>
connect Calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
process Calls issueProcess and then waitProcess.
issueProcess issues a process request to the server.
waitProcess waits until the server send a message that the process is complete.
</pre>
<p>
<b>issueConnect</b> and <b>issueProcess</b> do not block.
All other methods can block.
</p>
</body>
</html>

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientChannelPut</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientChannelPut</h1>s
<p>
pvaClientPut is a synchronous wrapper for the pvAccess::ChannelPut API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelPut itself.
</p>
<p>
<b>NOTE:</b>
Except for union fields pvaClientPut takes care of modifying the bitSet associated with
the data sent to the server.
</p>
<p>An instance of PvaClientPut is created via a call to one of the followimg:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientPutPtr put(std::string const & request = "field(value,alarm,timeStamp)");
PvaClientPutPtr createPut(std::string const & request = "");
PvaClientPutPtr createPut(epics::pvData::PVStructurePtr const & pvRequest);
...
};
<p>An instance of <b>PvaClientPut/b> connects to a single channel.
<b>PvaClientPut</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientPut</b> has methods:</p>
<pre>
connect Calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
get Calls issueGet and then waitGet.
issueGet issues a request to the server to get the latest data.
waitGet waits until the server send a message that the get is complete.
put Calls issuePut and then waitPut.
issuePut issues a put request to the server.
waitPut waits until the server send a message that the put is complete.
getData get the data.
</pre>
<p>
Note that <b>issueConnect</b>, <b>issueGet</b> and <b>issuePut</b> do not block but all other methods
do block.
</p>
</body>
</html>

View File

@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientPutData</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientPutData</h1>
<p>This class provides access to data to send to the server via a <b>PvaChannelPut</b>
It is created by <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b>.
This the client only gets access to an instance by getting it from <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b>.
<p>
<p>Note also that for all field types except <b>union</b> the <b>BitSet</b> for the data is updated
by <b>PvaChannelPut</b> or <b>PvaChannelPutGet</b> whenever the client changes a field.
For a <b>union</b> or <b>unionArray</b> field the client must update the <b>BitSet</b>.
</p>
<p>
PvaClientPutData provides methods:</p>
<pre>
getStructure Get the introspection interface for data sent to server
getPVStructure Get the complete set of data sent to the server.
getChangedBitSet Get the bitSet that shows which fields have a new value since last get.
showChanged Show all the fields that have changed value since the last get,
getAlarm If a alarm field is available get it.
getTimeStamp If a timeStamp field is available get it.
hasValue Does the PVStructure have a top level field named value
NOTE: The following only apply if hasValue is true.
isValueScalar Is the value field a scalar?
isValueScalarArray Is the value field a scalar array?
getValue Get the value field.
getScalarValue Get a scalar value field.
getArrayValue Get an array value field.
getScalarArrayValue Get a scalar array value field.
getDouble Get scalar value field as a double.
getString Get value field as a string.
getDoubleArray Get value field as a double array.
getStringArray Get value field as a string array.
putDouble Put scalar value field as a double.
putString Put value field as a string.
putDoubleArray Put value field as a double array.
putStringArray Put value field as a string array.
</pre>
</body>
</html>

View File

@@ -0,0 +1,85 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientPutGetGet</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientPutGetGet</h1>
<p>
pvaClientPutGet is a synchronous wrapper for the pvAccess::ChannelPutGet API, which is a callback based API.
Thus it is easier to use than pvAccess::ChannelPut itself.
</p>
<p>
<b>NOTE:</b>
Except for union fields pvaClientPutGet takes care of modifying the bitSet associated with
the data sent to the server.
</p>
<p>An instance of PvaClientPutGet is created via a call to one of the followimg:</p>
<pre>
class PvaClientChannel
...
{
...
PvaClientPutGetPtr createPutGet(std::string const &amp; request);
PvaClientPutGetPtr createPutGet(epics::pvData::PVStructurePtr const &amp; pvRequest);
...
};
<p>An instance of <b>PvaClientPutGet</b> connects to a single channel.
<b>PvaClientPutGet</b> has both synchronous methods, which block, and non blocking methods.
</p>
<p><b>PvaClientPutGet</b> has methods:</p>
<pre>
connect calls issueConnect and then waitConnect.
issueConnect issues a request to the server to create the server side of ChannelPut.
waitConnect blocks until server responds that it has created the ChannelPut.
putGet call issuePutGet and then waitPutGet.
issuePutGet issue a putGet and return immediately.
waitPutGet wait until putGet completes.
getGet calls issueGetGet and then waitGetGet.
issueGetGet issues a request to the server to get the latest data for the get data.
waitGetGet waits until the server send a message that the getGet is complete.
getPut calls issueGetPut and then waitGetPut.
issueGetPut issues a request to the server to get the latest data for the put data.
waitGetPut waits until the server send a message that the getPut is complete.
getPutData get the put portion of the data.
getGetData get the get portion of the data.
</pre>
<p>
<b>issueConnect</b>, <b>issuePutGet</b>, <b>issueGetGet</b> and <b>issueGetPut</b> do not block.
All other methods can block.
</p>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientPutRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientPutRequester</h1>
<p>
<b>Not Yet Written</b>
</p>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientRPC</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientRPC</h1>
<p>
<b>Not Yet Written</b>
</p>
</body>
</html>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>PvaClientRPCRequester</title>
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/base.css" />
<link rel="stylesheet" type="text/css"
href="http://epics-pvdata.sourceforge.net/epicsv4.css" />
<style type="text/css">
/*<![CDATA[*/
.about { margin-left: 3em; margin-right: 3em; font-size: .83em}
table { margin-left: auto; margin-right: auto }
.diagram { text-align: center; margin: 2.5em 0 }
span.opt { color: grey }
span.nterm { font-style:italic }
span.term { font-family:courier }
span.user { font-family:courier }
span.user:before { content:"<" }
span.user:after { content:">" }
.nonnorm { font-style:italic }
p.ed { color: #AA0000 }
span.ed { color: #AA0000 }
p.ed.priv { display: inline; }
span.ed.priv { display: inline; }
/*]]>*/</style>
<!-- Script that generates the Table of Contents -->
<script type="text/javascript"
src="http://epics-pvdata.sourceforge.net/script/tocgen.js">
</script>
</head>
<body>
<h1>PvaClientRPCRequester</h1>
<p>
<b>Not Yet Written</b>
</p>
</body>
</html>

View File

@@ -26,11 +26,11 @@
<div class="head">
<h1>EPICS pvaClientCPP</h1>
<h2 class="nocount">Release 4.2.0-SNAPSHOT - 2016-07-14</h2>
<h2 class="nocount">Release 4.7.0-SNAPSHOT - 2017-06-29</h2>
<h2 class="nocount">Abstract</h2>
<p>pvaClient is a software library that provides to an EPICS client programmer, a friendly
<p>pvaClient is a software library that provides, to an EPICS client programmer, a friendly
client side programming interface to the data of an EPICS based control system. It is intended
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>
@@ -62,11 +62,6 @@ 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">
<hr />
<h2>Overview</h2>
@@ -76,10 +71,10 @@ pvaClientCPP is one of the components of
EPICS Version 4
</a>
</p>
<p>This document is only a guide to help locate code and documentation related to pvDatabaseCPP
<p>This document is only a guide to help locate code and documentation related to pvaClientCPP
</p>
<p>
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
@@ -88,14 +83,11 @@ href="http://epics-pvdata.sourceforge.net/informative/developerGuide/developerGu
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 +96,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>

View File

@@ -31,7 +31,7 @@ LIBSRCS += pvaClientNTMultiGet.cpp
LIBSRCS += pvaClientNTMultiMonitor.cpp
LIBSRCS += pvaClientRPC.cpp
pvaClient_LIBS += pvAccess nt pvData Com
pvaClient_LIBS += pvAccessCA pvAccess nt pvData Com
pvaClient_LIBS += $(EPICS_BASE_IOC_LIBS)
include $(TOP)/configure/RULES

View File

@@ -3,6 +3,10 @@
* EPICS pvData is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
*/
/**
* @author mrk
* @date 2015.02
*/
#ifndef PVACLIENT_H
#define PVACLIENT_H
@@ -13,7 +17,7 @@
#include <list>
#include <iostream>
#include <compilerDependencies.h>
#include <sstream>
#include <pv/requester.h>
#include <pv/status.h>
#include <pv/event.h>
@@ -37,7 +41,6 @@
#include <shareLib.h>
namespace epics { namespace pvaClient {
class PvaClient;
@@ -57,8 +60,14 @@ class PvaClientField;
typedef std::tr1::shared_ptr<PvaClientField> PvaClientFieldPtr;
class PvaClientProcess;
typedef std::tr1::shared_ptr<PvaClientProcess> PvaClientProcessPtr;
class PvaClientGetRequester;
typedef std::tr1::shared_ptr<PvaClientGetRequester> PvaClientGetRequesterPtr;
typedef std::tr1::weak_ptr<PvaClientGetRequester> PvaClientGetRequesterWPtr;
class PvaClientGet;
typedef std::tr1::shared_ptr<PvaClientGet> PvaClientGetPtr;
class PvaClientPutRequester;
typedef std::tr1::shared_ptr<PvaClientPutRequester> PvaClientPutRequesterPtr;
typedef std::tr1::weak_ptr<PvaClientPutRequester> PvaClientPutRequesterWPtr;
class PvaClientPut;
typedef std::tr1::shared_ptr<PvaClientPut> PvaClientPutPtr;
class PvaClientPutGet;
@@ -83,10 +92,7 @@ typedef std::tr1::shared_ptr<PvaClientChannelCache> PvaClientChannelCachePtr;
/**
* @brief pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API.
*
* Thus it is easier to use than pvAccess itself.
* In addition pvaClient provides many convenience methods.
* @author mrk
* @date 2015.02
* <a href = "../htmldoxygen/pvaClient.html">Overview of PvaClient</a>
*/
class epicsShareClass PvaClient :
public epics::pvData::Requester,
@@ -99,18 +105,11 @@ public:
*/
~PvaClient();
/** @brief Get the single instance of PvaClient.
*
* @param providerNames Space separated list of provider names.
* @return shared pointer to the single instance.
*/
static PvaClientPtr get(std::string const & providerNames = "pva ca");
/** @brief Create an instance of PvaClient with providerName "pva ca".
* \deprecated This method will go away in future versions. Use get instead.
* @return shared pointer to the single instance
*/
static PvaClientPtr create() EPICS_DEPRECATED
{
return get();
}
/** @brief Get the requester name.
* @return The name.
*/
@@ -126,6 +125,7 @@ public:
std::string const & message,
epics::pvData::MessageType messageType);
/** @brief Get a cached channel or create and connect to a new channel.
*
* @param channelName The channelName.
* @param providerName The providerName.
* @param timeOut The number of seconds to wait for connection. 0.0 means forever.
@@ -137,6 +137,7 @@ public:
std::string const &providerName = "pva",
double timeOut = 5.0);
/** @brief Create an PvaClientChannel with the specified provider.
*
* @param channelName The channelName.
* @param providerName The provider.
* @return The interface.
@@ -161,20 +162,16 @@ public:
/** @brief Get the number of cached channels.
*/
size_t cacheSize();
/** Should debug info be shown?
/** @brief Should debug info be shown?
*
* @param value true or false
*/
static void setDebug(bool value) {debug = value;}
/** @brief Is debug set?
*
* @return true or false
*/
static bool getDebug() {return debug;}
/** @brief Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
static bool debug;
PvaClient(std::string const & providerNames);
@@ -183,6 +180,7 @@ private:
bool pvaStarted;
bool caStarted;
epics::pvData::Mutex mutex;
epics::pvAccess::ChannelProviderRegistry::shared_pointer channelRegistry;
};
// folowing private to PvaClientChannel
@@ -191,15 +189,12 @@ typedef std::tr1::shared_ptr<PvaClientGetCache> PvaClientGetCachePtr;
class PvaClientPutCache;
typedef std::tr1::shared_ptr<PvaClientPutCache> PvaClientPutCachePtr;
// NOTE: must use separate class that implements ChannelRequester,
// because pvAccess holds a shared_ptr to ChannelRequester instead of weak_pointer
class ChannelRequesterImpl;
typedef std::tr1::shared_ptr<ChannelRequesterImpl> ChannelRequesterImplPtr;
/**
* @brief A callback for change in connection status.
*
* @author mrk
* <a href = "../htmldoxygen/pvaClientChannelStateChangeRequester.html">Overview of PvaClientChannelStateChangeRequester</a>
*
*/
class PvaClientChannelStateChangeRequester
{
@@ -211,6 +206,8 @@ public:
virtual ~PvaClientChannelStateChangeRequester(){}
/**
* @brief A channel connection state change has occurred.
*
* <b>Warning</b> A call to a method that blocks should not be made by this method.
* @param channel The channel.
* @param isConnected The new connection status.
*/
@@ -220,10 +217,11 @@ public:
/**
* @brief An easy to use alternative to directly calling the Channel methods of pvAccess.
*
* @author mrk
* <a href = "../htmldoxygen/pvaClientChannel.html">Overview of PvaClientChannel</a>
*/
class epicsShareClass PvaClientChannel :
public epics::pvAccess::ChannelRequester,
public std::tr1::enable_shared_from_this<PvaClientChannel>
{
public:
@@ -232,12 +230,18 @@ public:
* @brief Destructor
*/
~PvaClientChannel();
/** @brief Set a client stateChangeRequester.
*
* @param stateChangeRequester The client stateChangeRequester implementation.
*/
void setStateChangeRequester(PvaClientChannelStateChangeRequesterPtr const &stateChangeRequester);
/** @brief Get the name of the channel to which PvaClientChannel is connected.
*
* @return The channel name.
*/
std::string getChannelName();
/** @brief Get the the channel to which PvaClientChannel is connected.
*
* @return The channel interface.
*/
epics::pvAccess::Channel::shared_pointer getChannel();
@@ -249,50 +253,53 @@ public:
*/
void connect(double timeout=5.0);
/** @brief Issue a connect request and return immediately.
*
*/
void issueConnect();
/** @brief Wait until the connection completes or for timeout.
*
* @param timeout The time in seconds to wait. A value of 0 means forever.
* @return status.
* @throw runtime_error if failure.
*/
epics::pvData::Status waitConnect(double timeout = 5.0);
/** @brief Create a PvaClientField for the specified subField.
*
* @param subField The desired subField, i. e. "field.field...."
* An empty string, i. e. "", asks for the entire top level struture as defined by the server.
* @return The interface.
*/
PvaClientFieldPtr createField(std::string const & subField = "");
/** @brief First call createRequest as implemented by pvDataCPP and then call the next method.
*
* @param request The syntax of request is defined by the copy facility of pvData.
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientProcessPtr createProcess(std::string const & request = "");
/** Creates an PvaClientProcess.
/** Creates a PvaClientProcess.
*
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientProcessPtr createProcess(epics::pvData::PVStructurePtr const & pvRequest);
/** @brief Get a cached PvaClientGet or create and connect to a new PvaClientGet.
/** @brief create a PvaChannelGet
*
* If connection can not be made an exception is thrown.
* @param request The syntax of request is defined by the copy facility of pvData.
* Get a cached PvaClientGet or create and connect to a new PvaClientGet.
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientGetPtr get(std::string const & request = "field(value,alarm,timeStamp)");
/** @brief create a PvaClientGet.
*
* First call createRequest as implemented by pvDataJava and then call the next method.
* Then get a cached PvaClientGet or create and connect to a new PvaClientGet.
* First call createRequest as implemented by pvData and then call the next method.
* @param request The syntax of request is defined by the copy facility of pvData.
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientGetPtr createGet(std::string const & request = "field(value,alarm,timeStamp)");
/** @brief Creates an PvaClientGet.
*
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
* @return The interface.
* @throw runtime_error if failure.
@@ -300,8 +307,7 @@ public:
PvaClientGetPtr createGet(epics::pvData::PVStructurePtr const & pvRequest);
/** @brief create a PvaClientPut.
*
* First call createRequest as implemented by pvDataJava.
* Then get a cached PvaClientPut or create and connect to a new PvaClientPut.
* Get a cached PvaClientPut or create and connect to a new PvaClientPut.
* Then call it's get method.
* @param request The syntax of request is defined by the copy facility of pvData.
* @return The interface.
@@ -317,6 +323,7 @@ public:
*/
PvaClientPutPtr createPut(std::string const & request = "field(value)");
/** @brief Create a PvaClientPut.
*
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
* @return The interface.
*/
@@ -331,6 +338,7 @@ public:
PvaClientPutGetPtr createPutGet(
std::string const & request = "putField(argument)getField(result)");
/** @brief Create a PvaClientPutGet.
*
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
* @return The interface.
*/
@@ -360,6 +368,7 @@ public:
*/
PvaClientMonitorPtr monitor(std::string const & request = "field(value,alarm,timeStamp)");
/** @brief Call the next method with request = "field(value,alarm,timeStamp)"
*
* @param pvaClientMonitorRequester The client callback.
* @return The interface.
* @throw runtime_error if failure.
@@ -378,7 +387,8 @@ public:
std::string const & request,
PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester);
/**
* @brief First call createRequest as implemented by pvDataJava and then calls the next method.
* @brief First call createRequest as implemented by pvDataJava and then call the next method.
*
* @param request The syntax of request is defined by the copy facility of pvData.
* @return The interface.
* @throw runtime_error if failure.
@@ -387,11 +397,13 @@ public:
std::string const & request = "field(value,alarm,timeStamp)");
/** Create an PvaClientMonitor.
* @param pvRequest The syntax of pvRequest is defined by the copy facility of pvData.
*
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientMonitorPtr createMonitor(epics::pvData::PVStructurePtr const & pvRequest);
/** @brief Issue a channelRPC request
*
* @param pvRequest The pvRequest that is passed to createRPC.
* @param pvArgument The argument for a request.
* @return The result.
@@ -401,6 +413,7 @@ public:
epics::pvData::PVStructurePtr const & pvRequest,
epics::pvData::PVStructurePtr const & pvArgument);
/** @brief Issue a channelRPC request
*
* @param pvArgument The argument for the request.
* @return The result.
* @throw runtime_error if failure.
@@ -408,11 +421,13 @@ public:
epics::pvData::PVStructurePtr rpc(
epics::pvData::PVStructurePtr const & pvArgument);
/** @brief Create a PvaClientRPC.
*
* @return The interface.
* @throw runtime_error if failure.
*/
PvaClientRPCPtr createRPC();
/** @brief Create a PvaClientRPC.
*
* @param pvRequest The pvRequest that must have the same interface
* as a pvArgument that is passed to an rpc request.
* @return The interface.
@@ -425,23 +440,7 @@ public:
/** @brief Get the number of cached gets and puts.
*/
size_t cacheSize();
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
//ChannelRequester methods
void channelCreated(
const epics::pvData::Status& status,
epics::pvAccess::Channel::shared_pointer const & channel);
void channelStateChange(
epics::pvAccess::Channel::shared_pointer const & channel,
epics::pvAccess::Channel::ConnectionState connectionState);
std::string getRequesterName();
void message(
std::string const & message,
epics::pvData::MessageType messageType);
static PvaClientChannelPtr create(
PvaClientPtr const &pvaClient,
std::string const & channelName,
@@ -465,16 +464,24 @@ private:
epics::pvData::Mutex mutex;
epics::pvData::Event waitForConnect;
epics::pvAccess::Channel::shared_pointer channel;
epics::pvAccess::ChannelProvider::shared_pointer channelProvider;
PvaClientChannelStateChangeRequesterWPtr stateChangeRequester;
ChannelRequesterImplPtr channelRequester;
public:
virtual std::string getRequesterName();
virtual void message(std::string const & message, epics::pvData::MessageType messageType);
virtual void channelCreated(
const epics::pvData::Status& status,
epics::pvAccess::Channel::shared_pointer const & channel);
virtual void channelStateChange(
epics::pvAccess::Channel::shared_pointer const & channel,
epics::pvAccess::Channel::ConnectionState connectionState);
friend class PvaClient;
friend class ChannelRequesterImpl;
};
/**
* @brief A class that holds data returned by PvaClientGet or PvaClientPutGet
*
* <a href = "../htmldoxygen/pvaClientGetData.html">Overview of PvaClientGetData</a>
*/
class epicsShareClass PvaClientGetData
{
@@ -491,11 +498,13 @@ public:
*/
void setMessagePrefix(std::string const & value);
/** @brief Get the structure.
*
* @return The Structure
* @throw runtime_error if failure.
*/
epics::pvData::StructureConstPtr getStructure();
/** @brief Get the pvStructure.
*
* @return the pvStructure.
* @throw runtime_error if failure.
*/
@@ -508,6 +517,7 @@ public:
*/
epics::pvData::BitSetPtr getChangedBitSet();
/** @brief Show the fields that have changed value since the last get.
*
* @param out The stream that shows the changed fields.
* @return The stream that was passed as out.
*/
@@ -613,6 +623,7 @@ class PvaClientPostHandlerPvt; // private to PvaClientPutData
/**
* @brief A class that holds data given to by PvaClientPut or PvaClientPutGet
*
* <a href = "../htmldoxygen/pvaClientPutData.html">Overview of PvaClientPutData</a>
*/
class epicsShareClass PvaClientPutData
{
@@ -623,36 +634,43 @@ public:
*/
~PvaClientPutData() {}
/** @brief Set a prefix for throw messages.
*
* @param value The prefix.
*/
void setMessagePrefix(std::string const & value);
/** @brief Get the structure.
* @return The Structure
* @throw runtime_error if failure.
*/
epics::pvData::StructureConstPtr getStructure();
*
* @return The Structure
* @throw runtime_error if failure.
*/
epics::pvData::StructureConstPtr getStructure();
/** @brief Get the pvStructure.
*
* @return the pvStructure.
* @throw runtime_error if failure.
*/
epics::pvData::PVStructurePtr getPVStructure();
/** @brief Get the changed BitSet for the pvStructure
*
* This shows which fields have changed values.
* @return The bitSet
* @throw runtime_error if failure.
*/
epics::pvData::BitSetPtr getChangedBitSet();
/** @brief Show the fields that have changed values.
*
* @param out The stream that shows the changed fields.
* @return The stream that was passed as out.
*/
std::ostream & showChanged(std::ostream & out);
/**
* @brief Is there a top level field named value.
*
* @return The answer.
*/
bool hasValue();
/** @brief Is the value field a scalar?
*
* @return The answer.
*/
bool isValueScalar();
@@ -661,10 +679,12 @@ public:
*/
bool isValueScalarArray();
/** Get the interface to the value field.
*
* @return The interface. an excetion is thrown if a value field does not exist.
*/
epics::pvData::PVFieldPtr getValue();
/** @brief Get the interface to a scalar value field.
*
* @return The interface for a scalar value field.
* @throw runtime_error if failure.
*/
@@ -751,6 +771,7 @@ private:
/**
* @brief A class that holds data returned by PvaClientMonitor
*
* <a href = "../htmldoxygen/pvaClientMonitorData.html">Overview of PvaClientMonitorData</a>
*/
class epicsShareClass PvaClientMonitorData
{
@@ -908,7 +929,7 @@ typedef std::tr1::shared_ptr<ChannelProcessRequesterImpl> ChannelProcessRequeste
/**
* @brief An easy to use alternative to ChannelProcess.
*
* @author mrk
* <a href = "../htmldoxygen/pvaClientProcess.html">Overview of PvaClientProcess</a>
*/
class epicsShareClass PvaClientProcess
{
@@ -925,6 +946,7 @@ public:
epics::pvAccess::Channel::shared_pointer const & channel,
epics::pvData::PVStructurePtr const &pvRequest
);
/** @brief Destructor
*/
~PvaClientProcess();
@@ -948,17 +970,13 @@ public:
* An exception is thrown if get fails.
*/
void process();
/** @brief Issue a process and return immediately.
/** @brief Issue a process request and return immediately.
*/
void issueProcess();
/** @brief Wait until process completes.
* @return status.
*/
epics::pvData::Status waitProcess();
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
std::string getRequesterName();
void message(std::string const & message,epics::pvData::MessageType messageType);
@@ -999,29 +1017,82 @@ private:
// because pvAccess holds a shared_ptr to ChannelGetRequester instead of weak_pointer
class ChannelGetRequesterImpl;
typedef std::tr1::shared_ptr<ChannelGetRequesterImpl> ChannelGetRequesterImplPtr;
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientGetRequester.html">Overview of PvaClientGetRequester</a>
*/
class PvaClientGetRequester
{
public:
POINTER_DEFINITIONS(PvaClientGetRequester);
virtual ~PvaClientGetRequester() {}
/** @brief A channelGet has connected.
*
* @param status The status returned by the server.
* @param clientGet The PvaClientGet that issued the request to create a ChannelGet.
*/
virtual void channelGetConnect(
const epics::pvData::Status& status,
PvaClientGetPtr const & clientGet);
/** @brief A get request is complete.
*
* @param status The status returned by the server.
* @param clientGet The PvaClientGet that issued the request to create a ChannelGet.
*/
virtual void getDone(
const epics::pvData::Status& status,
PvaClientGetPtr const & clientGet);
};
/**
* @brief An easy to use alternative to ChannelGet.
*
* @author mrk
* <a href = "../htmldoxygen/pvaClientGet.html">Overview of PvaClientGet</a>
*/
class epicsShareClass PvaClientGet
class epicsShareClass PvaClientGet :
public PvaClientChannelStateChangeRequester,
public std::tr1::enable_shared_from_this<PvaClientGet>
{
public:
POINTER_DEFINITIONS(PvaClientGet);
/** @brief Create a PvaClientGet.
* @param &pvaClient Interface to PvaClient
* @param channel Interface to Channel
* @param pvaClient Interface to PvaClient
* @param pvaClientChannel Interface to PvaClientChannel
* @param pvRequest The request structure.
* @return The interface to the PvaClientGet.
*/
static PvaClientGetPtr create(
PvaClientPtr const &pvaClient,
epics::pvAccess::Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest
);
/** @brief Create a PvaClientGet.
* @param pvaClient Interface to PvaClient
* @param channelName channel name
* @param providerName provider name
* @param request The request.
* @param stateChangeRequester The state change requester. Can be null.
* @param GetRequester The Get requester. Can be null;
* @return The new instance.
*/
static PvaClientGetPtr create(
PvaClientPtr const &pvaClient,
std::string const & channelName,
std::string const & providerName,
std::string const & request,
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester
= PvaClientChannelStateChangeRequesterPtr(),
PvaClientGetRequesterPtr const & getRequester
= PvaClientGetRequesterPtr()
);
/** @brief Destructor
*/
~PvaClientGet();
/** @brief Set a user callback.
* @param pvaClientGetRequester The requester which must be implemented by the caller.
*/
void setRequester(PvaClientGetRequesterPtr const & pvaClientGetRequester);
/** @brief Call issueConnect and then waitConnect.
*
* An exception is thrown if connect fails.
@@ -1054,10 +1125,11 @@ public:
* @return The interface.
*/
PvaClientGetDataPtr getData();
/** Deprecated method
* \deprecated This method will go away in future versions.
/** @brief Get the PvaClientChannel;
*
* @return The interface.
*/
void destroy() EPICS_DEPRECATED {}
PvaClientChannelPtr getPvaClientChannel();
private:
std::string getRequesterName();
void message(std::string const & message,epics::pvData::MessageType messageType);
@@ -1073,14 +1145,14 @@ private:
PvaClientGet(
PvaClientPtr const &pvaClient,
epics::pvAccess::Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest);
void checkGetState();
enum GetConnectState {connectIdle,connectActive,connected};
PvaClient::weak_pointer pvaClient;
epics::pvAccess::Channel::weak_pointer channel;
PvaClientChannelPtr pvaClientChannel;
epics::pvData::PVStructurePtr pvRequest;
epics::pvData::Mutex mutex;
epics::pvData::Event waitForConnect;
@@ -1094,9 +1166,14 @@ private:
GetConnectState connectState;
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
PvaClientGetRequesterWPtr pvaClientGetRequester;
enum GetState {getIdle,getActive,getComplete};
GetState getState;
ChannelGetRequesterImplPtr channelGetRequester;
public:
void channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected);
friend class ChannelGetRequesterImpl;
};
@@ -1106,12 +1183,50 @@ private:
class ChannelPutRequesterImpl;
typedef std::tr1::shared_ptr<ChannelPutRequesterImpl> ChannelPutRequesterImplPtr;
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientPutRequester.html">Overview of PvaClientPutRequester</a>
*/
class PvaClientPutRequester
{
public:
POINTER_DEFINITIONS(PvaClientPutRequester);
virtual ~PvaClientPutRequester() {}
/** @brief A channelPut has connected.
*
* @param status The status returned by the server.
* @param clientPut The PvaClientPut that issued the request to create a ChannelPut.
*/
virtual void channelPutConnect(
const epics::pvData::Status& status,
PvaClientPutPtr const & clientPut);
/** @brief A get request is complete.
*
* @param status The status returned by the server.
* @param clientPut The PvaClientPut that issued the request to create a ChannelPut.
*/
virtual void getDone(
const epics::pvData::Status& status,
PvaClientPutPtr const & clientPut);
/** @brief A put request is complete.
*
* @param status The status returned by the server.
* @param clientPut The PvaClientPut that issued the request to create a ChannelPut.
*/
virtual void putDone(
const epics::pvData::Status& status,
PvaClientPutPtr const & clientPut);
};
/**
* @brief An easy to use alternative to ChannelPut.
*
* @author mrk
* <a href = "../htmldoxygen/pvaClientPut.html">Overview of PvaClientPut</a>
*/
class epicsShareClass PvaClientPut
class epicsShareClass PvaClientPut :
public PvaClientChannelStateChangeRequester,
public std::tr1::enable_shared_from_this<PvaClientPut>
{
public:
POINTER_DEFINITIONS(PvaClientPut);
@@ -1123,13 +1238,35 @@ public:
*/
static PvaClientPutPtr create(
PvaClientPtr const &pvaClient,
epics::pvAccess::Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest
);
/** @brief Create a PvaClientPut.
* @param pvaClient Interface to PvaClient
* @param channelName channel name
* @param providerName provider name
* @param request The request.
* @param stateChangeRequester The state change requester. Can be null.
* @param PutRequester The Put requester. Can be null;
* @return The new instance.
*/
static PvaClientPutPtr create(
PvaClientPtr const &pvaClient,
std::string const & channelName,
std::string const & providerName,
std::string const & request,
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester
= PvaClientChannelStateChangeRequesterPtr(),
PvaClientPutRequesterPtr const & putRequester
= PvaClientPutRequesterPtr()
);
/** @brief Destructor
*/
~PvaClientPut();
/** @brief Set a user callback.
* @param pvaClientPutRequester The requester which must be implemented by the caller.
*/
void setRequester(PvaClientPutRequesterPtr const & pvaClientPutRequester);
/** @brief Call issueConnect and then waitConnect.
*
* An exception is thrown if connect fails.
@@ -1174,10 +1311,11 @@ public:
* @return The interface.
*/
PvaClientPutDataPtr getData();
/** Deprecated method
* \deprecated This method will go away in future versions.
/** @brief Get the PvaClientChannel;
*
* @return The interface.
*/
void destroy() EPICS_DEPRECATED {}
PvaClientChannelPtr getPvaClientChannel();
private :
std::string getRequesterName();
void message(std::string const & message,epics::pvData::MessageType messageType);
@@ -1195,14 +1333,14 @@ private :
epics::pvAccess::ChannelPut::shared_pointer const & channelPut);
PvaClientPut(
PvaClientPtr const &pvaClient,
epics::pvAccess::Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest);
void checkPutState();
enum PutConnectState {connectIdle,connectActive,connected};
PvaClient::weak_pointer pvaClient;
epics::pvAccess::Channel::weak_pointer channel;
PvaClientChannelPtr pvaClientChannel;
epics::pvData::PVStructurePtr pvRequest;
epics::pvData::Mutex mutex;
epics::pvData::Event waitForConnect;
@@ -1217,6 +1355,10 @@ private :
enum PutState {putIdle,getActive,putActive};
PutState putState;
ChannelPutRequesterImplPtr channelPutRequester;
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
PvaClientPutRequesterWPtr pvaClientPutRequester;
public:
void channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected);
friend class ChannelPutRequesterImpl;
};
@@ -1228,7 +1370,7 @@ typedef std::tr1::shared_ptr<ChannelPutGetRequesterImpl> ChannelPutGetRequesterI
/**
* @brief An easy to use alternative to ChannelPutGet.
*
* @author mrk
* <a href = "../htmldoxygen/pvaClientPutGet.html">Overview of PvaClientPutGet</a>
*/
class epicsShareClass PvaClientPutGet
{
@@ -1312,10 +1454,6 @@ public:
* @return The interface.
*/
PvaClientGetDataPtr getGetData();
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private :
std::string getRequesterName();
void message(std::string const & message,epics::pvData::MessageType messageType);
@@ -1371,6 +1509,7 @@ private :
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientMonitorRequester.html">Overview of PvaClientMonitorRequester</a>
*/
class PvaClientMonitorRequester
{
@@ -1401,23 +1540,45 @@ typedef std::tr1::shared_ptr<MonitorRequesterImpl> MonitorRequesterImplPtr;
/**
* @brief An easy to use alternative to Monitor.
*
* <a href = "../htmldoxygen/pvaClientMonitor.html">Overview of PvaClientMonitor</a>
*/
class epicsShareClass PvaClientMonitor :
public PvaClientChannelStateChangeRequester,
public PvaClientMonitorRequester,
public std::tr1::enable_shared_from_this<PvaClientMonitor>
{
public:
POINTER_DEFINITIONS(PvaClientMonitor);
/** @brief Create a PvaClientMonitor.
* @param &pvaClient Interface to PvaClient
* @param channel Interface to Channel
* @param pvaClient Interface to PvaClient
* @param pvaClientChannel Interface to PvaClientChannel
* @param pvRequest The request structure.
* @return The interface to the PvaClientMonitor.
*/
static PvaClientMonitorPtr create(
PvaClientPtr const &pvaClient,
epics::pvAccess::Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest
);
/** @brief Create a PvaClientMonitor.
* @param pvaClient Interface to PvaClient
* @param channelName channel name
* @param providerName provider name
* @param request The request.
* @param stateChangeRequester The state change requester. Can be null.
* @param monitorRequester The monitor requester. Can be null;
* @return The new instance.
*/
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()
);
/** @brief Destructor
*/
~PvaClientMonitor();
@@ -1444,6 +1605,12 @@ public:
/** @brief Start monitoring.
*/
void start();
/**
* @brief Start or restart the monitor with a new request.
*
* @param request The new request.
*/
void start(const std::string & request);
/** @brief Stop monitoring.
*/
void stop();
@@ -1463,14 +1630,16 @@ public:
/** @brief Release the monitorElement returned by poll
*/
void releaseEvent();
/** @brief Get the PvaClientChannel;
*
* @return The interface.
*/
PvaClientChannelPtr getPvaClientChannel();
/** @brief The data in which monitor events are placed.
*
* @return The interface.
*/
PvaClientMonitorDataPtr getData();
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
std::string getRequesterName();
void message(std::string const & message,epics::pvData::MessageType messageType);
@@ -1483,14 +1652,14 @@ private:
PvaClientMonitor(
PvaClientPtr const &pvaClient,
epics::pvAccess::Channel::shared_pointer const & channel,
PvaClientChannelPtr const & pvaClientChannel,
epics::pvData::PVStructurePtr const &pvRequest);
void checkMonitorState();
enum MonitorConnectState {connectIdle,connectActive,connected};
enum MonitorConnectState {connectIdle,connectWait,connectActive,connected};
PvaClient::weak_pointer pvaClient;
epics::pvAccess::Channel::weak_pointer channel;
PvaClientChannelPtr pvaClientChannel;
epics::pvData::PVStructurePtr pvRequest;
epics::pvData::Mutex mutex;
epics::pvData::Event waitForConnect;
@@ -1498,21 +1667,29 @@ private:
PvaClientMonitorDataPtr pvaClientData;
bool isStarted;
epics::pvData::Status connectStatus;
epics::pvData::Status monitorConnectStatus;
epics::pvData::MonitorPtr monitor;
epics::pvData::MonitorElementPtr monitorElement;
PvaClientChannelStateChangeRequesterWPtr pvaClientChannelStateChangeRequester;
PvaClientMonitorRequesterWPtr pvaClientMonitorRequester;
MonitorConnectState connectState;
bool userPoll;
bool userWait;
MonitorRequesterImplPtr monitorRequester;
public:
void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected);
void event(PvaClientMonitorPtr const & monitor);
friend class MonitorRequesterImpl;
};
/**
* @brief Optional client callback.
*
* <a href = "../htmldoxygen/pvaClientRPCRequester.html">Overview of PvaClientRPCRequester</a>
*/
class PvaClientRPCRequester
{
@@ -1538,6 +1715,7 @@ typedef std::tr1::shared_ptr<RPCRequesterImpl> RPCRequesterImplPtr;
/**
* @brief An easy to use alternative to RPC.
*
* <a href = "../htmldoxygen/pvaClientRPC.html">Overview of PvaClientRPC</a>
*/
class epicsShareClass PvaClientRPC :
public std::tr1::enable_shared_from_this<PvaClientRPC>
@@ -1663,6 +1841,6 @@ private:
/** @page Overview Documentation
*
* <a href = "../pvaClientCPP.html">pvaClientCPP.html</a>
*
*
*/

View File

@@ -145,10 +145,6 @@ 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,
@@ -209,10 +205,6 @@ public:
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientMultiGetDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -262,10 +254,6 @@ public:
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientMultiPutDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -329,10 +317,6 @@ public:
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientMultiMonitorDouble(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -390,10 +374,6 @@ public:
{
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,
@@ -453,10 +433,6 @@ public:
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientNTMultiPut(
PvaClientMultiChannelPtr const &pvaClientMultiChannel,
@@ -523,10 +499,6 @@ public:
{
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,
@@ -601,10 +573,6 @@ public:
{
return shared_from_this();
}
/** Deprecated method
* \deprecated This method will go away in future versions.
*/
void destroy() EPICS_DEPRECATED {}
private:
PvaClientNTMultiData(
epics::pvData::UnionConstPtr const & u,

View File

@@ -104,22 +104,31 @@ PvaClientPtr PvaClient::get(std::string const & providerNames)
PvaClient::PvaClient(std::string const & providerNames)
: pvaClientChannelCache(new PvaClientChannelCache()),
pvaStarted(false),
caStarted(false)
caStarted(false),
channelRegistry(ChannelProviderRegistry::clients())
{
stringstream ss(providerNames);
string providerName;
if(PvaClient::debug) {
cout<< "PvaClient::PvaClient()\n";
}
while (getline(ss, providerName, ' '))
{
ChannelProviderRegistry::shared_pointer registry(getChannelProviderRegistry());
if(providerName=="pva") {
if(PvaClient::debug) {
cout<< "calling ClientFactory::start()\n";
}
ClientFactory::start();
pvaStarted = true;
} else if(providerName=="ca") {
if(PvaClient::debug) {
cout<< "calling CAClientFactory::start()\n";
}
CAClientFactory::start();
caStarted = true;
} else {
if(!registry->getProvider(providerName)) {
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
} else {
if(!channelRegistry->getProvider(providerName)) {
cerr << "PvaClient::get provider " << providerName << " not known" << endl;
}
}
}
@@ -141,6 +150,7 @@ PvaClient::~PvaClient() {
CAClientFactory::stop();
if(PvaClient::debug) cout<< "after calling CAClientFactory::stop()\n";
}
channelRegistry.reset();
}
string PvaClient:: getRequesterName()

View File

@@ -122,60 +122,12 @@ size_t PvaClientPutCache::cacheSize()
}
class epicsShareClass ChannelRequesterImpl : public ChannelRequester
{
PvaClientChannel::weak_pointer pvaClientChannel;
PvaClient::weak_pointer pvaClient;
public:
ChannelRequesterImpl(
PvaClientChannelPtr const & pvaClientChannel,
PvaClientPtr const &pvaClient)
: pvaClientChannel(pvaClientChannel),
pvaClient(pvaClient)
{}
virtual ~ChannelRequesterImpl() {
if(PvaClient::getDebug()) std::cout << "~ChannelRequesterImpl" << std::endl;
}
virtual std::string getRequesterName() {
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return string("clientChannel is null");
return clientChannel->getRequesterName();
}
virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->message(message,messageType);
}
virtual void channelCreated(
const epics::pvData::Status& status,
Channel::shared_pointer const & channel)
{
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->channelCreated(status,channel);
}
virtual void channelStateChange(
Channel::shared_pointer const & channel,
Channel::ConnectionState connectionState)
{
PvaClientChannelPtr clientChannel(pvaClientChannel.lock());
if(!clientChannel) return;
clientChannel->channelStateChange(channel,connectionState);
}
};
PvaClientChannelPtr PvaClientChannel::create(
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;
}
@@ -332,13 +284,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 ");
}
@@ -421,7 +373,7 @@ 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);
}
@@ -454,7 +406,7 @@ 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);
}
PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
@@ -538,7 +490,7 @@ 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(

View File

@@ -73,29 +73,63 @@ 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,providerName,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;
}
PvaClientGetPtr PvaClientGet::create(
PvaClientPtr const &pvaClient,
std::string const & channelName,
std::string const & providerName,
std::string const & request,
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester,
PvaClientGetRequesterPtr const & getRequester)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientGet::create(pvaClient,channelName,providerName,request,stateChangeRequester,getRequester)\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);
PvaClientGetPtr clientGet(new PvaClientGet(pvaClient,pvaClientChannel,pvRequest));
clientGet->channelGetRequester = ChannelGetRequesterImplPtr(
new ChannelGetRequesterImpl(clientGet,pvaClient));
if(stateChangeRequester) clientGet->pvaClientChannelStateChangeRequester = stateChangeRequester;
if(getRequester) clientGet->pvaClientGetRequester = getRequester;
pvaClientChannel->setStateChangeRequester(clientGet);
pvaClientChannel->issueConnect();
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()
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
}
@@ -103,19 +137,53 @@ PvaClientGet::PvaClientGet(
PvaClientGet::~PvaClientGet()
{
if(PvaClient::getDebug()) {
string channelName("disconnected");
Channel::shared_pointer chan(channel.lock());
if(chan) channelName = chan->getChannelName();
cout<< "PvaClientGet::~PvaClientGet"
<< " channelName " << channelName
cout<< "PvaClientGet::~PvaClientGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(channelGet) channelGet->destroy();
}
void PvaClientGet::channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientGet::channelStateChange"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " isConnected " << (isConnected ? "true" : "false")
<< endl;
}
if(isConnected&&!channelGet)
{
connectState = connectActive;
channelGet = pvaClientChannel->getChannel()->createChannelGet(channelGetRequester,pvRequest);
}
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
if(req) {
req->channelStateChange(pvaClientChannel,isConnected);
}
}
void PvaClientGet::checkGetState()
{
if(connectState==connectIdle) connect();
if(PvaClient::getDebug()) {
cout << "PvaClientGet::checkGetState"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(!pvaClientChannel->getChannel()->isConnected()) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientGet::checkGetState 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);
}
if(getState==getIdle) get();
}
@@ -140,24 +208,32 @@ 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
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
{
Lock xx(mutex);
channelGetConnectStatus = status;
connectState = connected;
this->channelGet = channelGet;
if(status.isOK()) {
channelGetConnectStatus = status;
connectState = connected;
pvaClientData = PvaClientGetData::create(structure);
pvaClientData->setMessagePrefix(channelGet->getChannel()->getChannelName());
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientGet::channelGetConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
channelGetConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
}
}
PvaClientGetRequesterPtr req(pvaClientGetRequester.lock());
if(req) {
req->channelGetConnect(status,shared_from_this());
}
waitForConnect.signal();
}
@@ -169,11 +245,8 @@ 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
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " status.isOK " << (status.isOK() ? "true" : "false")
<< endl;
}
@@ -184,42 +257,52 @@ void PvaClientGet::getDone(
pvaClientData->setData(pvStructure,bitSet);
}
}
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()
<< 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()
+ " 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()
<< endl;
}
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()
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(connectState==connected) {
@@ -227,10 +310,7 @@ Status PvaClientGet::waitConnect()
return channelGetConnectStatus;
}
if(connectState!=connectActive) {
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::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
@@ -242,25 +322,29 @@ Status PvaClientGet::waitConnect()
void PvaClientGet::get()
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::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()
+ " PvaClientGet::get " + status.getMessage();
throw std::runtime_error(message);
}
void PvaClientGet::issueGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::issueGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle) connect();
if(getState==getActive) {
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::issueGet get aleady active ";
throw std::runtime_error(message);
}
@@ -270,16 +354,18 @@ void PvaClientGet::issueGet()
Status PvaClientGet::waitGet()
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::waitGet"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(getState==getComplete) {
return channelGetStatus;
}
if(getState!=getActive){
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::waitGet llegal get state";
throw std::runtime_error(message);
}
@@ -294,5 +380,21 @@ PvaClientGetDataPtr PvaClientGet::getData()
return pvaClientData;
}
void PvaClientGet::setRequester(PvaClientGetRequesterPtr const & pvaClientGetRequester)
{
if(PvaClient::getDebug()) {
cout << "PvaClientGet::setRequester"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
this->pvaClientGetRequester = pvaClientGetRequester;
}
PvaClientChannelPtr PvaClientGet::getPvaClientChannel()
{
return pvaClientChannel;
}
}}

View File

@@ -80,21 +80,56 @@ public:
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;
if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::create(pvaClient,pvaClientChannel,pvRequest)\n"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
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,21 +137,15 @@ PvaClientMonitor::PvaClientMonitor(
userWait(false)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientMonitor::PvaClientMonitor()"
<< " channelName " << channel->getChannelName()
<< endl;
cout<< "PvaClientMonitor::PvaClientMonitor()" << 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) {
@@ -125,19 +154,50 @@ PvaClientMonitor::~PvaClientMonitor()
}
}
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)
{
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()
@@ -159,50 +219,58 @@ 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);
this->monitor = monitor;
if(!status.isOK()) {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientMonitor::monitorConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
return;
}
}
bool signal = (connectState==connectWait) ? true : false;
monitorConnectStatus = status;
connectState = connected;
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;
}
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();
} else {
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::monitorConnect calling start\n";
}
start();
}
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::monitorConnect calling waitForConnect.signal\n";
}
waitForConnect.signal();
}
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();
@@ -218,10 +286,7 @@ void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
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";
cerr << pvaClientChannel->getChannel()->getChannelName() + "pvaClientMonitor::unlisten called but no PvaClientMonitorRequester\n";
}
@@ -231,11 +296,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
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::connect "
+ status.getMessage();
throw std::runtime_error(message);
@@ -244,59 +306,49 @@ 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;
}
{
Lock xx(mutex);
if(connectState==connected) {
if(!monitorConnectStatus.isOK()) connectState = connectIdle;
return monitorConnectStatus;
}
if(connectState!=connectWait) {
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
}
waitForConnect.wait();
connectState = connectStatus.isOK() ? connected : connectIdle;
connectState = monitorConnectStatus.isOK() ? connected : connectIdle;
if(PvaClient::getDebug()) {
cout << "PvaClientMonitor::waitConnect"
<< " connectStatus " << (connectStatus.isOK() ? "connected" : "not connected");
<< " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected");
}
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 +357,21 @@ 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
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " 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 +379,47 @@ 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();
monitor->destroy();
}
monitorRequester.reset();
monitor.reset();
isStarted = false;
connectState = connectIdle;
userPoll = false;
userWait = false;
monitorRequester = MonitorRequesterImplPtr(
new MonitorRequesterImpl(shared_from_this(),client));
pvRequest = pvr;
connect();
start();
}
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,27 +430,18 @@ 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
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " 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
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientMonitor::poll did not release last";
throw std::runtime_error(message);
}
@@ -389,18 +455,12 @@ bool PvaClientMonitor::poll()
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 +478,17 @@ 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
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " 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 +496,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();

View File

@@ -82,30 +82,58 @@ 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;
}
PvaClientPutPtr PvaClientPut::create(
PvaClientPtr const &pvaClient,
std::string const & channelName,
std::string const & providerName,
std::string const & request,
PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester,
PvaClientPutRequesterPtr const & putRequester)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientPut::create(pvaClient,channelName,providerName,request,stateChangeRequester,putRequester)\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);
PvaClientPutPtr clientPut(new PvaClientPut(pvaClient,pvaClientChannel,pvRequest));
clientPut->channelPutRequester = ChannelPutRequesterImplPtr(
new ChannelPutRequesterImpl(clientPut,pvaClient));
if(stateChangeRequester) clientPut->pvaClientChannelStateChangeRequester = stateChangeRequester;
if(putRequester) clientPut->pvaClientPutRequester = putRequester;
pvaClientChannel->setStateChangeRequester(clientPut);
pvaClientChannel->issueConnect();
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,21 +141,49 @@ 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::channelStateChange(PvaClientChannelPtr const & pvaClientChannel, bool isConnected)
{
if(PvaClient::getDebug()) {
cout<< "PvaClientPut::channelStateChange"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< " isConnected " << (isConnected ? "true" : "false")
<< endl;
}
if(isConnected&&!channelPut)
{
connectState = connectActive;
channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
}
PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
if(req) {
req->channelStateChange(pvaClientChannel,isConnected);
}
}
void PvaClientPut::checkPutState()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPut::checkPutState"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
if(connectState==connectIdle){
connect();
get();
return;
}
if(connectState==connectActive){
string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
+ " "
+ channelPutConnectStatus.getMessage();
throw std::runtime_error(message);
}
}
@@ -151,23 +207,32 @@ 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()) {
channelPutConnectStatus = status;
connectState = connected;
pvaClientData = PvaClientPutData::create(structure);
pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName());
} else {
stringstream ss;
ss << pvRequest;
string message = string("\nPvaClientPut::channelPutConnect)")
+ "\npvRequest\n" + ss.str()
+ "\nerror\n" + status.getMessage();
channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
}
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->channelPutConnect(status,shared_from_this());
}
waitForConnect.signal();
}
@@ -179,11 +244,8 @@ 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;
}
@@ -195,6 +257,10 @@ void PvaClientPut::getDone(
bs->clear();
*bs |= *bitSet;
}
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->getDone(status,shared_from_this());
}
waitForGetPut.signal();
}
@@ -203,28 +269,31 @@ 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;
PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
if(req) {
req->putDone(status,shared_from_this());
}
waitForGetPut.signal();
}
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
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::connect "
+ status.getMessage();
throw std::runtime_error(message);
@@ -232,24 +301,29 @@ 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()
{
if(PvaClient::getDebug()) {
cout << "PvaClientPut::waitConnect"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
{
Lock xx(mutex);
if(connectState==connected) {
@@ -257,10 +331,7 @@ Status PvaClientPut::waitConnect()
return channelPutConnectStatus;
}
if(connectState!=connectActive) {
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::waitConnect illegal connect state ";
throw std::runtime_error(message);
}
@@ -275,11 +346,8 @@ void PvaClientPut::get()
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
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::get "
+ status.getMessage();
throw std::runtime_error(message);
@@ -289,11 +357,8 @@ void PvaClientPut::issueGet()
{
if(connectState==connectIdle) connect();
if(putState!=putIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ pvaClientChannel->getChannel()->getChannelName()
+ "PvaClientPut::issueGet get or put aleady active ";
throw std::runtime_error(message);
}
@@ -304,11 +369,8 @@ 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
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::waitGet illegal put state";
throw std::runtime_error(message);
}
@@ -322,11 +384,8 @@ void PvaClientPut::put()
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);
@@ -336,11 +395,8 @@ void PvaClientPut::issuePut()
{
if(connectState==connectIdle) connect();
if(putState!=putIdle) {
Channel::shared_pointer chan(channel.lock());
string channelName("disconnected");
if(chan) channelName = chan->getChannelName();
string message = string("channel ")
+ channelName
+ pvaClientChannel->getChannel()->getChannelName()
+ "PvaClientPut::issueGet get or put aleady active ";
throw std::runtime_error(message);
}
@@ -351,11 +407,8 @@ 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
+ pvaClientChannel->getChannel()->getChannelName()
+ " PvaClientPut::waitPut illegal put state";
throw std::runtime_error(message);
}
@@ -367,9 +420,28 @@ Status PvaClientPut::waitPut()
PvaClientPutDataPtr PvaClientPut::getData()
{
if(PvaClient::getDebug()) {
cout<< "PvaClientPut::getData"
<< " channelName " << pvaClientChannel->getChannel()->getChannelName()
<< endl;
}
checkPutState();
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;
}
}}