pvaClientCPP  4.8.1-dev
pvaClientChannel.cpp
Go to the documentation of this file.
1 /* pvaClientChannel.cpp */
12 #include <map>
13 #include <pv/event.h>
14 #include <pv/lock.h>
15 #include <pv/createRequest.h>
16 
17 #define epicsExportSharedSymbols
18 
19 #include <pv/pvaClient.h>
20 
21 using namespace epics::pvData;
22 using namespace epics::pvAccess;
23 using namespace std;
24 
25 namespace epics { namespace pvaClient {
26 
27 
28 class epicsShareClass PvaClientGetCache
29 {
30 public:
31  PvaClientGetCache(){}
32  ~PvaClientGetCache()
33  {
34  if(PvaClient::getDebug()) cout << "PvaClientGetCache::~PvaClientGetCache\n";
35  }
36  PvaClientGetPtr getGet(string const & request);
37  void addGet(string const & request,PvaClientGetPtr const & pvaClientGet);
38  void showCache();
39  size_t cacheSize();
40 private:
41  map<string,PvaClientGetPtr> pvaClientGetMap;
42 };
43 
44 PvaClientGetPtr PvaClientGetCache::getGet(string const & request)
45 {
46  map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request);
47  if(iter!=pvaClientGetMap.end()) return iter->second;
48  return PvaClientGetPtr();
49 }
50 
51 void PvaClientGetCache::addGet(string const & request,PvaClientGetPtr const & pvaClientGet)
52 {
53  map<string,PvaClientGetPtr>::iterator iter = pvaClientGetMap.find(request);
54  if(iter!=pvaClientGetMap.end()) {
55  throw std::runtime_error("pvaClientGetCache::addGet pvaClientGet already cached");
56  }
57  pvaClientGetMap.insert(std::pair<string,PvaClientGetPtr>(request,pvaClientGet));
58 }
59 
60 void PvaClientGetCache::showCache()
61 {
62  map<string,PvaClientGetPtr>::iterator iter;
63  for(iter = pvaClientGetMap.begin(); iter != pvaClientGetMap.end(); ++iter)
64  {
65  cout << " " << iter->first << endl;
66  }
67 }
68 
69 size_t PvaClientGetCache::cacheSize()
70 {
71  return pvaClientGetMap.size();
72 
73 }
74 
75 class epicsShareClass PvaClientPutCache
76 {
77 public:
78  PvaClientPutCache(){}
79  ~PvaClientPutCache()
80  {
81  if(PvaClient::getDebug()) cout << "PvaClientPutCache::~PvaClientPutCache\n";
82  }
83  PvaClientPutPtr getPut(string const & request);
84  void addPut(string const & request,PvaClientPutPtr const & pvaClientPut);
85  void showCache();
86  size_t cacheSize();
87 private:
88  map<string,PvaClientPutPtr> pvaClientPutMap;
89 };
90 
91 
92 PvaClientPutPtr PvaClientPutCache::getPut(string const & request)
93 {
94  map<string,PvaClientPutPtr>::iterator iter = pvaClientPutMap.find(request);
95  if(iter!=pvaClientPutMap.end()) return iter->second;
96  return PvaClientPutPtr();
97 }
98 
99 void PvaClientPutCache::addPut(string const & request,PvaClientPutPtr const & pvaClientPut)
100 {
101  map<string,PvaClientPutPtr>::iterator iter = pvaClientPutMap.find(request);
102  if(iter!=pvaClientPutMap.end()) {
103  throw std::runtime_error("pvaClientPutCache::addPut pvaClientPut already cached");
104  }
105  pvaClientPutMap.insert(std::pair<string,PvaClientPutPtr>(
106  request,pvaClientPut));
107 }
108 
109 void PvaClientPutCache::showCache()
110 {
111  map<string,PvaClientPutPtr>::iterator iter;
112  for(iter = pvaClientPutMap.begin(); iter != pvaClientPutMap.end(); ++iter)
113  {
114  cout << " " << iter->first << endl;
115  }
116 }
117 
118 size_t PvaClientPutCache::cacheSize()
119 {
120  return pvaClientPutMap.size();
121 
122 }
123 
124 PvaClientChannelPtr PvaClientChannel::create(
125  PvaClientPtr const &pvaClient,
126  string const & channelName,
127  string const & providerName)
128 {
129  PvaClientChannelPtr channel(new PvaClientChannel(pvaClient,channelName,providerName));
130  return channel;
131 }
132 
133 
134 PvaClientChannel::PvaClientChannel(
135  PvaClientPtr const &pvaClient,
136  string const & channelName,
137  string const & providerName)
138 : pvaClient(pvaClient),
139  channelName(channelName),
140  providerName(providerName),
141  connectState(connectIdle),
142  createRequest(CreateRequest::create()),
143  pvaClientGetCache(new PvaClientGetCache()),
144  pvaClientPutCache(new PvaClientPutCache())
145 {
146  if(PvaClient::getDebug()) {
147  cout << "PvaClientChannel::PvaClientChannel channelName " << channelName << endl;
148  }
149 }
150 
151 PvaClientChannel::~PvaClientChannel()
152 {
153  if(PvaClient::getDebug()) {
154  cout << "PvaClientChannel::~PvaClientChannel() "
155  << " channelName " << channelName
156  << endl;
157  }
158  if(PvaClient::getDebug()) showCache();
159 }
160 
161 void PvaClientChannel::channelCreated(const Status& status, Channel::shared_pointer const & channel)
162 {
163  if(PvaClient::getDebug()) {
164  cout << "PvaClientChannel::channelCreated"
165  << " channelName " << channelName
166  << " connectState " << connectState
167  << " isConnected " << (channel->isConnected() ? "true" : "false")
168  << " status.isOK " << (status.isOK() ? "true" : "false")
169  << endl;
170  }
171  Lock xx(mutex);
172  this->channel = channel;
173  if(connectState==connected) return;
174  if(connectState!=connectActive) {
175  string message("PvaClientChannel::channelCreated");
176  message += " channel " + channelName
177  + " why was this called when connectState!=ConnectState.connectActive";
178  throw std::runtime_error(message);
179  }
180  if(!status.isOK()) {
181  string message("PvaClientChannel::channelCreated");
182  + " status " + status.getMessage() + " why??";
183  throw std::runtime_error(message);
184  }
185 }
186 
187 void PvaClientChannel::channelStateChange(
188  Channel::shared_pointer const & channel,
189  Channel::ConnectionState connectionState)
190 {
191  if(PvaClient::getDebug()) {
192  cout << " PvaClientChannel::channelStateChange "
193  << " channelName " << channelName
194  << " " << Channel::ConnectionStateNames[connectionState]
195  << endl;
196  }
197  bool waitingForConnect = false;
198  if(connectState==connectActive) waitingForConnect = true;
199  if(connectionState!=Channel::CONNECTED) {
200  Lock xx(mutex);
201  connectState = notConnected;
202  } else {
203  Lock xx(mutex);
204  this->channel = channel;
205  connectState = connected;
206  }
207  if(waitingForConnect) {
208  Lock xx(mutex);
209  waitForConnect.signal();
210  }
211  PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock());
212  if(req) {
213  bool value = (connectionState==Channel::CONNECTED ? true : false);
214  req->channelStateChange(shared_from_this(),value);
215  }
216 }
217 
218 string PvaClientChannel::getRequesterName()
219 {
220  PvaClientPtr yyy = pvaClient.lock();
221  if(!yyy) return string("PvaClientChannel::getRequesterName() PvaClient isDestroyed");
222  return yyy->getRequesterName();
223 }
224 
225 void PvaClientChannel::message(
226  string const & message,
227  MessageType messageType)
228 {
229  PvaClientPtr yyy = pvaClient.lock();
230  if(!yyy) return;
231  yyy->message(channelName + " " + message, messageType);
232 }
233 
234 string PvaClientChannel::getChannelName()
235 {
236  return channelName;
237 }
238 
239 Channel::shared_pointer PvaClientChannel::getChannel()
240 {
241  return channel;
242 }
243 
244 void PvaClientChannel::setStateChangeRequester(
245  PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester)
246 {
247  this->stateChangeRequester = stateChangeRequester;
248  bool isConnected = false;
249  if(channel) isConnected = channel->isConnected();
250  stateChangeRequester->channelStateChange(shared_from_this(),isConnected);
251 }
252 
253 void PvaClientChannel::connect(double timeout)
254 {
255  if(PvaClient::getDebug()) {
256  cout << "PvaClientChannel::connect"
257  << " channelName " << channelName << endl;
258  }
259  issueConnect();
260  Status status = waitConnect(timeout);
261  if(status.isOK()) return;
262  if(PvaClient::getDebug()) cout << "PvaClientChannel::connect waitConnect failed\n";
263  string message = string("channel ") + channelName
264  + " PvaClientChannel::connect " + status.getMessage();
265  throw std::runtime_error(message);
266 }
267 
268 void PvaClientChannel::issueConnect()
269 {
270  if(PvaClient::getDebug()) {
271  cout << "PvaClientChannel::issueConnect"
272  << " channelName " << channelName << endl;
273  }
274  {
275  Lock xx(mutex);
276  if(connectState==connected) return;
277  if(connectState!=connectIdle) {
278  throw std::runtime_error("pvaClientChannel already connected");
279  }
280  connectState = connectActive;
281  }
282  ChannelProviderRegistry::shared_pointer reg(ChannelProviderRegistry::clients());
283  channelProvider = reg->getProvider(providerName);
284  if(!channelProvider) {
285  throw std::runtime_error(channelName + " provider " + providerName + " not registered");
286  }
287  if(PvaClient::getDebug()) cout << "PvaClientChannel::issueConnect calling provider->createChannel\n";
288  channel = channelProvider->createChannel(channelName,shared_from_this(),ChannelProvider::PRIORITY_DEFAULT);
289  if(!channel) {
290  throw std::runtime_error(channelName + " channelCreate failed ");
291  }
292 }
293 
294 Status PvaClientChannel::waitConnect(double timeout)
295 {
296  if(PvaClient::getDebug()) {
297  cout << "PvaClientChannel::waitConnect"
298  << " channelName " << channelName << endl;
299  }
300  {
301  Lock xx(mutex);
302  if(!channel) return Status(Status::STATUSTYPE_ERROR,"");
303  if(channel->isConnected()) return Status::Ok;
304  }
305  if(timeout>0.0) {
306  waitForConnect.wait(timeout);
307  } else {
308  waitForConnect.wait();
309  }
310  if(!channel) return Status(Status::STATUSTYPE_ERROR,"pvaClientChannel::waitConnect channel is null");
311  if(channel->isConnected()) return Status::Ok;
312  return Status(Status::STATUSTYPE_ERROR," not connected");
313 }
314 
315 PvaClientProcessPtr PvaClientChannel::createProcess(string const & request)
316 {
317  PVStructurePtr pvRequest = createRequest->createRequest(request);
318  if(!pvRequest) {
319  string message = string("channel ") + channelName
320  + " PvaClientChannel::createProcess invalid pvRequest: "
321  + createRequest->getMessage();
322  throw std::runtime_error(message);
323  }
324  return createProcess(pvRequest);
325 }
326 
327 PvaClientProcessPtr PvaClientChannel::createProcess(PVStructurePtr const & pvRequest)
328 {
329  if(connectState!=connected) connect(5.0);
330  PvaClientPtr yyy = pvaClient.lock();
331  if(!yyy) throw std::runtime_error("PvaClient was destroyed");
332  return PvaClientProcess::create(yyy,shared_from_this(),pvRequest);
333 }
334 
335 
336 PvaClientGetPtr PvaClientChannel::get(string const & request)
337 {
338  PvaClientGetPtr pvaClientGet = pvaClientGetCache->getGet(request);
339  if(!pvaClientGet) {
340  pvaClientGet = createGet(request);
341  pvaClientGet->connect();
342  pvaClientGetCache->addGet(request,pvaClientGet);
343  }
344  pvaClientGet->get();
345  return pvaClientGet;
346 }
347 
348 
349 PvaClientGetPtr PvaClientChannel::createGet(string const & request)
350 {
351  PVStructurePtr pvRequest = createRequest->createRequest(request);
352  if(!pvRequest) {
353  string message = string("channel ") + channelName
354  + " PvaClientChannel::createGet invalid pvRequest: "
355  + createRequest->getMessage();
356  throw std::runtime_error(message);
357  }
358  return createGet(pvRequest);
359 }
360 
361 PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & pvRequest)
362 {
363  if(connectState!=connected) connect(5.0);
364  PvaClientPtr yyy = pvaClient.lock();
365  if(!yyy) throw std::runtime_error("PvaClient was destroyed");
366  return PvaClientGet::create(yyy,shared_from_this(),pvRequest);
367 }
368 
369 double PvaClientChannel::getDouble(string const & request)
370 {
371  return get(request)->getData()->getDouble();
372 }
373 
374 string PvaClientChannel::getString(string const & request)
375 {
376  return get(request)->getData()->getString();
377 }
378 
379 shared_vector<const double> PvaClientChannel::getDoubleArray(string const & request)
380 {
381  return get(request)->getData()->getDoubleArray();
382 }
383 
384 shared_vector<const std::string> PvaClientChannel::getStringArray(string const & request)
385 {
386  return get(request)->getData()->getStringArray();
387 }
388 
389 
390 PvaClientPutPtr PvaClientChannel::put(string const & request)
391 {
392  PvaClientPutPtr pvaClientPut = pvaClientPutCache->getPut(request);
393  if(pvaClientPut) return pvaClientPut;
394  if(!pvaClientPut) {
395  pvaClientPut = createPut(request);
396  pvaClientPut->connect();
397  pvaClientPut->get();
398  pvaClientPutCache->addPut(request,pvaClientPut);
399  }
400  return pvaClientPut;
401 }
402 
403 
404 PvaClientPutPtr PvaClientChannel::createPut(string const & request)
405 {
406  PVStructurePtr pvRequest = createRequest->createRequest(request);
407  if(!pvRequest) {
408  string message = string("channel ") + channelName
409  + " PvaClientChannel::createPut invalid pvRequest: "
410  + createRequest->getMessage();
411  throw std::runtime_error(message);
412  }
413  return createPut(pvRequest);
414 }
415 
416 PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest)
417 {
418  if(connectState!=connected) connect(5.0);
419  PvaClientPtr yyy = pvaClient.lock();
420  if(!yyy) throw std::runtime_error("PvaClient was destroyed");
421  return PvaClientPut::create(yyy,shared_from_this(),pvRequest);
422 }
423 
424 void PvaClientChannel::putDouble(double value,string const & request)
425 {
426  PvaClientPutPtr clientPut = put(request);
427  PvaClientPutDataPtr putData = clientPut->getData();
428  putData->putDouble(value); clientPut->put();
429 }
430 
431 void PvaClientChannel::putString(std::string const & value,string const & request)
432 {
433  PvaClientPutPtr clientPut = put(request);
434  PvaClientPutDataPtr putData = clientPut->getData();
435  putData->putString(value); clientPut->put();
436 }
437 
438 void PvaClientChannel::putDoubleArray(
439  shared_vector<const double> const & value,
440  string const & request)
441 {
442  PvaClientPutPtr clientPut = put(request);
443  PvaClientPutDataPtr putData = clientPut->getData();
444  size_t n = value.size();
445  shared_vector<double> valueArray(n);
446  for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
447  putData->putDoubleArray(freeze(valueArray)); clientPut->put();
448 }
449 
450 void PvaClientChannel::putStringArray(
451  shared_vector<const string> const & value,
452  string const & request)
453 {
454  PvaClientPutPtr clientPut = put(request);
455  PvaClientPutDataPtr putData = clientPut->getData();
456  size_t n = value.size();
457  shared_vector<string> valueArray(n);
458  for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
459  putData->putStringArray(freeze(valueArray)); clientPut->put();
460 }
461 
462 PvaClientPutGetPtr PvaClientChannel::createPutGet(string const & request)
463 {
464  PVStructurePtr pvRequest = createRequest->createRequest(request);
465  if(!pvRequest) {
466  string message = string("channel ") + channelName
467  + " PvaClientChannel::createPutGet invalid pvRequest: "
468  + createRequest->getMessage();
469  throw std::runtime_error(message);
470  }
471  return createPutGet(pvRequest);
472 }
473 
474 PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvRequest)
475 {
476  if(connectState!=connected) connect(5.0);
477  PvaClientPtr yyy = pvaClient.lock();
478  if(!yyy) throw std::runtime_error("PvaClient was destroyed");
479  return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest);
480 }
481 
482 PvaClientMonitorPtr PvaClientChannel::monitor(string const & request)
483 {
484  PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
485  pvaClientMonitor->connect();
486  pvaClientMonitor->start();
487  return pvaClientMonitor;
488 }
489 
490 PvaClientMonitorPtr PvaClientChannel::monitor(PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
491 {
492  return monitor("field(value,alarm,timeStamp)",pvaClientMonitorRequester);
493 }
494 
495 PvaClientMonitorPtr PvaClientChannel::monitor(string const & request,
496  PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
497 {
498  PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
499  pvaClientMonitor->connect();
500  pvaClientMonitor->setRequester(pvaClientMonitorRequester);
501  pvaClientMonitor->start();
502  return pvaClientMonitor;
503 }
504 
505 PvaClientMonitorPtr PvaClientChannel::createMonitor(string const & request)
506 {
507  PVStructurePtr pvRequest = createRequest->createRequest(request);
508  if(!pvRequest) {
509  string message = string("channel ") + channelName
510  + " PvaClientChannel::createMonitor invalid pvRequest: "
511  + createRequest->getMessage();
512  throw std::runtime_error(message);
513  }
514  return createMonitor(pvRequest);
515 }
516 
517 PvaClientMonitorPtr PvaClientChannel::createMonitor(PVStructurePtr const & pvRequest)
518 {
519  if(connectState!=connected) connect(5.0);
520  PvaClientPtr yyy = pvaClient.lock();
521  if(!yyy) throw std::runtime_error("PvaClient was destroyed");
522  return PvaClientMonitor::create(yyy,shared_from_this(),pvRequest);
523 }
524 
525 PVStructurePtr PvaClientChannel::rpc(
526  PVStructurePtr const & pvRequest,
527  PVStructurePtr const & pvArgument)
528 {
529 
530  PvaClientRPCPtr rpc = createRPC(pvRequest);
531  return rpc->request(pvArgument);
532 }
533 
534 PVStructurePtr PvaClientChannel::rpc(
535  PVStructurePtr const & pvArgument)
536 {
537  PvaClientRPCPtr rpc = createRPC();
538  return rpc->request(pvArgument);
539 }
540 
541 PvaClientRPCPtr PvaClientChannel::createRPC()
542 {
543  if(connectState!=connected) connect(5.0);
544  PvaClientPtr yyy = pvaClient.lock();
545  if(!yyy) throw std::runtime_error("PvaClient was destroyed");
546  return PvaClientRPC::create(yyy,channel);
547 }
548 
549 PvaClientRPCPtr PvaClientChannel::createRPC(PVStructurePtr const & pvRequest)
550 {
551  if(connectState!=connected) connect(5.0);
552  PvaClientPtr yyy = pvaClient.lock();
553  if(!yyy) throw std::runtime_error("PvaClient was destroyed");
554  return PvaClientRPC::create(yyy,channel,pvRequest);
555 }
556 
557 void PvaClientChannel::showCache()
558 {
559  if(pvaClientGetCache->cacheSize()>=1) {
560  cout << " pvaClientGet cache" << endl;
561  pvaClientGetCache->showCache();
562  } else {
563  cout << " pvaClientGet cache is empty\n";
564  }
565  if(pvaClientPutCache->cacheSize()>=1) {
566  cout << " pvaClientPut cache" << endl;
567  pvaClientPutCache->showCache();
568  } else {
569  cout << " pvaClientPut cache is empty\n";
570  }
571 }
572 
573 size_t PvaClientChannel::cacheSize()
574 {
575  return pvaClientGetCache->cacheSize() + pvaClientPutCache->cacheSize();
576 }
577 
578 
579 
580 }}
std::tr1::shared_ptr< PvaClient > PvaClientPtr
Definition: pvaClient.h:46
std::tr1::shared_ptr< PvaClientChannel > PvaClientChannelPtr
Definition: pvaClient.h:59
STL namespace.
std::tr1::shared_ptr< PvaClientPut > PvaClientPutPtr
Definition: pvaClient.h:74
std::tr1::shared_ptr< PvaClientMonitorRequester > PvaClientMonitorRequesterPtr
Definition: pvaClient.h:83
std::tr1::shared_ptr< PvaClientGet > PvaClientGetPtr
Definition: pvaClient.h:69
std::tr1::shared_ptr< PvaClientRPC > PvaClientRPCPtr
Definition: pvaClient.h:86
std::tr1::shared_ptr< PvaClientChannelStateChangeRequester > PvaClientChannelStateChangeRequesterPtr
Definition: pvaClient.h:56
std::tr1::shared_ptr< PvaClientProcess > PvaClientProcessPtr
Definition: pvaClient.h:64
std::tr1::shared_ptr< PvaClientPutGet > PvaClientPutGetPtr
Definition: pvaClient.h:79
std::tr1::shared_ptr< PvaClientMonitor > PvaClientMonitorPtr
Definition: pvaClient.h:81
std::tr1::shared_ptr< PvaClientPutData > PvaClientPutDataPtr
Definition: pvaClient.h:52