diff --git a/README.md b/README.md index d664352..d64a0fa 100644 --- a/README.md +++ b/README.md @@ -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. diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index faa83ee..628422d 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -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. diff --git a/documentation/htmldoxygen/README.md b/documentation/htmldoxygen/README.md new file mode 100644 index 0000000..372621f --- /dev/null +++ b/documentation/htmldoxygen/README.md @@ -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. diff --git a/documentation/htmldoxygen/pvaClient.html b/documentation/htmldoxygen/pvaClient.html new file mode 100644 index 0000000..315f718 --- /dev/null +++ b/documentation/htmldoxygen/pvaClient.html @@ -0,0 +1,146 @@ + + + + + + PvaClient + + + + + + + + +

PvaClient

+ + +

Overview

+

+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. +

+

+Class PvaClient is a class that is used by all the other pvaClient classes. +An application that uses pvaClient must call:

+
+PvaClientPtr pvaClient = PvaClient::get(providers);
+
+

+before it uses any other pvaClient classes. +

+

+This is a singleton method, i. e. only one instance of PvaClient is created. +

+

+pvaClient must not be deleted until the client no longer wants to use any part +of pvaClient. +

+

+providers is a blank separated set of provider names. +For example:

+
+PvaClientPtr pvaClient = PvaClient::get("ca pva");
+
+

+The providers ca and pva are special. +For each of these a client context is created when the PvaClient +is constructed and the context destroyed when PvaClient is deleted. +

+

Channel Caching

+

+PvaClient has a method: +

+
+PvaClientChannelPtr channel(
+    string const & channelName,
+    string const &providerName = "pva",
+    double timeOut = 5.0);
+
+

+This method creates a +PvaClientChannel and then connects to the channel. +

+

+If a call is successful then multiple calls to the same channelName and providerName +share the same PvaClientChannel, i. e. the PvaClientChannel is cached. +

+

+pvaClientChannelGet and pvaClientChannelPut also implement caching. +

+

+For example consider a client that makes multiple calls like: +

+
+double value;
+value =  pva->channel(channelName)->get()->getData()->getDouble();
+...
+value =  pva->channel(channelName)->get()->getData()->getDouble();
+
+

+Only the first call creates a new PvaClientChannel and a new PvaClientGet. +The second call reuses the cached PvaClientChannel and PvaClientGet. +

+

Non Cached Channels

+

+PvaClient has a method: +

+
+PvaClientChannelPtr createChannel(
+    string const & channelName,
+    string const &providerName = "pva");
+
+

+This method is just creates a new PvaClientChannel and returns it to the caller. +The caller must call the PvaClientChannel connect methods. +

+ +

Blocking vs Non-Blocking Methods

+

Each component of pvaClient provides a set of blocking and non-blocking calls. +For example several components (examples are PvaClientChannel and PvaChannelGet) +have methods:

+
+
connect
+
+ This calls issueConnect and then waitConnect. + If waitConnect fails an exception is thrown. + Since waitConnect is a blocking method so is this. +
+
issueConnect
+
+ 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. +
+
waitConnect
+
+ This waits for the server to respond to issueConnect. + It blocks until the server responds or a timeout occurs. +
+
+ + + + + diff --git a/documentation/htmldoxygen/pvaClientChannel.html b/documentation/htmldoxygen/pvaClientChannel.html new file mode 100644 index 0000000..671b115 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientChannel.html @@ -0,0 +1,123 @@ + + + + + + PvaClientChannel + + + + + + + + +

PvaClientChannel

+ +

Overview

+

+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. +

+

An instance of PvaClientChannel connects to a single channel. +An instance can only be created via class PvaClient 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. +

+

PvaClientChannel has methods:

+
+
Connect to channel
+
These can be called indirectly by a blocking request to PvaClient + or by the client if a non blocking request is made to PvaClient. +
+
Channel state change requester
+
The client can provide a callback that is called each time the connection state + of the channel changes. +
+
Creating all of the following
+
+
+PvaClientField      NOT IMPLEMENTED
+PvaClientProcess
+PvaClientGet
+PvaClientPut
+PvaClientPutGet
+PvaClientMonitor
+PvaClientArray      NOT IMPLEMENTED
+PvaClientRPC
+
+
+
+

