This is Unofficial EPICS BASE Doxygen Site
sharedstate_channel.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 <list>
7 
8 #include <epicsMutex.h>
9 #include <epicsGuard.h>
10 #include <errlog.h>
11 
12 #include <shareLib.h>
13 #include <pv/sharedPtr.h>
14 #include <pv/noDefaultMethods.h>
15 #include <pv/sharedVector.h>
16 #include <pv/bitSet.h>
17 #include <pv/pvData.h>
18 #include <pv/createRequest.h>
19 #include <pv/status.h>
20 #include <pv/reftrack.h>
21 
22 #define epicsExportSharedSymbols
23 #include "sharedstateimpl.h"
24 
25 namespace pvas {
26 namespace detail {
27 
29 
30 
31 SharedChannel::SharedChannel(const std::tr1::shared_ptr<SharedPV> &owner,
32  const pva::ChannelProvider::shared_pointer provider,
33  const std::string& channelName,
34  const requester_type::shared_pointer& requester)
35  :owner(owner)
36  ,channelName(channelName)
37  ,requester(requester)
38  ,provider(provider)
39  ,dead(false)
40 {
41  REFTRACE_INCREMENT(num_instances);
42 
43  if(owner->debugLvl>5) {
44  errlogPrintf("%s : Open channel to %s > %p\n",
45  requester->getRequesterName().c_str(),
46  channelName.c_str(),
47  this);
48  }
49 
50  {
51  Guard G(owner->mutex);
52  owner->channels.push_back(this);
53  }
54 }
55 
57 {
58  destroy();
59  REFTRACE_DECREMENT(num_instances);
60 }
61 
63 {
64  std::tr1::shared_ptr<SharedPV::Handler> handler;
65  {
66  Guard G(owner->mutex);
67 
68  if(dead) return;
69  dead = true;
70 
71  bool wasempty = owner->channels.empty();
72  owner->channels.remove(this);
73  if(!wasempty && owner->channels.empty() && owner->notifiedConn) {
74  handler = owner->handler;
75  owner->notifiedConn = false;
76  }
77  }
78  if(handler) {
79  handler->onLastDisconnect(owner);
80  }
81  if(owner->debugLvl>5)
82  {
83  pva::ChannelRequester::shared_pointer req(requester.lock());
84  errlogPrintf("%s : Close channel to %s > %p\n",
85  req ? req->getRequesterName().c_str() : "<Defunct>",
86  channelName.c_str(),
87  this);
88  }
89 }
90 
91 std::tr1::shared_ptr<pva::ChannelProvider> SharedChannel::getProvider()
92 {
93  return provider.lock();
94 }
95 
97 {
98  return getChannelName(); // for lack of anything better to do...
99 }
100 
102 {
103  return channelName;
104 }
105 
106 std::tr1::shared_ptr<pva::ChannelRequester> SharedChannel::getChannelRequester()
107 {
108  return requester.lock();
109 }
110 
111 void SharedChannel::getField(pva::GetFieldRequester::shared_pointer const & requester,std::string const & subField)
112 {
113  pvd::FieldConstPtr desc;
114  pvd::Status sts;
115  SharedPV::Handler::shared_pointer handler;
116  {
117  Guard G(owner->mutex);
118  if(dead) {
119  sts = pvd::Status::error("Dead Channel");
120 
121  } else {
122  if(owner->type) {
123  desc = owner->type;
124  }
125 
126  if(!owner->channels.empty() && !owner->notifiedConn) {
127  handler = owner->handler;
128  owner->notifiedConn = true;
129  }
130  owner->getfields.push_back(requester);
131  }
132  }
133  if(desc || !sts.isOK()) {
134  requester->getDone(sts, desc);
135  }
136  if(handler) {
137  handler->onFirstConnect(owner);
138  }
139 }
140 
141 pva::ChannelPut::shared_pointer SharedChannel::createChannelPut(
142  pva::ChannelPutRequester::shared_pointer const & requester,
143  pvd::PVStructure::shared_pointer const & pvRequest)
144 {
145  std::tr1::shared_ptr<SharedPut> ret(new SharedPut(shared_from_this(), requester, pvRequest));
146 
148  pvd::Status sts;
149  std::string warning;
150  SharedPV::Handler::shared_pointer handler;
151  try {
152  {
153  Guard G(owner->mutex);
154  if(dead) {
155  sts = pvd::Status::error("Dead Channel");
156 
157  } else {
158  // ~SharedPut removes
159  owner->puts.push_back(ret.get());
160  if(owner->current) {
161  ret->mapper.compute(*owner->current, *pvRequest, owner->config.mapperMode);
162  type = ret->mapper.requested();
163  warning = ret->mapper.warnings();
164  }
165 
166  if(!owner->channels.empty() && !owner->notifiedConn) {
167  handler = owner->handler;
168  owner->notifiedConn = true;
169  }
170  }
171  }
172  if(!warning.empty())
173  requester->message(warning, pvd::warningMessage);
174  if(type || !sts.isOK())
175  requester->channelPutConnect(sts, ret, type);
176  }catch(std::runtime_error& e){
177  ret.reset();
178  type.reset();
179  requester->channelPutConnect(pvd::Status::error(e.what()), ret, type);
180  }
181  if(handler) {
182  handler->onFirstConnect(owner);
183  }
184  return ret;
185 }
186 
187 pva::ChannelRPC::shared_pointer SharedChannel::createChannelRPC(
188  pva::ChannelRPCRequester::shared_pointer const & requester,
189  pvd::PVStructure::shared_pointer const & pvRequest)
190 {
191  std::tr1::shared_ptr<SharedRPC> ret(new SharedRPC(shared_from_this(), requester, pvRequest));
192  ret->connected = true;
193 
194  pvd::Status sts;
195  {
196  Guard G(owner->mutex);
197  if(dead) {
198  sts = pvd::Status::error("Dead Channel");
199 
200  } else {
201  owner->rpcs.push_back(ret.get());
202  }
203  }
204  requester->channelRPCConnect(sts, ret);
205  return ret;
206 }
207 
208 pva::Monitor::shared_pointer SharedChannel::createMonitor(
209  pva::MonitorRequester::shared_pointer const & requester,
210  pvd::PVStructure::shared_pointer const & pvRequest)
211 {
213  SharedPV::Handler::shared_pointer handler;
214  mconf.dropEmptyUpdates = owner->config.dropEmptyUpdates;
215  mconf.mapperMode = owner->config.mapperMode;
216 
217  std::tr1::shared_ptr<SharedMonitorFIFO> ret(new SharedMonitorFIFO(shared_from_this(), requester, pvRequest, &mconf));
218 
219  bool notify;
220  pvd::Status sts;
221  {
222  Guard G(owner->mutex);
223  if(dead) {
224  sts = pvd::Status::error("Dead Channel");
225  notify = false;
226 
227  } else {
228  owner->monitors.push_back(ret.get());
229  notify = !!owner->type;
230  if(notify) {
231  ret->open(owner->type);
232  // post initial update
233  ret->post(*owner->current, owner->valid);
234  }
235 
236  if(!owner->channels.empty() && !owner->notifiedConn) {
237  handler = owner->handler;
238  owner->notifiedConn = true;
239  }
240  }
241  }
242  if(!sts.isOK()) {
243  requester->monitorConnect(sts, pvd::MonitorPtr(), pvd::StructureConstPtr());
244  ret.reset();
245 
246  } else {
247  if(notify) {
248  ret->notify();
249  }
250  if(handler) {
251  handler->onFirstConnect(owner);
252  }
253  }
254  return ret;
255 }
256 
257 
258 SharedMonitorFIFO::SharedMonitorFIFO(const std::tr1::shared_ptr<SharedChannel>& channel,
259  const requester_type::shared_pointer& requester,
260  const pvd::PVStructure::const_shared_pointer &pvRequest,
261  Config *conf)
262  :pva::MonitorFIFO(requester, pvRequest, pva::MonitorFIFO::Source::shared_pointer(), conf)
263  ,channel(channel)
264 {}
265 
267 {
268  Guard G(channel->owner->mutex);
269  channel->owner->monitors.remove(this);
270 }
271 
272 } // namespace detail
273 
274 Operation::Operation(const std::tr1::shared_ptr<Impl> impl)
275  :impl(impl)
276 {}
277 
279 {
280  return *impl->pvRequest;
281 }
282 
284 {
285  return *impl->value;
286 }
287 
289 {
290  return impl->changed;
291 }
292 
293 std::string Operation::channelName() const
294 {
295  std::string ret;
296  std::tr1::shared_ptr<epics::pvAccess::Channel> chan(impl->getChannel());
297  if(chan) {
298  ret = chan->getChannelName();
299  }
300  return ret;
301 }
302 
304 {
305  return impl->info ? impl->info.get() : 0;
306 }
307 
309 {
310  impl->complete(pvd::Status(), 0);
311 }
312 
314 {
315  impl->complete(sts, 0);
316 }
317 
319  const epics::pvData::BitSet &changed)
320 {
321  impl->complete(pvd::Status(), &value);
322 }
323 
324 void Operation::info(const std::string& msg)
325 {
326  pva::ChannelBaseRequester::shared_pointer req(impl->getRequester());
327  if(req)
328  req->message(msg, pvd::infoMessage);
329 }
330 
331 void Operation::warn(const std::string& msg)
332 {
333  pva::ChannelBaseRequester::shared_pointer req(impl->getRequester());
334  if(req)
335  req->message(msg, pvd::warningMessage);
336 }
337 
339 {
340  Guard G(impl->mutex);
341  return impl->debugLvl;
342 }
343 
344 std::tr1::shared_ptr<epics::pvAccess::Channel> Operation::getChannel()
345 {
346  return impl->getChannel();
347 }
348 
349 std::tr1::shared_ptr<pva::ChannelBaseRequester> Operation::getRequester()
350 {
351  return impl->getRequester();
352 }
353 
354 bool Operation::valid() const
355 {
356  return !!impl;
357 }
358 
360  bool err;
361  {
362  Guard G(impl->mutex);
363  err = !impl->done;
364  }
365  if(err)
366  impl->complete(pvd::Status::error("Implicit Cancel"), 0);
367 
368  delete impl;
369 }
370 
371 } // namespace pvas
virtual void destroy() OVERRIDE FINAL
std::tr1::shared_ptr< epics::pvAccess::ChannelBaseRequester > getRequester()
Definition: link.h:174
virtual std::tr1::shared_ptr< pva::ChannelRequester > getChannelRequester() OVERRIDE FINAL
const requester_type::weak_pointer requester
Information provded by a client to a server-type ChannelProvider.
Definition: security.h:119
static Status error(const std::string &m)
Definition: status.h:50
std::tr1::shared_ptr< epics::pvAccess::Channel > getChannel()
pvd::StructureConstPtr type
virtual pva::ChannelRPC::shared_pointer createChannelRPC(pva::ChannelRPCRequester::shared_pointer const &requester, pvd::PVStructure::shared_pointer const &pvRequest) OVERRIDE FINAL
void warn(const std::string &)
Send warning message to client. Does not complete().
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
A vector of bits.
Definition: bitSet.h:56
Mark external symbols and entry points for shared libraries.
epics::pvData::PVRequestMapper::mode_t mapperMode
default Mask.
Definition: monitor.h:279
Holds all PVA related.
Definition: pvif.h:34
const std::tr1::shared_ptr< SharedPV > owner
virtual pva::ChannelPut::shared_pointer createChannelPut(pva::ChannelPutRequester::shared_pointer const &requester, pvd::PVStructure::shared_pointer const &pvRequest) OVERRIDE FINAL
SharedMonitorFIFO(const std::tr1::shared_ptr< SharedChannel > &channel, const requester_type::shared_pointer &requester, const pvd::PVStructure::const_shared_pointer &pvRequest, Config *conf)
APIs for the epicsMutex mutual exclusion semaphore.
const epics::pvData::PVStructure & pvRequest() const
pvRequest blob, may be used to modify handling.
virtual void getField(pva::GetFieldRequester::shared_pointer const &requester, std::string const &subField) OVERRIDE FINAL
const ChannelProcessRequester::weak_pointer requester
Definition: pvAccess.cpp:68
virtual std::tr1::shared_ptr< pva::ChannelProvider > getProvider() OVERRIDE FINAL
Operation()
create empty op for later assignment
Definition: sharedstate.h:239
virtual void complete(const pvd::Status &sts, const epics::pvData::PVStructure *value)=0
const epics::pvAccess::PeerInfo * peer() const
See Server API API.
const pva::ChannelProvider::weak_pointer provider
Data interface for a structure,.
Definition: pvData.h:712
std::tr1::shared_ptr< const Field > FieldConstPtr
Definition: pvIntrospect.h:137
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
virtual std::string getChannelName() OVERRIDE FINAL
virtual std::string getRemoteAddress() OVERRIDE FINAL
std::string channelName() const
The name of the channel through which this request was made (eg. for logging purposes).
const std::string channelName
const epics::pvData::BitSet & changed() const
Applies to value(). Which fields of input data are actual valid. Others should not be used...
void info(const std::string &)
Send info message to client. Does not complete().
bool isOK() const
Definition: status.h:95
SharedChannel(const std::tr1::shared_ptr< SharedPV > &owner, const pva::ChannelProvider::shared_pointer provider, const std::string &channelName, const requester_type::shared_pointer &requester)
const std::tr1::shared_ptr< SharedChannel > channel
bool dropEmptyUpdates
default true. Drop updates which don&#39;t include an field values.
Definition: monitor.h:278
#define false
Definition: flexdef.h:85
std::tr1::shared_ptr< Monitor > MonitorPtr
Definition: monitor.h:44
virtual pva::Monitor::shared_pointer createMonitor(pva::MonitorRequester::shared_pointer const &requester, pvd::PVStructure::shared_pointer const &pvRequest) OVERRIDE FINAL
const epics::pvData::PVStructure & value() const