This is Unofficial EPICS BASE Doxygen Site
pvAccess.cpp
Go to the documentation of this file.
1 
7 #include <epicsMutex.h>
8 #include <epicsGuard.h>
9 #include <pv/reftrack.h>
10 #include <pv/valueBuilder.h>
11 #include <pv/epicsException.h>
12 
13 #define epicsExportSharedSymbols
14 #include <pv/pvAccess.h>
15 #include <pv/security.h>
16 
17 namespace pvd = epics::pvData;
18 
19 namespace epics {
20 namespace pvAccess {
21 
23 
24 const char* Channel::ConnectionStateNames[] = { "NEVER_CONNECTED", "CONNECTED", "DISCONNECTED", "DESTROYED" };
25 
26 Channel::Channel() {REFTRACE_INCREMENT(num_instances);}
27 Channel::~Channel() {REFTRACE_DECREMENT(num_instances);}
28 
30 {
31  std::tr1::shared_ptr<ChannelRequester> req(getChannelRequester());
32  return req ? req->getRequesterName() : std::string("<Destroy'd Channel>");
33 }
34 
35 void Channel::message(std::string const & message, epics::pvData::MessageType messageType)
36 {
37  std::tr1::shared_ptr<ChannelRequester> req(getChannelRequester());
38  if(req) {
39  req->message(message, messageType);
40  } else {
41  std::cerr<<epics::pvData::getMessageTypeName(messageType)
42  <<": on Destroy'd Channel \""<<getChannelName()
43  <<"\" : "<<message;
44  }
45 }
46 
48 
50 
51 void Channel::getField(GetFieldRequester::shared_pointer const & requester,std::string const & subField)
52 {
53  requester->getDone(pvd::Status(pvd::Status::STATUSTYPE_FATAL, "Not Implemented")
55 }
56 
57 AccessRights Channel::getAccessRights(epics::pvData::PVField::shared_pointer const & pvField)
58 {
59  return readWrite;
60 }
61 
62 namespace {
63 /* allow createChannelProcess() to use a ChannelPut w/o data */
64 struct Process2PutProxy : public ChannelProcess
65 {
66  struct Req : public ChannelPutRequester
67  {
68  const ChannelProcessRequester::weak_pointer requester; // was passed to createChannelProcess()
69  const std::tr1::weak_ptr<Process2PutProxy> operation; // enclosing Process2PutProxy
70 
73 
74  Req(const ChannelProcessRequester::weak_pointer& req,
75  const std::tr1::weak_ptr<Process2PutProxy>& op)
76  :requester(req), operation(op)
77  {}
78  virtual ~Req() {}
79 
80  virtual std::string getRequesterName() OVERRIDE FINAL {
81  ChannelProcessRequester::shared_pointer req(requester.lock());
82  return req ? req->getRequesterName() : "";
83  }
84 
85  virtual void channelDisconnect(bool destroy) OVERRIDE FINAL {
87  {
88  epicsGuard<epicsMutex> G(mutex);
89  this->dummy.swap(dummy);
90  }
91  ChannelProcessRequester::shared_pointer req(requester.lock());
92  if(req)
93  req->channelDisconnect(destroy);
94  }
95 
96  virtual void channelPutConnect(
98  ChannelPut::shared_pointer const & channelPut,
99  epics::pvData::Structure::const_shared_pointer const & structure) OVERRIDE FINAL
100  {
101  epics::pvData::PVStructurePtr dummy(epics::pvData::getPVDataCreate()->createPVStructure(structure));
102  ChannelProcessRequester::shared_pointer req(requester.lock());
103  std::tr1::shared_ptr<Process2PutProxy> op(operation.lock());
104  if(!op) return;
105  {
106  epicsGuard<epicsMutex> G(mutex);
107  this->dummy = dummy;
108  op->op = channelPut;
109  }
110  if(req)
111  req->channelProcessConnect(status, op);
112  }
113 
114  virtual void putDone(
115  const epics::pvData::Status& status,
116  ChannelPut::shared_pointer const & channelPut) OVERRIDE FINAL
117  {
118  ChannelProcessRequester::shared_pointer req(requester.lock());
119  std::tr1::shared_ptr<Process2PutProxy> op(operation.lock());
120  if(req && op)
121  req->processDone(status, op);
122  }
123 
124  virtual void getDone(
125  const epics::pvData::Status& status,
126  ChannelPut::shared_pointer const & channelPut,
127  epics::pvData::PVStructure::shared_pointer const & pvStructure,
128  epics::pvData::BitSet::shared_pointer const & bitSet) OVERRIDE FINAL
129  { /* never called */ }
130  };
131 
132  ChannelPut::shared_pointer op; // the op we wrap
133  std::tr1::shared_ptr<Req> op_request; // keep our Req alive
134 
136 
137  Process2PutProxy() :empty(new epics::pvData::BitSet) {}
138  virtual ~Process2PutProxy() {}
139 
140  virtual void destroy() OVERRIDE FINAL
141  { op->destroy(); }
142  virtual std::tr1::shared_ptr<Channel> getChannel() OVERRIDE FINAL
143  { return op->getChannel(); }
144  virtual void cancel() OVERRIDE FINAL
145  { op->cancel(); }
146  virtual void lastRequest() OVERRIDE FINAL
147  { op->lastRequest(); }
148  virtual void process() OVERRIDE FINAL
149  {
151  {
152  epicsGuard<epicsMutex> G(op_request->mutex);
153  blob = op_request->dummy;
154  }
155  if(!blob) {
156  ChannelProcessRequester::shared_pointer req(op_request->requester.lock());
157  ChannelProcess::shared_pointer op(op_request->operation.lock());
158  req->processDone(epics::pvData::Status::error("Not connected"), op);
159  } else {
160  empty->clear();
161  op->put(blob, empty);
162  }
163  }
164 };
165 }//namespace
166 
167 ChannelProcess::shared_pointer Channel::createChannelProcess(
168  ChannelProcessRequester::shared_pointer const & requester,
169  epics::pvData::PVStructure::shared_pointer const & pvRequestx)
170 {
171  pvd::PVStructure::shared_pointer pvRequest(pvRequestx);
172  std::tr1::shared_ptr<Process2PutProxy> ret(new Process2PutProxy);
173  ret->op_request.reset(new Process2PutProxy::Req(requester, ret));
174 
175  // inject record._options.process=true if client hasn't provided
176  if(!pvRequest->getSubField("record._options.process"))
177  {
178  pvRequest = pvd::ValueBuilder(*pvRequest)
179  .addNested("record")
180  .addNested("_options")
181  .add<pvd::pvString>("process", "true")
182  .endNested()
183  .endNested()
184  .buildPVStructure();
185  }
186 
187  ChannelPut::shared_pointer op(createChannelPut(ret->op_request, pvRequest));
188  if(!op) {
189  ret.reset();
190  } else {
191  epicsGuard<epicsMutex> G(ret->op_request->mutex);
192  ret->op = op;
193  }
194 
195  return ret;
196 }
197 
198 namespace {
201 struct Get2PutProxy : public ChannelGet
202 {
203  struct Req : public ChannelPutRequester
204  {
205  const ChannelGetRequester::weak_pointer requester; // was passed to createChannelGet()
206  const std::tr1::weak_ptr<Get2PutProxy> operation; // enclosing Get2PutProxy
207 
209 
210  Req(const ChannelGetRequester::weak_pointer& req,
211  const std::tr1::weak_ptr<Get2PutProxy>& op)
212  :requester(req), operation(op)
213  {}
214  virtual ~Req() {}
215 
216  virtual std::string getRequesterName() OVERRIDE FINAL {
217  ChannelGetRequester::shared_pointer req(requester.lock());
218  return req ? req->getRequesterName() : "";
219  }
220 
221  virtual void message(const std::string &message, MessageType messageType) OVERRIDE FINAL {
222  ChannelGetRequester::shared_pointer req(requester.lock());
223  if(req)
224  req->message(message, messageType);
225  else
226  ChannelPutRequester::message(message, messageType);
227  }
228 
229  virtual void channelDisconnect(bool destroy) OVERRIDE FINAL {
230  ChannelGetRequester::shared_pointer req(requester.lock());
231  if(req)
232  req->channelDisconnect(destroy);
233  }
234 
235  virtual void channelPutConnect(
237  ChannelPut::shared_pointer const & channelPut,
238  epics::pvData::Structure::const_shared_pointer const & structure) OVERRIDE FINAL
239  {
240  ChannelGetRequester::shared_pointer req(requester.lock());
241  std::tr1::shared_ptr<Get2PutProxy> op(operation.lock());
242  if(!op) return;
243  {
244  epicsGuard<epicsMutex> G(mutex);
245  op->op = channelPut;
246  }
247  if(req)
248  req->channelGetConnect(status, op, structure);
249  }
250 
251  virtual void putDone(
252  const epics::pvData::Status& status,
253  ChannelPut::shared_pointer const & channelPut) OVERRIDE FINAL
254  { /* never called */ }
255 
256  virtual void getDone(
257  const epics::pvData::Status& status,
258  ChannelPut::shared_pointer const & channelPut,
259  epics::pvData::PVStructure::shared_pointer const & pvStructure,
260  epics::pvData::BitSet::shared_pointer const & bitSet) OVERRIDE FINAL
261  {
262  ChannelGetRequester::shared_pointer req(requester.lock());
263  std::tr1::shared_ptr<Get2PutProxy> op(operation.lock());
264  if(req && op)
265  req->getDone(status, op, pvStructure, bitSet);
266  }
267  };
268 
269  ChannelPut::shared_pointer op; // the put we wrap
270  std::tr1::shared_ptr<Get2PutProxy::Req> op_request; // keep our Req alive
271 
272  ChannelPut::shared_pointer OP() {
273  epicsGuard<epicsMutex> G(op_request->mutex);
274  return op;
275  }
276 
277  Get2PutProxy() {}
278  virtual ~Get2PutProxy() {}
279 
280  virtual void destroy() OVERRIDE FINAL
281  {
282  ChannelPut::shared_pointer O(OP());
283  if(O) O->destroy();
284  }
285  virtual std::tr1::shared_ptr<Channel> getChannel() OVERRIDE FINAL
286  {
287  ChannelPut::shared_pointer O(OP());
288  return O ? O->getChannel() : std::tr1::shared_ptr<Channel>();
289  }
290  virtual void cancel() OVERRIDE FINAL
291  {
292  ChannelPut::shared_pointer O(OP());
293  if(O) O->cancel();
294  }
295  virtual void lastRequest() OVERRIDE FINAL
296  {
297  ChannelPut::shared_pointer O(OP());
298  if(O) O->lastRequest();
299  }
300  virtual void get() OVERRIDE FINAL
301  {
302  ChannelPut::shared_pointer O(OP());
303  if(O) O->get();
304  }
305 };
306 }// namespace
307 
308 ChannelGet::shared_pointer Channel::createChannelGet(
309  ChannelGetRequester::shared_pointer const & requester,
310  epics::pvData::PVStructure::shared_pointer const & pvRequest)
311 {
312  std::tr1::shared_ptr<Get2PutProxy> ret(new Get2PutProxy);
313  ret->op_request.reset(new Get2PutProxy::Req(requester, ret));
314 
315  ChannelPut::shared_pointer op(createChannelPut(ret->op_request, pvRequest));
316  if(!op) {
317  ret.reset();
318  } else {
319  epicsGuard<epicsMutex> G(ret->op_request->mutex);
320  ret->op = op;
321  }
322 
323  return ret;
324 }
325 
326 ChannelPut::shared_pointer Channel::createChannelPut(
327  ChannelPutRequester::shared_pointer const & requester,
328  epics::pvData::PVStructure::shared_pointer const & pvRequest)
329 {
330  ChannelPut::shared_pointer ret;
331  requester->channelPutConnect(pvd::Status(pvd::Status::STATUSTYPE_FATAL, "Not Implemented"),
332  ret, pvd::StructureConstPtr());
333  return ret;
334 }
335 
336 ChannelPutGet::shared_pointer Channel::createChannelPutGet(
337  ChannelPutGetRequester::shared_pointer const & requester,
338  epics::pvData::PVStructure::shared_pointer const & pvRequest)
339 {
340  ChannelPutGet::shared_pointer ret;
341  requester->channelPutGetConnect(pvd::Status(pvd::Status::STATUSTYPE_FATAL, "Not Implemented"),
343  return ret;
344 }
345 
346 ChannelRPC::shared_pointer Channel::createChannelRPC(
347  ChannelRPCRequester::shared_pointer const & requester,
348  epics::pvData::PVStructure::shared_pointer const & pvRequest)
349 {
350  ChannelRPC::shared_pointer ret;
351  requester->channelRPCConnect(pvd::Status(pvd::Status::STATUSTYPE_FATAL, "Not Implemented"), ret);
352  return ret;
353 }
354 
355 pvd::Monitor::shared_pointer Channel::createMonitor(
356  epics::pvAccess::MonitorRequester::shared_pointer const & requester,
357  epics::pvData::PVStructure::shared_pointer const & pvRequest)
358 {
359  pvd::Monitor::shared_pointer ret;
360  requester->monitorConnect(pvd::Status(pvd::Status::STATUSTYPE_FATAL, "Not Implemented"),
361  ret, pvd::StructureConstPtr());
362  return ret;
363 }
364 
365 ChannelArray::shared_pointer Channel::createChannelArray(
366  ChannelArrayRequester::shared_pointer const & requester,
367  epics::pvData::PVStructure::shared_pointer const & pvRequest)
368 {
369  ChannelArray::shared_pointer ret;
370  requester->channelArrayConnect(pvd::Status(pvd::Status::STATUSTYPE_FATAL, "Not Implemented"),
371  ret, pvd::Array::const_shared_pointer());
372  return ret;
373 }
374 
376 
378 {
379  REFTRACE_INCREMENT(num_instances);
380 }
381 
383 {
384  REFTRACE_DECREMENT(num_instances);
385 }
386 
388 
390 
392 {
393  REFTRACE_INCREMENT(num_instances);
394 }
395 
397 {
398  REFTRACE_DECREMENT(num_instances);
399 }
400 
402 
404 {
405  REFTRACE_INCREMENT(num_instances);
406 }
407 
409 {
410  REFTRACE_DECREMENT(num_instances);
411 }
412 
414 
416 {
417  REFTRACE_INCREMENT(num_instances);
418 }
419 
421 {
422  REFTRACE_DECREMENT(num_instances);
423 }
424 
425 PeerInfo::const_shared_pointer ChannelRequester::getPeerInfo()
426 {
427  return PeerInfo::const_shared_pointer();
428 }
429 
430 std::string DefaultChannelRequester::getRequesterName() { return "DefaultChannelRequester"; }
431 
432 void DefaultChannelRequester::channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel)
433 {
434  if(!status.isSuccess()) {
435  std::ostringstream strm;
436  status.dump(strm);
437  throw std::runtime_error(strm.str());
438  }
439 }
440 
441 void DefaultChannelRequester::channelStateChange(Channel::shared_pointer const & channel, Channel::ConnectionState connectionState)
442 { /* no-op */ }
443 
444 ChannelRequester::shared_pointer DefaultChannelRequester::build()
445 {
446  ChannelRequester::shared_pointer ret(new DefaultChannelRequester);
447  return ret;
448 }
449 
451  : pvStructurePtr(pvStructurePtr)
452  ,changedBitSet(epics::pvData::BitSet::create(static_cast<epics::pvData::uint32>(pvStructurePtr->getNumberFields())))
453  ,overrunBitSet(epics::pvData::BitSet::create(static_cast<epics::pvData::uint32>(pvStructurePtr->getNumberFields())))
454 {}
455 
456 }} // namespace epics::pvAccess
457 
458 namespace {
459 
460 struct DummyChannelFind : public epics::pvAccess::ChannelFind {
461  epics::pvAccess::ChannelProvider::weak_pointer provider;
462  DummyChannelFind(const epics::pvAccess::ChannelProvider::shared_pointer& provider) : provider(provider) {}
463  virtual ~DummyChannelFind() {}
464  virtual void destroy() OVERRIDE FINAL {}
465  virtual epics::pvAccess::ChannelProvider::shared_pointer getChannelProvider() OVERRIDE FINAL { return provider.lock(); }
466  virtual void cancel() OVERRIDE FINAL {}
467 };
468 
469 }
470 
471 namespace epics {namespace pvAccess {
472 
473 ChannelFind::shared_pointer ChannelFind::buildDummy(const ChannelProvider::shared_pointer& provider)
474 {
475  std::tr1::shared_ptr<DummyChannelFind> ret(new DummyChannelFind(provider));
476  return ret;
477 }
478 
479 }} // namespace epics::pvAccess
epics::pvData::BitSetPtr empty
Definition: pvAccess.cpp:135
void dump(std::ostream &o) const
Definition: status.cpp:83
epicsShareExtern std::string getMessageTypeName(MessageType messageType)
Definition: requester.cpp:25
virtual std::tr1::shared_ptr< const PeerInfo > getPeerInfo()
Return information on connected peer if applicable.
Definition: pvAccess.cpp:425
virtual std::string getRequesterName() OVERRIDE FINAL
Definition: pvAccess.cpp:430
pvd::Status status
static Status error(const std::string &m)
Definition: status.h:50
ValueBuilder & addNested(const std::string &name, Type type=structure, const std::string &id=std::string())
Start a sub-structure.
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
A vector of bits.
Definition: bitSet.h:56
virtual void getField(GetFieldRequester::shared_pointer const &requester, std::string const &subField)
Definition: pvAccess.cpp:51
#define OVERRIDE
Definition: pvAccess.h:55
const std::tr1::weak_ptr< Process2PutProxy > operation
Definition: pvAccess.cpp:69
static size_t num_instances
Definition: pvAccess.h:895
std::tr1::shared_ptr< Req > op_request
Definition: pvAccess.cpp:133
Used when ChannelProvider::createChannel() is passed a NULL ChannelRequester.
Definition: pvAccess.h:1209
MonitorElement(epics::pvData::PVStructurePtr const &pvStructurePtr)
Definition: pvAccess.cpp:450
virtual AccessRights getAccessRights(epics::pvData::PVField::shared_pointer const &pvField)
Definition: pvAccess.cpp:57
pvData
Definition: monitor.h:428
virtual Monitor::shared_pointer createMonitor(MonitorRequester::shared_pointer const &requester, epics::pvData::PVStructure::shared_pointer const &pvRequest)
Definition: pvAccess.cpp:355
static const char * ConnectionStateNames[]
Definition: pvAccess.h:910
virtual ChannelPutGet::shared_pointer createChannelPutGet(ChannelPutGetRequester::shared_pointer const &requester, epics::pvData::PVStructure::shared_pointer const &pvRequest)
Definition: pvAccess.cpp:336
epicsMutex mutex
Definition: pvAccess.cpp:71
APIs for the epicsMutex mutual exclusion semaphore.
const ChannelProcessRequester::weak_pointer requester
Definition: pvAccess.cpp:68
bool isSuccess() const
Definition: status.h:103
static ChannelFind::shared_pointer buildDummy(const std::tr1::shared_ptr< ChannelProvider > &provider)
Definition: pvAccess.cpp:473
virtual ChannelPut::shared_pointer createChannelPut(ChannelPutRequester::shared_pointer const &requester, epics::pvData::PVStructure::shared_pointer const &pvRequest)
Definition: pvAccess.cpp:326
virtual std::tr1::shared_ptr< ChannelRequester > getChannelRequester()=0
std::tr1::shared_ptr< const Field > FieldConstPtr
Definition: pvIntrospect.h:137
virtual ChannelArray::shared_pointer createChannelArray(ChannelArrayRequester::shared_pointer const &requester, epics::pvData::PVStructure::shared_pointer const &pvRequest)
Definition: pvAccess.cpp:365
FORCE_INLINE ValueBuilder & add(const std::string &name, typename meta::arg_type< typename ScalarTypeTraits< ENUM >::type >::type V)
Add a scalar field with a given name and initial value.
Definition: valueBuilder.h:42
virtual std::string getChannelName()=0
epics::pvData::PVStructurePtr dummy
Definition: pvAccess.cpp:72
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
virtual ChannelGet::shared_pointer createChannelGet(ChannelGetRequester::shared_pointer const &requester, epics::pvData::PVStructure::shared_pointer const &pvRequest)
Definition: pvAccess.cpp:308
virtual void message(std::string const &message, epics::pvData::MessageType messageType)
Definition: pvAccess.cpp:35
virtual ChannelRPC::shared_pointer createChannelRPC(ChannelRPCRequester::shared_pointer const &requester, epics::pvData::PVStructure::shared_pointer const &pvRequest)
Definition: pvAccess.cpp:346
virtual void channelCreated(const epics::pvData::Status &status, Channel::shared_pointer const &channel) OVERRIDE FINAL
Definition: pvAccess.cpp:432
std::tr1::shared_ptr< BitSet > BitSetPtr
Definition: bitSet.h:26
virtual void channelStateChange(Channel::shared_pointer const &channel, Channel::ConnectionState connectionState) OVERRIDE FINAL
Definition: pvAccess.cpp:441
virtual ConnectionState getConnectionState()
Definition: pvAccess.cpp:47
ChannelPut::shared_pointer op
Definition: pvAccess.cpp:132
#define OP(ENUM, TYPE)
virtual std::string getRequesterName()
Definition: pvAccess.cpp:29
virtual bool isConnected()
Definition: pvAccess.cpp:49
virtual ChannelProcess::shared_pointer createChannelProcess(ChannelProcessRequester::shared_pointer const &requester, epics::pvData::PVStructure::shared_pointer const &pvRequest)
Definition: pvAccess.cpp:167
static ChannelRequester::shared_pointer build()
Definition: pvAccess.cpp:444
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
Definition: pvData.h:1648
#define FINAL
Definition: pvAccess.h:48
uint32_t uint32
Definition: pvType.h:99