Connect: Blocking vs Non-Blocking

+

PvaClientChannel has methods:

+
+
connect
+
+ This calls issueConnect and then waitConnect. + If waitConnect fails an exception is thrown. + Since waitConnect is a blocking method so is this. +
+
issueConnect
+
+ This is a request to connect to the channel. This is a non blocking call. +
+
waitConnect
+
+ This waits for the server to respond to issueConnect. + It blocks until the server responds or a timeout occurs. +
+
+ +

Get and Put Caching

+

+PvaClientChannel has methods: +

+
+PvaClientGetPtr get(std::string const & request);
+PvaClientPutPtr put(std::string const & request);
+
+

+Each of these caches. +For example all calls to get with the same request will share the same +PvaChannelGet +

+

+For example consider a client that makes multiple calls like: +

+
+double value;
+value =  pva->channel(channelName)->get()->getData()->getDouble();
+...
+value =  pva->channel(channelName)->get()->getData()->getDouble();
+
+

+Only the first call creates a new PvaClientChannel and a new PvaClientGet. +The second call reuses the cached PvaClientChannel and PvaClientGet. +

+ + + + + diff --git a/documentation/htmldoxygen/pvaClientChannelStateChangeRequester.html b/documentation/htmldoxygen/pvaClientChannelStateChangeRequester.html new file mode 100644 index 0000000..6513646 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientChannelStateChangeRequester.html @@ -0,0 +1,81 @@ + + + + + + PvaClientChannelStateChangeRequester + + + + + + + + +

PvaClientChannelStateChangeRequester

+ +

This class has the single method channelStateChange. +It is called each time the channel connection status changes. +

+

+NOTE: +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. +

+

+An example of illegal code is: +

+
+virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
+{
+    if(isConnected&&!pvaClientPut)
+    {
+       pvaClientPut  = pvaClientChannel->createPut(request);
+       pvaClientPut->connect();
+    }
+}
+
+

+This is illegal because the call to connect blocks. +

+

The following is an example of legal code: +

+
+virtual void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
+{
+    if(isConnected&&!pvaClientPut)
+    {
+       pvaClientPut  = pvaClientChannel->createPut(request);
+       pvaClientPut->issueConnect();
+    }
+}
+
+

This is legal code because neither createPut or issueConnect +blocks. +

+ + + + + diff --git a/documentation/htmldoxygen/pvaClientGet.html b/documentation/htmldoxygen/pvaClientGet.html new file mode 100644 index 0000000..0845e92 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientGet.html @@ -0,0 +1,74 @@ + + + + + + PvaClientGet + + + + + + + + +

PvaClientGet

+ + +

+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. +

+

An instance of PvaClientGet is created via a call to one of the following:

+
+class PvaClientChannel
+...
+{
+...
+    PvaClientGetPtr get(std::string const & request = "field(value,alarm,timeStamp)");
+    PvaClientGetPtr createGet(std::string const & request = "");
+    PvaClientGetPtr createGet(epics::pvData::PVStructurePtr const &  pvRequest);
+...
+};
+

An instance of PvaClientGet connects to a single channel. +PvaClientGet has both synchronous methods, which block, and non blocking methods. +

+

PvaClientChannel has methods:

+
+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.
+
+

+issueConnect and issueGet do not block. +All other methods can block. +

+ + + + diff --git a/documentation/htmldoxygen/pvaClientGetData.html b/documentation/htmldoxygen/pvaClientGetData.html new file mode 100644 index 0000000..8625301 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientGetData.html @@ -0,0 +1,63 @@ + + + + + + PvaClientGetData + + + + + + + + +

PvaClientGetData

+ +

This class provides access to the data returned by calls to get data via PvaChannelGet +It provides methods:

+
+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.
+
+ + + + diff --git a/documentation/htmldoxygen/pvaClientGetRequester.html b/documentation/htmldoxygen/pvaClientGetRequester.html new file mode 100644 index 0000000..e2fe9f6 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientGetRequester.html @@ -0,0 +1,44 @@ + + + + + + PvaClientGetRequester + + + + + + + + +

PvaClientGetRequester

+ +

+Not Yet Written +

