This is Unofficial EPICS BASE Doxygen Site
clientRPC.cpp
Go to the documentation of this file.
1 /*
2  * Copyright information and license terms for this software can be
3  * found in the file LICENSE that is included with the distribution
4  */
5 
6 #include <epicsMutex.h>
7 #include <epicsGuard.h>
8 #include <epicsEvent.h>
9 #include <epicsThread.h>
10 
11 #include <pv/pvData.h>
12 #include <pv/bitSet.h>
13 #include <pv/reftrack.h>
14 
15 #define epicsExportSharedSymbols
16 #include "pv/logger.h"
17 #include "clientpvt.h"
18 #include "pv/pvAccess.h"
19 
20 namespace {
23 
24 struct RPCer : public pvac::detail::CallbackStorage,
26  public pvac::Operation::Impl,
28 {
29  bool started;
30  operation_type::shared_pointer op;
31 
33  // 'event' may be modified as long as cb!=NULL
34  pvac::GetEvent event;
35 
36  pvd::PVStructure::const_shared_pointer args;
37 
38  static size_t num_instances;
39 
41  const pvd::PVStructure::const_shared_pointer& args) :started(false), cb(cb), args(args)
42  {REFTRACE_INCREMENT(num_instances);}
43  virtual ~RPCer() {
44  CallbackGuard G(*this);
45  cb = 0;
46  G.wait(); // paranoia
47  REFTRACE_DECREMENT(num_instances);
48  }
49 
51  {
53  if(!cb) return;
54 
55  event.event = evt;
56 
57  this->cb = 0;
58 
59  try {
60  CallbackUse U(G);
61  cb->getDone(event);
62  return;
63  }catch(std::exception& e){
64  LOG(pva::logLevelError, "Unhandled exception in ClientChannel::RPCCallback::requestDone(): %s", e.what());
65  }
66  }
67 
68  virtual std::string name() const OVERRIDE FINAL
69  {
70  Guard G(mutex);
71  return op ? op->getChannel()->getChannelName() : "<dead>";
72  }
73 
74  // called automatically via wrapped_shared_from_this
75  virtual void cancel() OVERRIDE FINAL
76  {
77  std::tr1::shared_ptr<RPCer> keepalive(internal_shared_from_this());
78  CallbackGuard G(*this);
79  if(started && op) op->cancel();
80  callEvent(G, pvac::GetEvent::Cancel);
81  }
82 
83  virtual std::string getRequesterName() OVERRIDE FINAL
84  {
85  Guard G(mutex);
86  return op ? op->getChannel()->getRequesterName() : "<dead>";
87  }
88 
89  virtual void channelRPCConnect(
91  pva::ChannelRPC::shared_pointer const & operation) OVERRIDE FINAL
92  {
93  std::tr1::shared_ptr<RPCer> keepalive(internal_shared_from_this());
94  CallbackGuard G(*this);
95  if(!cb || started) return;
96 
97  if(!status.isOK()) {
98  event.message = status.getMessage();
99  } else {
100  event.message.clear();
101  }
102  if(!status.isSuccess()) {
103  callEvent(G);
104 
105  } else {
106  operation->request(std::tr1::const_pointer_cast<pvd::PVStructure>(args));
107  started = true;
108  }
109  }
110 
111  virtual void channelDisconnect(bool destroy) OVERRIDE FINAL
112  {
113  std::tr1::shared_ptr<RPCer> keepalive(internal_shared_from_this());
114  CallbackGuard G(*this);
115  if(!cb) return;
116  event.message = "Disconnect";
117 
118  callEvent(G);
119  }
120 
121  virtual void requestDone(
122  const epics::pvData::Status& status,
123  pva::ChannelRPC::shared_pointer const & operation,
124  epics::pvData::PVStructure::shared_pointer const & pvResponse) OVERRIDE FINAL
125  {
126  std::tr1::shared_ptr<RPCer> keepalive(internal_shared_from_this());
127  CallbackGuard G(*this);
128  if(!cb) return;
129 
130  if(!status.isOK()) {
131  event.message = status.getMessage();
132  } else {
133  event.message.clear();
134  }
135  event.value = pvResponse;
137  valid->set(0);
138  event.valid = valid;
139 
140  callEvent(G, status.isSuccess()? pvac::GetEvent::Success : pvac::GetEvent::Fail);
141  }
142 
143  virtual void show(std::ostream &strm) const OVERRIDE FINAL
144  {
145  strm << "Operation(RPC"
146  "\"" << name() <<"\""
147  ")";
148  }
149 };
150 
151 size_t RPCer::num_instances;
152 
153 }//namespace
154 
155 namespace pvac {
156 
157 Operation
158 ClientChannel::rpc(GetCallback* cb,
159  const epics::pvData::PVStructure::const_shared_pointer& arguments,
160  epics::pvData::PVStructure::const_shared_pointer pvRequest)
161 {
162  if(!impl) throw std::logic_error("Dead Channel");
163  if(!pvRequest)
164  pvRequest = pvd::createRequest("field()");
165 
166  std::tr1::shared_ptr<RPCer> ret(RPCer::build(cb, arguments));
167 
168  {
169  Guard G(ret->mutex);
170  ret->op = getChannel()->createChannelRPC(ret->internal_shared_from_this(),
172  }
173 
174  return Operation(ret);
175 }
176 
177 namespace detail {
178 
180 {
181  epics::registerRefCounter("pvac::RPCer", &RPCer::num_instances);
182 }
183 
184 }
185 
186 }//namespace pvac
virtual void getDone(const GetEvent &evt)=0
get or rpc operation is complete
pvd::Status status
Information on get/rpc completion.
Definition: client.h:99
bool valid() const
Definition: client.h:69
virtual std::string name() const =0
A vector of bits.
Definition: bitSet.h:56
callback for get() and rpc()
Definition: client.h:319
#define OVERRIDE
Definition: pvAccess.h:55
const std::string & getMessage() const
Definition: status.h:80
PVStructure::shared_pointer createRequest(std::string const &request)
const std::tr1::weak_ptr< Process2PutProxy > operation
Definition: pvAccess.cpp:69
Handle for in-progress get/put/rpc operation.
Definition: client.h:50
virtual void show(std::ostream &) const =0
#define LOG(level, format,...)
Definition: logger.h:48
virtual void channelDisconnect(bool destroy)
Definition: pvAccess.h:198
std::tr1::shared_ptr< Derived > internal_shared_from_this()
Definition: clientpvt.h:44
epicsMutex mutex
Definition: pvAccess.cpp:71
APIs for the epicsMutex mutual exclusion semaphore.
virtual void cancel()=0
virtual void channelRPCConnect(const epics::pvData::Status &status, ChannelRPC::shared_pointer const &operation)=0
bool isSuccess() const
Definition: status.h:103
Data interface for a structure,.
Definition: pvData.h:712
virtual void requestDone(const epics::pvData::Status &status, ChannelRPC::shared_pointer const &operation, epics::pvData::PVStructure::shared_pointer const &pvResponse)=0
void registerRefCounter(const char *name, const size_t *counter)
Definition: reftrack.cpp:59
request cancelled before completion
Definition: client.h:92
APIs for the epicsEvent binary semaphore.
request ends in failure. Check message
Definition: client.h:91
std::tr1::shared_ptr< BitSet > BitSetPtr
Definition: bitSet.h:26
bool isOK() const
Definition: status.h:95
ChannelPut::shared_pointer op
Definition: pvAccess.cpp:132
void registerRefTrackRPC()
Definition: clientRPC.cpp:179
shared_ptr< T > const_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
Definition: shared_ptr.hpp:798
C++ and C descriptions for a thread.
epicsTimeStamp started
Definition: epicsUnitTest.c:52
It worked!
Definition: client.h:93
#define FINAL
Definition: pvAccess.h:48
See Client API API.
Definition: client.cpp:30