This is Unofficial EPICS BASE Doxygen Site
pvaClientPut.cpp
Go to the documentation of this file.
1 /* pvaClientPut.cpp */
12 #include <pv/event.h>
13 
14 #define epicsExportSharedSymbols
15 
16 #include <pv/pvaClient.h>
17 
18 using namespace epics::pvData;
19 using namespace epics::pvAccess;
20 using namespace std;
21 
22 namespace epics { namespace pvaClient {
23 
25 {
26  PvaClientPut::weak_pointer pvaClientPut;
27  PvaClient::weak_pointer pvaClient;
28 public:
30  PvaClientPutPtr const & pvaClientPut,
31  PvaClientPtr const &pvaClient)
32  : pvaClientPut(pvaClientPut),
33  pvaClient(pvaClient)
34  {}
36  if(PvaClient::getDebug()) std::cout << "~ChannelPutRequesterImpl" << std::endl;
37  }
38 
39  virtual std::string getRequesterName() {
40  PvaClientPutPtr clientPut(pvaClientPut.lock());
41  if(!clientPut) return string("clientPut is null");
42  return clientPut->getRequesterName();
43  }
44 
45  virtual void message(std::string const & message, epics::pvData::MessageType messageType) {
46  PvaClientPutPtr clientPut(pvaClientPut.lock());
47  if(!clientPut) return;
48  clientPut->message(message,messageType);
49  }
50 
51  virtual void channelPutConnect(
52  const Status& status,
53  ChannelPut::shared_pointer const & channelPut,
54  Structure::const_shared_pointer const & structure)
55  {
56  PvaClientPutPtr clientPut(pvaClientPut.lock());
57  if(!clientPut) return;
58  clientPut->channelPutConnect(status,channelPut,structure);
59  }
60 
61  virtual void getDone(
62  const Status& status,
63  ChannelPut::shared_pointer const & channelPut,
64  PVStructurePtr const & pvStructure,
65  BitSet::shared_pointer const & bitSet)
66  {
67  PvaClientPutPtr clientPut(pvaClientPut.lock());
68  if(!clientPut) return;
69  clientPut->getDone(status,channelPut,pvStructure,bitSet);
70  }
71 
72  virtual void putDone(
73  const Status& status,
74  ChannelPut::shared_pointer const & channelPut)
75  {
76  PvaClientPutPtr clientPut(pvaClientPut.lock());
77  if(!clientPut) return;
78  clientPut->putDone(status,channelPut);
79  }
80 };
81 
82 PvaClientPutPtr PvaClientPut::create(
83  PvaClientPtr const &pvaClient,
84  PvaClientChannelPtr const & pvaClientChannel,
85  PVStructurePtr const &pvRequest)
86 {
87  PvaClientPutPtr clientPut(new PvaClientPut(pvaClient,pvaClientChannel,pvRequest));
88  clientPut->channelPutRequester = ChannelPutRequesterImplPtr(
89  new ChannelPutRequesterImpl(clientPut,pvaClient));
90  return clientPut;
91 }
92 
93 
94 PvaClientPut::PvaClientPut(
95  PvaClientPtr const &pvaClient,
96  PvaClientChannelPtr const & pvaClientChannel,
97  PVStructurePtr const &pvRequest)
98 : pvaClient(pvaClient),
99  pvaClientChannel(pvaClientChannel),
100  pvRequest(pvRequest),
101  connectState(connectIdle),
102  putState(putIdle)
103 {
104  if(PvaClient::getDebug()) {
105  cout<< "PvaClientPut::PvaClientPut"
106  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
107  << endl;
108  }
109 }
110 
111 PvaClientPut::~PvaClientPut()
112 {
113  if(PvaClient::getDebug()) {
114  cout<< "PvaClientPut::~PvaClientPut"
115  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
116  << endl;
117  }
118 }
119 
120 
121 void PvaClientPut::checkConnectState()
122 {
123  if(PvaClient::getDebug()) {
124  cout << "PvaClientPut::checkConnectState"
125  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
126  << endl;
127  }
128  if(connectState==connectIdle){
129  connect();
130  }
131  if(connectState==connectActive){
132  string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
133  + " "
134  + channelPutConnectStatus.getMessage();
135  throw std::runtime_error(message);
136  }
137 }
138 
139 string PvaClientPut::getRequesterName()
140 {
141  PvaClientPtr yyy = pvaClient.lock();
142  if(!yyy) return string("PvaClientPut::getRequesterName() PvaClient isDestroyed");
143  return yyy->getRequesterName();
144 }
145 
146 void PvaClientPut::message(string const & message,MessageType messageType)
147 {
148  PvaClientPtr yyy = pvaClient.lock();
149  if(!yyy) return;
150  yyy->message(message, messageType);
151 }
152 
153 void PvaClientPut::channelPutConnect(
154  const Status& status,
155  ChannelPut::shared_pointer const & channelPut,
157 {
158  if(PvaClient::getDebug()) {
159  cout << "PvaClientPut::channelPutConnect"
160  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
161  << " status.isOK " << (status.isOK() ? "true" : "false")
162  << endl;
163  }
164  {
165  Lock xx(mutex);
166  this->channelPut = channelPut;
167  if(status.isOK()) {
168  channelPutConnectStatus = status;
169  connectState = connected;
170  pvaClientData = PvaClientPutData::create(structure);
171  pvaClientData->setMessagePrefix(channelPut->getChannel()->getChannelName());
172  } else {
173  stringstream ss;
174  ss << pvRequest;
175  string message = string("\nPvaClientPut::channelPutConnect)")
176  + "\npvRequest\n" + ss.str()
177  + "\nerror\n" + status.getMessage();
178  channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
179  }
180  }
181  PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
182  if(req) {
183  req->channelPutConnect(status,shared_from_this());
184  }
185  waitForConnect.signal();
186 
187 }
188 
189 void PvaClientPut::getDone(
190  const Status& status,
191  ChannelPut::shared_pointer const & channelPut,
192  PVStructurePtr const & pvStructure,
193  BitSetPtr const & bitSet)
194 {
195  if(PvaClient::getDebug()) {
196  cout << "PvaClientPut::getDone"
197  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
198  << " status.isOK " << (status.isOK() ? "true" : "false")
199  << endl;
200  }
201  {
202  Lock xx(mutex);
203  channelGetPutStatus = status;
204  if(status.isOK()) {
205  PVStructurePtr pvs = pvaClientData->getPVStructure();
206  pvs->copyUnchecked(*pvStructure,*bitSet);
207  BitSetPtr bs = pvaClientData->getChangedBitSet();
208  bs->clear();
209  *bs |= *bitSet;
210  putState = putComplete;
211  }
212  }
213  PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
214  if(req) {
215  req->getDone(status,shared_from_this());
216  }
217  waitForGetPut.signal();
218 }
219 
220 void PvaClientPut::putDone(
221  const Status& status,
222  ChannelPut::shared_pointer const & channelPut)
223 {
224  if(PvaClient::getDebug()) {
225  cout << "PvaClientPut::putDone"
226  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
227  << " status.isOK " << (status.isOK() ? "true" : "false")
228  << endl;
229  }
230  {
231  Lock xx(mutex);
232  channelGetPutStatus = status;
233  putState = putComplete;
234  }
235  PvaClientPutRequesterPtr req(pvaClientPutRequester.lock());
236  if(req) {
237  req->putDone(status,shared_from_this());
238  }
239  waitForGetPut.signal();
240 }
241 
242 void PvaClientPut::connect()
243 {
244  if(PvaClient::getDebug()) {
245  cout << "PvaClientPut::connect"
246  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
247  << endl;
248  }
249  issueConnect();
250  Status status = waitConnect();
251  if(status.isOK()) return;
252  string message = string("channel ")
253  + pvaClientChannel->getChannel()->getChannelName()
254  + " PvaClientPut::connect "
255  + status.getMessage();
256  throw std::runtime_error(message);
257 }
258 
259 void PvaClientPut::issueConnect()
260 {
261  if(PvaClient::getDebug()) {
262  cout << "PvaClientPut::issueConnect"
263  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
264  << endl;
265  }
266  if(connectState!=connectIdle) {
267  string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
268  + " pvaClientPut already connected ";
269  throw std::runtime_error(message);
270  }
271  connectState = connectActive;
272  channelPutConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active");
273  channelPut = pvaClientChannel->getChannel()->createChannelPut(channelPutRequester,pvRequest);
274 
275 }
276 
277 Status PvaClientPut::waitConnect()
278 {
279  if(PvaClient::getDebug()) {
280  cout << "PvaClientPut::waitConnect"
281  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
282  << endl;
283  }
284  {
285  Lock xx(mutex);
286  if(connectState==connected) {
287  if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
288  return channelPutConnectStatus;
289  }
290  if(connectState!=connectActive) {
291  string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
292  + " PvaClientPut::waitConnect illegal connect state ";
293  throw std::runtime_error(message);
294  }
295  }
296  waitForConnect.wait();
297  if(!channelPutConnectStatus.isOK()) connectState = connectIdle;
298  return channelPutConnectStatus;
299 }
300 
302 {
303  if(PvaClient::getDebug()) {
304  cout << "PvaClientPut::get"
305  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
306  << endl;
307  }
308  issueGet();
309  Status status = waitGet();
310  if(status.isOK()) return;
311  string message = string("channel ")
312  + pvaClientChannel->getChannel()->getChannelName()
313  + " PvaClientPut::get "
314  + status.getMessage();
315  throw std::runtime_error(message);
316 }
317 
318 void PvaClientPut::issueGet()
319 {
320  if(PvaClient::getDebug()) {
321  cout << "PvaClientPut::issueGet"
322  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
323  << endl;
324  }
325  if(connectState==connectIdle) connect();
326  if(putState==getActive || putState==putActive) {
327  string message = string("channel ")
328  + pvaClientChannel->getChannel()->getChannelName()
329  + "PvaClientPut::issueGet get or put aleady active ";
330  throw std::runtime_error(message);
331  }
332  putState = getActive;
333  channelPut->get();
334 }
335 
336 Status PvaClientPut::waitGet()
337 {
338  if(PvaClient::getDebug()) {
339  cout << "PvaClientPut::waitGet"
340  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
341  << endl;
342  }
343  {
344  Lock xx(mutex);
345  if(putState==putComplete) return channelGetPutStatus;
346  if(putState!=getActive){
347  string message = string("channel ")
348  + pvaClientChannel->getChannel()->getChannelName()
349  + " PvaClientPut::waitGet illegal put state";
350  throw std::runtime_error(message);
351  }
352  }
353  waitForGetPut.wait();
354  return channelGetPutStatus;
355 }
356 
358 {
359  if(PvaClient::getDebug()) {
360  cout << "PvaClientPut::put"
361  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
362  << endl;
363  }
364  issuePut();
365  Status status = waitPut();
366  if(status.isOK()) return;
367  string message = string("channel ")
368  + pvaClientChannel->getChannel()->getChannelName()
369  + " PvaClientPut::put "
370  + status.getMessage();
371  throw std::runtime_error(message);
372 }
373 
374 void PvaClientPut::issuePut()
375 {
376  if(PvaClient::getDebug()) {
377  cout << "PvaClientPut::issuePut"
378  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
379  << " pvStructure\n" << pvaClientData->getPVStructure()
380  << " bitSet " << *pvaClientData->getChangedBitSet() << endl
381  << endl;
382  }
383  if(connectState==connectIdle) connect();
384  if(putState==getActive || putState==putActive) {
385  string message = string("channel ")
386  + pvaClientChannel->getChannel()->getChannelName()
387  + "PvaClientPut::issuePut get or put aleady active ";
388  throw std::runtime_error(message);
389  }
390  putState = putActive;
391  channelPut->put(pvaClientData->getPVStructure(),pvaClientData->getChangedBitSet());
392 }
393 
394 Status PvaClientPut::waitPut()
395 {
396  if(PvaClient::getDebug()) {
397  cout << "PvaClientPut::waitPut"
398  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
399  << endl;
400  }
401  {
402  Lock xx(mutex);
403  if(putState==putComplete) return channelGetPutStatus;
404  if(putState!=putActive){
405  string message = string("channel ")
406  + pvaClientChannel->getChannel()->getChannelName()
407  + " PvaClientPut::waitPut illegal put state";
408  throw std::runtime_error(message);
409  }
410  }
411  waitForGetPut.wait();
412  if(channelGetPutStatus.isOK()) pvaClientData->getChangedBitSet()->clear();
413  return channelGetPutStatus;
414 }
415 
416 PvaClientPutDataPtr PvaClientPut::getData()
417 {
418  if(PvaClient::getDebug()) {
419  cout<< "PvaClientPut::getData"
420  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
421  << endl;
422  }
423  checkConnectState();
424  if(putState==putIdle) get();
425  return pvaClientData;
426 }
427 
428 void PvaClientPut::setRequester(PvaClientPutRequesterPtr const & pvaClientPutRequester)
429 {
430  if(PvaClient::getDebug()) {
431  cout << "PvaClientPut::setRequester"
432  << " channelName " << pvaClientChannel->getChannel()->getChannelName()
433  << endl;
434  }
435  this->pvaClientPutRequester = pvaClientPutRequester;
436 }
437 
438 PvaClientChannelPtr PvaClientPut::getPvaClientChannel()
439 {
440  return pvaClientChannel;
441 }
442 
443 }}
std::tr1::shared_ptr< PvaClient > PvaClientPtr
Definition: pvaClient.h:46
ChannelPutRequesterImpl(PvaClientPutPtr const &pvaClientPut, PvaClientPtr const &pvaClient)
virtual void putDone(const Status &status, ChannelPut::shared_pointer const &channelPut)
std::tr1::shared_ptr< detail::SharedPut > put
pvd::Status status
std::tr1::shared_ptr< PvaClientChannel > PvaClientChannelPtr
Definition: pvaClient.h:59
Definition: memory.hpp:41
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
std::tr1::shared_ptr< const Structure > StructureConstPtr
Definition: pvIntrospect.h:162
A lock for multithreading.
Definition: lock.h:36
const std::string & getMessage() const
Definition: status.h:80
std::tr1::shared_ptr< PvaClientPut > PvaClientPutPtr
Definition: pvaClient.h:76
virtual void getDone(const Status &status, ChannelPut::shared_pointer const &channelPut, PVStructurePtr const &pvStructure, BitSet::shared_pointer const &bitSet)
Holds all PVA related.
Definition: pvif.h:34
pvData
Definition: monitor.h:428
std::tr1::shared_ptr< PvaClientPutRequester > PvaClientPutRequesterPtr
Definition: pvaClient.h:73
epicsMutex mutex
Definition: pvAccess.cpp:71
std::tr1::shared_ptr< PVStructure > PVStructurePtr
Definition: pvData.h:87
An easy to use alternative to ChannelPut.
Definition: pvaClient.h:1191
Definition: caget.c:48
virtual void channelPutConnect(const Status &status, ChannelPut::shared_pointer const &channelPut, Structure::const_shared_pointer const &structure)
std::tr1::shared_ptr< BitSet > BitSetPtr
Definition: bitSet.h:26
bool isOK() const
Definition: status.h:95
virtual void message(std::string const &message, epics::pvData::MessageType messageType)
std::tr1::shared_ptr< ChannelPutRequesterImpl > ChannelPutRequesterImplPtr
Definition: pvaClient.h:1143
std::tr1::shared_ptr< PvaClientPutData > PvaClientPutDataPtr
Definition: pvaClient.h:52