+ + + + diff --git a/documentation/htmldoxygen/pvaClientMonitor.html b/documentation/htmldoxygen/pvaClientMonitor.html new file mode 100644 index 0000000..f3b3f25 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientMonitor.html @@ -0,0 +1,106 @@ + + + + + + PvaClientMonitor + + + + + + + + +

PvaClientMonitor

+

+NOTE: This is a work in progress. +

+

Overview

+

+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: +

+

The client first creates a PvaClientMonitorChannel and then creates a monitor

+The client calls: +
+static PvaClientMonitorPtr create(
+    PvaClientMonitorPtr const &PvaClientMonitor,
+    PvaClientMonitorChannelPtr const & PvaClientMonitorChannel,
+    epics::pvData::PVStructurePtr const &pvRequest
+);
+
+where
+
+PvaClientMonitor
+    The PvaClientMonitor.
+
+PvaClientMonitorChannel
+    The PvaClientMonitorChannel that has already been created by the client.
+
+pvRequest
+    The pvRequest for creating the monitor.
+
+With this method the monitor is created and started. +This method blocks while the monitor is created. +

The client provides names for a channel and a provider

+The client calls: +
+static PvaClientMonitorPtr create(
+    PvaClientMonitorPtr const &PvaClientMonitor,
+    std::string const & channelName,
+    std::string const & providerName,
+    std::string const & request,
+    PvaClientMonitorChannelStateChangeRequesterPtr const & stateChangeRequester,
+    PvaClientMonitorRequesterPtr const & 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.
+
+With this method a pvaChannel is created and after it connects a pvaMonitor is created and started. +This method never blocks. + + + + diff --git a/documentation/htmldoxygen/pvaClientMonitorData.html b/documentation/htmldoxygen/pvaClientMonitorData.html new file mode 100644 index 0000000..1b76f83 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientMonitorData.html @@ -0,0 +1,66 @@ + + + + + + PvaClientMonitorData + + + + + + + + +

PvaClientMonitorData

+ + +

This class provides access to the data returned by calls to get data via PvaChannelGet +It provides methods:

+
+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.
+
+ + + + diff --git a/documentation/htmldoxygen/pvaClientMonitorRequester.html b/documentation/htmldoxygen/pvaClientMonitorRequester.html new file mode 100644 index 0000000..43d36bd --- /dev/null +++ b/documentation/htmldoxygen/pvaClientMonitorRequester.html @@ -0,0 +1,44 @@ + + + + + + PvaClientMonitorRequester + + + + + + + + +

PvaClientMonitorRequester

+ +

+Not Yet Written +

+ + + + diff --git a/documentation/htmldoxygen/pvaClientProcess.html b/documentation/htmldoxygen/pvaClientProcess.html new file mode 100644 index 0000000..b1de4f2 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientProcess.html @@ -0,0 +1,71 @@ + + + + + + PvaClientProcess + + + + + + + + +

PvaClientProcess

+ +

+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. +

+

An instance of PvaClientProcess is created via a call to one of the followimg:

+
+class PvaClientChannel
+...
+{
+...
+    PvaClientProcessPtr createProcess(std::string const & request = "");
+    PvaClientProcessPtr createProcess(epics::pvData::PVStructurePtr const &  pvRequest);
+...
+};
+

An instance of PvaClientProcess connects to a single channel. +PvaClientProcess has both synchronous methods, which block, and non blocking methods. +

+

PvaClientChannel has methods:

+
+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.
+
+

+issueConnect and issueProcess do not block. +All other methods can block. +

+ + + + diff --git a/documentation/htmldoxygen/pvaClientPut.html b/documentation/htmldoxygen/pvaClientPut.html new file mode 100644 index 0000000..7fef373 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientPut.html @@ -0,0 +1,82 @@ + + + + + + PvaClientChannelPut + + + + + + + + +

PvaClientChannelPut

s + +

+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. +

+

+NOTE: +Except for union fields pvaClientPut takes care of modifying the bitSet associated with +the data sent to the server. +

+

An instance of PvaClientPut is created via a call to one of the followimg:

+
+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);
+...
+};
+

An instance of PvaClientPut/b> connects to a single channel. +PvaClientPut has both synchronous methods, which block, and non blocking methods. +

+

PvaClientPut has methods:

+
+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.
+
+

+Note that issueConnect, issueGet and issuePut do not block but all other methods +do block. +

+ + + + + diff --git a/documentation/htmldoxygen/pvaClientPutData.html b/documentation/htmldoxygen/pvaClientPutData.html new file mode 100644 index 0000000..09cff35 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientPutData.html @@ -0,0 +1,75 @@ + + + + + + PvaClientPutData + + + + + + + + +

PvaClientPutData

+ +

This class provides access to data to send to the server via a PvaChannelPut +It is created by PvaChannelPut or PvaChannelPutGet. +This the client only gets access to an instance by getting it from PvaChannelPut or PvaChannelPutGet. +

+

Note also that for all field types except union the BitSet for the data is updated +by PvaChannelPut or PvaChannelPutGet whenever the client changes a field. +For a union or unionArray field the client must update the BitSet. +

+ +

+PvaClientPutData provides methods:

+
+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.
+
+ + + diff --git a/documentation/htmldoxygen/pvaClientPutGet.html b/documentation/htmldoxygen/pvaClientPutGet.html new file mode 100644 index 0000000..f0db3bf --- /dev/null +++ b/documentation/htmldoxygen/pvaClientPutGet.html @@ -0,0 +1,85 @@ + + + + + + PvaClientPutGetGet + + + + + + + + +

PvaClientPutGetGet

+ +

+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. +

+

+NOTE: +Except for union fields pvaClientPutGet takes care of modifying the bitSet associated with +the data sent to the server. +

+

An instance of PvaClientPutGet is created via a call to one of the followimg:

+
+class PvaClientChannel
+...
+{
+...
+    PvaClientPutGetPtr createPutGet(std::string const & request);
+    PvaClientPutGetPtr createPutGet(epics::pvData::PVStructurePtr const &  pvRequest);
+...
+};
+

An instance of PvaClientPutGet connects to a single channel. +PvaClientPutGet has both synchronous methods, which block, and non blocking methods. +

+

PvaClientPutGet has methods:

+
+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.
+
+

+issueConnect, issuePutGet, issueGetGet and issueGetPut do not block. +All other methods can block. +

+ + + + + diff --git a/documentation/htmldoxygen/pvaClientPutRequester.html b/documentation/htmldoxygen/pvaClientPutRequester.html new file mode 100644 index 0000000..00aed26 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientPutRequester.html @@ -0,0 +1,44 @@ + + + + + + PvaClientPutRequester + + + + + + + + +

PvaClientPutRequester

+ +

+Not Yet Written +

+ + + + diff --git a/documentation/htmldoxygen/pvaClientRPC.html b/documentation/htmldoxygen/pvaClientRPC.html new file mode 100644 index 0000000..4a754c1 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientRPC.html @@ -0,0 +1,44 @@ + + + + + + PvaClientRPC + + + + + + + + +

PvaClientRPC

+ +

+Not Yet Written +

+ + + + diff --git a/documentation/htmldoxygen/pvaClientRPCRequester.html b/documentation/htmldoxygen/pvaClientRPCRequester.html new file mode 100644 index 0000000..1476214 --- /dev/null +++ b/documentation/htmldoxygen/pvaClientRPCRequester.html @@ -0,0 +1,44 @@ + + + + + + PvaClientRPCRequester + + + + + + + + +

PvaClientRPCRequester

+ +

+Not Yet Written +

+ + + + diff --git a/documentation/pvaClientCPP.html b/documentation/pvaClientCPP.html index 20ee501..ee62eff 100644 --- a/documentation/pvaClientCPP.html +++ b/documentation/pvaClientCPP.html @@ -26,11 +26,11 @@

EPICS pvaClientCPP

-

Release 4.2.0-SNAPSHOT - 2016-07-14

+

Release 4.7.0-SNAPSHOT - 2017-06-29

Abstract

-

pvaClient is a software library that provides to an EPICS client programmer, a friendly +

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.

@@ -62,11 +62,6 @@ The data for the channels is presented via normative type NTMultiChannel.
-
-

Table of Contents

-
- -

Overview

@@ -76,10 +71,10 @@ pvaClientCPP is one of the components of EPICS Version 4

-

This document is only a guide to help locate code and documentation related to pvDatabaseCPP +

This document is only a guide to help locate code and documentation related to pvaClientCPP

-It is intended for developers that want to use pvDatabaseCPP. +It is intended for developers that want to use pvaClientCPP.

Developer Guide

A guide for developers is available at @@ -88,14 +83,11 @@ href="http://epics-pvdata.sourceforge.net/informative/developerGuide/developerGu developerGuide

-

This guide discusses all the components that are part of an EPICS V4 release. +

This guide provides an overview of the components that are part of an EPICS V4 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.

-

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. -

doxygen

doxygen documentation is available at @@ -104,9 +96,9 @@ href="./html/index.html">doxygen

exampleCPP

-

Example code is available as part of this release. +

Example code is available at +href="https://github.com/epics-base/exampleCPP"> exampleCPP

diff --git a/src/Makefile b/src/Makefile index 7e945c7..52d3327 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ include $(TOP)/configure/CONFIG LIBRARY += pvaClient # shared library ABI version. -SHRLIB_VERSION ?= 4.2.0 +SHRLIB_VERSION ?= 4.3.0 INC += pv/pvaClient.h INC += pv/pvaClientMultiChannel.h @@ -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 diff --git a/src/pv/pvaClient.h b/src/pv/pvaClient.h index 08cad2e..53e8cbd 100644 --- a/src/pv/pvaClient.h +++ b/src/pv/pvaClient.h @@ -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 #include -#include +#include #include #include #include @@ -28,7 +32,6 @@ #include #include #include -#include #include #ifdef pvaClientEpicsExportSharedSymbols @@ -57,8 +60,14 @@ class PvaClientField; typedef std::tr1::shared_ptr PvaClientFieldPtr; class PvaClientProcess; typedef std::tr1::shared_ptr PvaClientProcessPtr; +class PvaClientGetRequester; +typedef std::tr1::shared_ptr PvaClientGetRequesterPtr; +typedef std::tr1::weak_ptr PvaClientGetRequesterWPtr; class PvaClientGet; typedef std::tr1::shared_ptr PvaClientGetPtr; +class PvaClientPutRequester; +typedef std::tr1::shared_ptr PvaClientPutRequesterPtr; +typedef std::tr1::weak_ptr PvaClientPutRequesterWPtr; class PvaClientPut; typedef std::tr1::shared_ptr PvaClientPutPtr; class PvaClientPutGet; @@ -83,10 +92,7 @@ typedef std::tr1::shared_ptr 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 + * Overview of PvaClient */ 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); @@ -192,15 +189,12 @@ typedef std::tr1::shared_ptr PvaClientGetCachePtr; class PvaClientPutCache; typedef std::tr1::shared_ptr 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 ChannelRequesterImplPtr; /** * @brief A callback for change in connection status. * - * @author mrk + * Overview of PvaClientChannelStateChangeRequester + * */ class PvaClientChannelStateChangeRequester { @@ -212,6 +206,8 @@ public: virtual ~PvaClientChannelStateChangeRequester(){} /** * @brief A channel connection state change has occurred. + * + * Warning A call to a method that blocks should not be made by this method. * @param channel The channel. * @param isConnected The new connection status. */ @@ -221,10 +217,11 @@ public: /** * @brief An easy to use alternative to directly calling the Channel methods of pvAccess. * - * @author mrk + * Overview of PvaClientChannel */ class epicsShareClass PvaClientChannel : + public epics::pvAccess::ChannelRequester, public std::tr1::enable_shared_from_this { public: @@ -233,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(); @@ -250,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. @@ -301,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. @@ -318,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. */ @@ -332,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. */ @@ -361,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. @@ -379,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. @@ -388,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. @@ -402,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. @@ -409,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. @@ -426,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, @@ -466,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 * + * Overview of PvaClientGetData */ class epicsShareClass PvaClientGetData { @@ -492,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. */ @@ -509,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. */ @@ -614,6 +623,7 @@ class PvaClientPostHandlerPvt; // private to PvaClientPutData /** * @brief A class that holds data given to by PvaClientPut or PvaClientPutGet * + * Overview of PvaClientPutData */ class epicsShareClass PvaClientPutData { @@ -624,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(); @@ -662,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. */ @@ -752,6 +771,7 @@ private: /** * @brief A class that holds data returned by PvaClientMonitor * + * Overview of PvaClientMonitorData */ class epicsShareClass PvaClientMonitorData { @@ -909,7 +929,7 @@ typedef std::tr1::shared_ptr ChannelProcessRequeste /** * @brief An easy to use alternative to ChannelProcess. * - * @author mrk + * Overview of PvaClientProcess */ class epicsShareClass PvaClientProcess { @@ -926,6 +946,7 @@ public: epics::pvAccess::Channel::shared_pointer const & channel, epics::pvData::PVStructurePtr const &pvRequest ); + /** @brief Destructor */ ~PvaClientProcess(); @@ -949,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); @@ -1000,29 +1017,82 @@ private: // because pvAccess holds a shared_ptr to ChannelGetRequester instead of weak_pointer class ChannelGetRequesterImpl; typedef std::tr1::shared_ptr ChannelGetRequesterImplPtr; + +/** + * @brief Optional client callback. + * + * Overview of PvaClientGetRequester + */ +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 + * Overview of PvaClientGet */ -class epicsShareClass PvaClientGet +class epicsShareClass PvaClientGet : + public PvaClientChannelStateChangeRequester, + public std::tr1::enable_shared_from_this { 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. @@ -1055,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); @@ -1074,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; @@ -1095,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; }; @@ -1107,12 +1183,50 @@ private: class ChannelPutRequesterImpl; typedef std::tr1::shared_ptr ChannelPutRequesterImplPtr; +/** + * @brief Optional client callback. + * + * Overview of PvaClientPutRequester + */ +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 + * Overview of PvaClientPut */ -class epicsShareClass PvaClientPut +class epicsShareClass PvaClientPut : + public PvaClientChannelStateChangeRequester, + public std::tr1::enable_shared_from_this { public: POINTER_DEFINITIONS(PvaClientPut); @@ -1124,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. @@ -1175,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); @@ -1196,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; @@ -1218,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; }; @@ -1229,7 +1370,7 @@ typedef std::tr1::shared_ptr ChannelPutGetRequesterI /** * @brief An easy to use alternative to ChannelPutGet. * - * @author mrk + * Overview of PvaClientPutGet */ class epicsShareClass PvaClientPutGet { @@ -1313,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); @@ -1372,6 +1509,7 @@ private : /** * @brief Optional client callback. * + * Overview of PvaClientMonitorRequester */ class PvaClientMonitorRequester { @@ -1402,11 +1540,11 @@ typedef std::tr1::shared_ptr MonitorRequesterImplPtr; /** * @brief An easy to use alternative to Monitor. * + * Overview of PvaClientMonitor */ class epicsShareClass PvaClientMonitor : public PvaClientChannelStateChangeRequester, public PvaClientMonitorRequester, - public epics::pvData::Command, public std::tr1::enable_shared_from_this { public: @@ -1436,8 +1574,10 @@ public: std::string const & channelName, std::string const & providerName, std::string const & request, - PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester, - PvaClientMonitorRequesterPtr const & monitorRequester + PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester + = PvaClientChannelStateChangeRequesterPtr(), + PvaClientMonitorRequesterPtr const & monitorRequester + = PvaClientMonitorRequesterPtr() ); /** @brief Destructor */ @@ -1490,16 +1630,17 @@ 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: - static epics::pvData::ExecutorPtr executor; std::string getRequesterName(); void message(std::string const & message,epics::pvData::MessageType messageType); void monitorConnect( @@ -1515,7 +1656,7 @@ private: epics::pvData::PVStructurePtr const &pvRequest); void checkMonitorState(); - enum MonitorConnectState {connectIdle,connectActive,connected}; + enum MonitorConnectState {connectIdle,connectWait,connectActive,connected}; PvaClient::weak_pointer pvaClient; PvaClientChannelPtr pvaClientChannel; @@ -1526,7 +1667,7 @@ private: PvaClientMonitorDataPtr pvaClientData; bool isStarted; - epics::pvData::Status connectStatus; + epics::pvData::Status monitorConnectStatus; epics::pvData::MonitorPtr monitor; epics::pvData::MonitorElementPtr monitorElement; @@ -1537,11 +1678,9 @@ private: bool userWait; MonitorRequesterImplPtr monitorRequester; - void init(); public: void channelStateChange(PvaClientChannelPtr const & channel, bool isConnected); void event(PvaClientMonitorPtr const & monitor); - void command(); friend class MonitorRequesterImpl; }; @@ -1550,6 +1689,7 @@ public: /** * @brief Optional client callback. * + * Overview of PvaClientRPCRequester */ class PvaClientRPCRequester { @@ -1575,6 +1715,7 @@ typedef std::tr1::shared_ptr RPCRequesterImplPtr; /** * @brief An easy to use alternative to RPC. * + * Overview of PvaClientRPC */ class epicsShareClass PvaClientRPC : public std::tr1::enable_shared_from_this @@ -1700,6 +1841,6 @@ private: /** @page Overview Documentation * * pvaClientCPP.html - * + * */ diff --git a/src/pv/pvaClientMultiChannel.h b/src/pv/pvaClientMultiChannel.h index ffaff18..c58ad7a 100644 --- a/src/pv/pvaClientMultiChannel.h +++ b/src/pv/pvaClientMultiChannel.h @@ -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, diff --git a/src/pvaClient.cpp b/src/pvaClient.cpp index 6078b49..cb3790d 100644 --- a/src/pvaClient.cpp +++ b/src/pvaClient.cpp @@ -105,7 +105,7 @@ PvaClient::PvaClient(std::string const & providerNames) : pvaClientChannelCache(new PvaClientChannelCache()), pvaStarted(false), caStarted(false), - channelRegistry(getChannelProviderRegistry()) + channelRegistry(ChannelProviderRegistry::clients()) { stringstream ss(providerNames); string providerName; diff --git a/src/pvaClientChannel.cpp b/src/pvaClientChannel.cpp index c048a4b..b17b45d 100644 --- a/src/pvaClientChannel.cpp +++ b/src/pvaClientChannel.cpp @@ -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; } @@ -246,25 +198,26 @@ void PvaClientChannel::channelStateChange( << " " << Channel::ConnectionStateNames[connectionState] << endl; } + + bool waitingForConnect = false; + if(connectState==connectActive) waitingForConnect = true; + if(connectionState!=Channel::CONNECTED) { + string mess(channelName + + " connection state " + Channel::ConnectionStateNames[connectionState]); + message(mess,errorMessage); + connectState = notConnected; + } else { + connectState = connected; + } + if(waitingForConnect) { + Lock xx(mutex); + waitForConnect.signal(); + } PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock()); if(req) { bool value = (connectionState==Channel::CONNECTED ? true : false); req->channelStateChange(shared_from_this(),value); } - - Lock xx(mutex); - bool waitingForConnect = false; - if(connectState==connectActive) waitingForConnect = true; - if(connectionState!=Channel::CONNECTED) { - string mess(channelName + - " connection state " + Channel::ConnectionStateNames[connectionState]); - message(mess,errorMessage); - connectState = notConnected; - return; - } else { - connectState = connected; - } - if(waitingForConnect) waitForConnect.signal(); } string PvaClientChannel::getRequesterName() @@ -331,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 "); } @@ -420,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); } @@ -453,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) diff --git a/src/pvaClientGet.cpp b/src/pvaClientGet.cpp index 34e4f89..83b964b 100644 --- a/src/pvaClientGet.cpp +++ b/src/pvaClientGet.cpp @@ -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; +} + + }} diff --git a/src/pvaClientMonitor.cpp b/src/pvaClientMonitor.cpp index caaa4c0..33088ca 100644 --- a/src/pvaClientMonitor.cpp +++ b/src/pvaClientMonitor.cpp @@ -25,8 +25,6 @@ using namespace std; namespace epics { namespace pvaClient { -ExecutorPtr PvaClientMonitor::executor(new Executor("pvaClientMonitor",middlePriority)); - class MonitorRequesterImpl : public MonitorRequester { PvaClientMonitor::weak_pointer pvaClientMonitor; @@ -120,15 +118,11 @@ PvaClientMonitorPtr PvaClientMonitor::create( new MonitorRequesterImpl(clientMonitor,pvaClient)); if(stateChangeRequester) clientMonitor->pvaClientChannelStateChangeRequester = stateChangeRequester; if(monitorRequester) clientMonitor->pvaClientMonitorRequester = monitorRequester; - clientMonitor->init(); + pvaClientChannel->setStateChangeRequester(clientMonitor); + pvaClientChannel->issueConnect(); return clientMonitor; } -void PvaClientMonitor::init() -{ - pvaClientChannel->setStateChangeRequester(shared_from_this()); - pvaClientChannel->issueConnect(); -} PvaClientMonitor::PvaClientMonitor( PvaClientPtr const &pvaClient, @@ -149,7 +143,6 @@ PvaClientMonitor::PvaClientMonitor( PvaClientMonitor::~PvaClientMonitor() { - if(PvaClient::getDebug()) cout<< "PvaClientMonitor::~PvaClientMonitor\n"; if(PvaClient::getDebug()) { cout<< "PvaClientMonitor::~PvaClientMonitor" << " channelName " << pvaClientChannel->getChannel()->getChannelName() @@ -171,12 +164,12 @@ void PvaClientMonitor::channelStateChange(PvaClientChannelPtr const & channel, b } if(isConnected&&!monitor) { - if(PvaClient::getDebug()) cout<< "PvaClientMonitor::channelStateChange calling executor.execute\n"; - executor->execute(shared_from_this()); - PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock()); - if(req) { - req->channelStateChange(channel,isConnected); - } + connectState = connectActive; + monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest); + } + PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock()); + if(req) { + req->channelStateChange(channel,isConnected); } } @@ -186,13 +179,6 @@ void PvaClientMonitor::event(PvaClientMonitorPtr const & monitor) if(req) req->event(monitor); } -void PvaClientMonitor::command() -{ - if(PvaClient::getDebug()) cout<< "PvaClientMonitor::command\n"; - connect(); - if(connectState==connected && !isStarted) start(); -} - void PvaClientMonitor::checkMonitorState() { if(PvaClient::getDebug()) { @@ -201,8 +187,17 @@ void PvaClientMonitor::checkMonitorState() << " 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() @@ -230,9 +225,22 @@ void PvaClientMonitor::monitorConnect( << " 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()) { cout << "PvaClientMonitor::monitorConnect" @@ -242,14 +250,19 @@ void PvaClientMonitor::monitorConnect( } return; } - if(status.isOK()) { - pvaClientData = PvaClientMonitorData::create(structure); - pvaClientData->setMessagePrefix(pvaClientChannel->getChannel()->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(); } @@ -299,37 +312,36 @@ void PvaClientMonitor::issueConnect() + " pvaClientMonitor already connected "; throw std::runtime_error(message); } - connectState = connectActive; + connectState = connectWait; monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest); } Status PvaClientMonitor::waitConnect() { if(PvaClient::getDebug()) { - cout << "PvaClientMonitor::waitConnect" + cout << "PvaClientMonitor::waitConnect " << pvaClientChannel->getChannel()->getChannelName() << endl; } - if(connectState==connected) { - if(!connectStatus.isOK()) connectState = connectIdle; - return connectStatus; - } - if(connectState!=connectActive) { - string message = string("channel ") - + pvaClientChannel->getChannel()->getChannelName() - + " PvaClientMonitor::waitConnect illegal connect state "; - throw std::runtime_error(message); - } - if(PvaClient::getDebug()) { - cout << "PvaClientMonitor::waitConnect calling waitForConnect.wait\n"; + { + 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) @@ -379,7 +391,7 @@ void PvaClientMonitor::start(string const & request) if(!pvaClientChannel->getChannel()->isConnected()) { client->message( "PvaClientMonitor::start(request) but not connected", - MessageType::errorMessage); + errorMessage); return; } CreateRequest::shared_pointer createRequest(CreateRequest::create()); @@ -484,6 +496,11 @@ void PvaClientMonitor::releaseEvent() monitor->release(monitorElement); } +PvaClientChannelPtr PvaClientMonitor::getPvaClientChannel() +{ + return pvaClientChannel; +} + PvaClientMonitorDataPtr PvaClientMonitor::getData() { if(PvaClient::getDebug()) { diff --git a/src/pvaClientPut.cpp b/src/pvaClientPut.cpp index 8b21cb7..dc5c158 100644 --- a/src/pvaClientPut.cpp +++ b/src/pvaClientPut.cpp @@ -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; +} }}