pvaClientCPP 4.8.1
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
21using namespace epics::pvData;
22using namespace epics::pvAccess;
23using namespace std;
24
25namespace epics { namespace pvaClient {
26
27
28class epicsShareClass PvaClientGetCache
29{
30public:
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();
40private:
41 map<string,PvaClientGetPtr> pvaClientGetMap;
42};
43
44PvaClientGetPtr 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
51void 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
60void 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
69size_t PvaClientGetCache::cacheSize()
70{
71 return pvaClientGetMap.size();
72
73}
74
75class epicsShareClass PvaClientPutCache
76{
77public:
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();
87private:
88 map<string,PvaClientPutPtr> pvaClientPutMap;
89};
90
91
92PvaClientPutPtr 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
99void 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
109void 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
118size_t PvaClientPutCache::cacheSize()
119{
120 return pvaClientPutMap.size();
121
122}
123
124PvaClientChannelPtr 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
134PvaClientChannel::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
152{
153 if(PvaClient::getDebug()) {
154 cout << "PvaClientChannel::~PvaClientChannel() "
155 << " channelName " << channelName
156 << endl;
157 }
159}
160
161void 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 message += " channel " + channelName
183 + " status " + status.getMessage() + " why??";
184 throw std::runtime_error(message);
185 }
186}
187
189 Channel::shared_pointer const & channel,
190 Channel::ConnectionState connectionState)
191{
192 if(PvaClient::getDebug()) {
193 cout << " PvaClientChannel::channelStateChange "
194 << " channelName " << channelName
195 << " " << Channel::ConnectionStateNames[connectionState]
196 << endl;
197 }
198 bool waitingForConnect = false;
199 if(connectState==connectActive) waitingForConnect = true;
200 if(connectionState!=Channel::CONNECTED) {
201 Lock xx(mutex);
202 connectState = notConnected;
203 } else {
204 Lock xx(mutex);
205 this->channel = channel;
206 connectState = connected;
207 }
208 if(waitingForConnect) {
209 Lock xx(mutex);
210 waitForConnect.signal();
211 }
212 PvaClientChannelStateChangeRequesterPtr req(stateChangeRequester.lock());
213 if(req) {
214 bool value = (connectionState==Channel::CONNECTED ? true : false);
215 req->channelStateChange(shared_from_this(),value);
216 }
217}
218
220{
221 PvaClientPtr yyy = pvaClient.lock();
222 if(!yyy) return string("PvaClientChannel::getRequesterName() PvaClient isDestroyed");
223 return yyy->getRequesterName();
224}
225
227 string const & message,
228 MessageType messageType)
229{
230 PvaClientPtr yyy = pvaClient.lock();
231 if(!yyy) return;
232 yyy->message(channelName + " " + message, messageType);
233}
234
236{
237 return channelName;
238}
239
240Channel::shared_pointer PvaClientChannel::getChannel()
241{
242 return channel;
243}
244
246 PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester)
247{
248 this->stateChangeRequester = stateChangeRequester;
249 bool isConnected = false;
250 if(channel) isConnected = channel->isConnected();
251 stateChangeRequester->channelStateChange(shared_from_this(),isConnected);
252}
253
254void PvaClientChannel::connect(double timeout)
255{
256 if(PvaClient::getDebug()) {
257 cout << "PvaClientChannel::connect"
258 << " channelName " << channelName << endl;
259 }
260 issueConnect();
261 Status status = waitConnect(timeout);
262 if(status.isOK()) return;
263 if(PvaClient::getDebug()) cout << "PvaClientChannel::connect waitConnect failed\n";
264 string message = string("channel ") + channelName
265 + " PvaClientChannel::connect " + status.getMessage();
266 throw std::runtime_error(message);
267}
268
270{
271 if(PvaClient::getDebug()) {
272 cout << "PvaClientChannel::issueConnect"
273 << " channelName " << channelName << endl;
274 }
275 {
276 Lock xx(mutex);
277 if(connectState==connected) return;
278 if(connectState!=connectIdle) {
279 throw std::runtime_error("pvaClientChannel already connected");
280 }
281 connectState = connectActive;
282 }
283 ChannelProviderRegistry::shared_pointer reg(ChannelProviderRegistry::clients());
284 channelProvider = reg->getProvider(providerName);
285 if(!channelProvider) {
286 throw std::runtime_error(channelName + " provider " + providerName + " not registered");
287 }
288 if(PvaClient::getDebug()) cout << "PvaClientChannel::issueConnect calling provider->createChannel\n";
289 channel = channelProvider->createChannel(channelName,shared_from_this(),ChannelProvider::PRIORITY_DEFAULT);
290 if(!channel) {
291 throw std::runtime_error(channelName + " channelCreate failed ");
292 }
293}
294
295Status PvaClientChannel::waitConnect(double timeout)
296{
297 if(PvaClient::getDebug()) {
298 cout << "PvaClientChannel::waitConnect"
299 << " channelName " << channelName << endl;
300 }
301 {
302 Lock xx(mutex);
303 if(!channel) return Status(Status::STATUSTYPE_ERROR,"");
304 if(channel->isConnected()) return Status::Ok;
305 }
306 if(timeout>0.0) {
307 waitForConnect.wait(timeout);
308 } else {
309 waitForConnect.wait();
310 }
311 if(!channel) return Status(Status::STATUSTYPE_ERROR,"pvaClientChannel::waitConnect channel is null");
312 if(channel->isConnected()) return Status::Ok;
313 return Status(Status::STATUSTYPE_ERROR," not connected");
314}
315
317{
318 PVStructurePtr pvRequest = createRequest->createRequest(request);
319 if(!pvRequest) {
320 string message = string("channel ") + channelName
321 + " PvaClientChannel::createProcess invalid pvRequest: "
322 + createRequest->getMessage();
323 throw std::runtime_error(message);
324 }
325 return createProcess(pvRequest);
326}
327
328PvaClientProcessPtr PvaClientChannel::createProcess(PVStructurePtr const & pvRequest)
329{
330 if(connectState!=connected) connect(5.0);
331 PvaClientPtr yyy = pvaClient.lock();
332 if(!yyy) throw std::runtime_error("PvaClient was destroyed");
333 return PvaClientProcess::create(yyy,shared_from_this(),pvRequest);
334}
335
336
338{
339 PvaClientGetPtr pvaClientGet = pvaClientGetCache->getGet(request);
340 if(!pvaClientGet) {
341 pvaClientGet = createGet(request);
342 pvaClientGet->connect();
343 pvaClientGetCache->addGet(request,pvaClientGet);
344 }
345 pvaClientGet->get();
346 return pvaClientGet;
347}
348
349
351{
352 PVStructurePtr pvRequest = createRequest->createRequest(request);
353 if(!pvRequest) {
354 string message = string("channel ") + channelName
355 + " PvaClientChannel::createGet invalid pvRequest: "
356 + createRequest->getMessage();
357 throw std::runtime_error(message);
358 }
359 return createGet(pvRequest);
360}
361
362PvaClientGetPtr PvaClientChannel::createGet(PVStructurePtr const & pvRequest)
363{
364 if(connectState!=connected) connect(5.0);
365 PvaClientPtr yyy = pvaClient.lock();
366 if(!yyy) throw std::runtime_error("PvaClient was destroyed");
367 return PvaClientGet::create(yyy,shared_from_this(),pvRequest);
368}
369
370double PvaClientChannel::getDouble(string const & request)
371{
372 return get(request)->getData()->getDouble();
373}
374
375string PvaClientChannel::getString(string const & request)
376{
377 return get(request)->getData()->getString();
378}
379
380shared_vector<const double> PvaClientChannel::getDoubleArray(string const & request)
381{
382 return get(request)->getData()->getDoubleArray();
383}
384
385shared_vector<const std::string> PvaClientChannel::getStringArray(string const & request)
386{
387 return get(request)->getData()->getStringArray();
388}
389
390
392{
393 PvaClientPutPtr pvaClientPut = pvaClientPutCache->getPut(request);
394 if(pvaClientPut) return pvaClientPut;
395 if(!pvaClientPut) {
396 pvaClientPut = createPut(request);
397 pvaClientPut->connect();
398 pvaClientPut->get();
399 pvaClientPutCache->addPut(request,pvaClientPut);
400 }
401 return pvaClientPut;
402}
403
404
406{
407 PVStructurePtr pvRequest = createRequest->createRequest(request);
408 if(!pvRequest) {
409 string message = string("channel ") + channelName
410 + " PvaClientChannel::createPut invalid pvRequest: "
411 + createRequest->getMessage();
412 throw std::runtime_error(message);
413 }
414 return createPut(pvRequest);
415}
416
417PvaClientPutPtr PvaClientChannel::createPut(PVStructurePtr const & pvRequest)
418{
419 if(connectState!=connected) connect(5.0);
420 PvaClientPtr yyy = pvaClient.lock();
421 if(!yyy) throw std::runtime_error("PvaClient was destroyed");
422 return PvaClientPut::create(yyy,shared_from_this(),pvRequest);
423}
424
425void PvaClientChannel::putDouble(double value,string const & request)
426{
427 PvaClientPutPtr clientPut = put(request);
428 PvaClientPutDataPtr putData = clientPut->getData();
429 putData->putDouble(value); clientPut->put();
430}
431
432void PvaClientChannel::putString(std::string const & value,string const & request)
433{
434 PvaClientPutPtr clientPut = put(request);
435 PvaClientPutDataPtr putData = clientPut->getData();
436 putData->putString(value); clientPut->put();
437}
438
440 shared_vector<const double> const & value,
441 string const & request)
442{
443 PvaClientPutPtr clientPut = put(request);
444 PvaClientPutDataPtr putData = clientPut->getData();
445 size_t n = value.size();
446 shared_vector<double> valueArray(n);
447 for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
448 putData->putDoubleArray(freeze(valueArray)); clientPut->put();
449}
450
452 shared_vector<const string> const & value,
453 string const & request)
454{
455 PvaClientPutPtr clientPut = put(request);
456 PvaClientPutDataPtr putData = clientPut->getData();
457 size_t n = value.size();
458 shared_vector<string> valueArray(n);
459 for(size_t i=0; i<n; ++i) valueArray[i] = value[i];
460 putData->putStringArray(freeze(valueArray)); clientPut->put();
461}
462
464{
465 PVStructurePtr pvRequest = createRequest->createRequest(request);
466 if(!pvRequest) {
467 string message = string("channel ") + channelName
468 + " PvaClientChannel::createPutGet invalid pvRequest: "
469 + createRequest->getMessage();
470 throw std::runtime_error(message);
471 }
472 return createPutGet(pvRequest);
473}
474
475PvaClientPutGetPtr PvaClientChannel::createPutGet(PVStructurePtr const & pvRequest)
476{
477 if(connectState!=connected) connect(5.0);
478 PvaClientPtr yyy = pvaClient.lock();
479 if(!yyy) throw std::runtime_error("PvaClient was destroyed");
480 return PvaClientPutGet::create(yyy,shared_from_this(),pvRequest);
481}
482
484{
485 PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
486 pvaClientMonitor->connect();
487 pvaClientMonitor->start();
488 return pvaClientMonitor;
489}
490
492{
493 return monitor("field(value,alarm,timeStamp)",pvaClientMonitorRequester);
494}
495
497 PvaClientMonitorRequesterPtr const & pvaClientMonitorRequester)
498{
499 PvaClientMonitorPtr pvaClientMonitor = createMonitor(request);
500 pvaClientMonitor->connect();
501 pvaClientMonitor->setRequester(pvaClientMonitorRequester);
502 pvaClientMonitor->start();
503 return pvaClientMonitor;
504}
505
507{
508 PVStructurePtr pvRequest = createRequest->createRequest(request);
509 if(!pvRequest) {
510 string message = string("channel ") + channelName
511 + " PvaClientChannel::createMonitor invalid pvRequest: "
512 + createRequest->getMessage();
513 throw std::runtime_error(message);
514 }
515 return createMonitor(pvRequest);
516}
517
518PvaClientMonitorPtr PvaClientChannel::createMonitor(PVStructurePtr const & pvRequest)
519{
520 if(connectState!=connected) connect(5.0);
521 PvaClientPtr yyy = pvaClient.lock();
522 if(!yyy) throw std::runtime_error("PvaClient was destroyed");
523 return PvaClientMonitor::create(yyy,shared_from_this(),pvRequest);
524}
525
526PVStructurePtr PvaClientChannel::rpc(
527 PVStructurePtr const & pvRequest,
528 PVStructurePtr const & pvArgument)
529{
530
531 PvaClientRPCPtr rpc = createRPC(pvRequest);
532 return rpc->request(pvArgument);
533}
534
535PVStructurePtr PvaClientChannel::rpc(
536 PVStructurePtr const & pvArgument)
537{
539 return rpc->request(pvArgument);
540}
541
543{
544 if(connectState!=connected) connect(5.0);
545 PvaClientPtr yyy = pvaClient.lock();
546 if(!yyy) throw std::runtime_error("PvaClient was destroyed");
547 return PvaClientRPC::create(yyy,channel);
548}
549
550PvaClientRPCPtr PvaClientChannel::createRPC(PVStructurePtr const & pvRequest)
551{
552 if(connectState!=connected) connect(5.0);
553 PvaClientPtr yyy = pvaClient.lock();
554 if(!yyy) throw std::runtime_error("PvaClient was destroyed");
555 return PvaClientRPC::create(yyy,channel,pvRequest);
556}
557
559{
560 if(pvaClientGetCache->cacheSize()>=1) {
561 cout << " pvaClientGet cache" << endl;
562 pvaClientGetCache->showCache();
563 } else {
564 cout << " pvaClientGet cache is empty\n";
565 }
566 if(pvaClientPutCache->cacheSize()>=1) {
567 cout << " pvaClientPut cache" << endl;
568 pvaClientPutCache->showCache();
569 } else {
570 cout << " pvaClientPut cache is empty\n";
571 }
572}
573
575{
576 return pvaClientGetCache->cacheSize() + pvaClientPutCache->cacheSize();
577}
578
579
580
581}}
PvaClientGetPtr createGet(std::string const &request="field(value,alarm,timeStamp)")
create a PvaClientGet.
void putDouble(double value, std::string const &request="field(value)")
Put the value as a double.
void putDoubleArray(epics::pvData::shared_vector< const double > const &value, std::string const &request="field(value)")
Copy the array to the value field.
size_t cacheSize()
Get the number of cached gets and puts.
PvaClientPutPtr put(std::string const &request="field(value)")
create a PvaClientPut.
void issueConnect()
Issue a connect request and return immediately.
PvaClientPutGetPtr createPutGet(std::string const &request="putField(argument)getField(result)")
create a PvaClientPutGet.
PvaClientGetPtr get(std::string const &request="field(value,alarm,timeStamp)")
create a PvaChannelGet
std::string getChannelName()
Get the name of the channel to which PvaClientChannel is connected.
epics::pvData::Status waitConnect(double timeout=5.0)
Wait until the connection completes or for timeout.
void putStringArray(epics::pvData::shared_vector< const std::string > const &value, std::string const &request="field(value)")
Copy array to the value field.
void putString(std::string const &value, std::string const &request="field(value)")
Put the value as a string.
void showCache()
Show the list of cached gets and puts.
virtual void message(std::string const &message, epics::pvData::MessageType messageType)
std::string getString(std::string const &request="field(value)")
double getDouble(std::string const &request="field(value)")
Get the value as a double.
epics::pvData::PVStructurePtr rpc(epics::pvData::PVStructurePtr const &pvRequest, epics::pvData::PVStructurePtr const &pvArgument)
Issue a channelRPC request.
PvaClientPutPtr createPut(std::string const &request="field(value)")
create a PvaClientPut.
void setStateChangeRequester(PvaClientChannelStateChangeRequesterPtr const &stateChangeRequester)
Set a client stateChangeRequester.
virtual void channelStateChange(epics::pvAccess::Channel::shared_pointer const &channel, epics::pvAccess::Channel::ConnectionState connectionState)
PvaClientMonitorPtr monitor(std::string const &request="field(value,alarm,timeStamp)")
Create a PvaClientMonitor.
virtual void channelCreated(const epics::pvData::Status &status, epics::pvAccess::Channel::shared_pointer const &channel)
epics::pvAccess::Channel::shared_pointer getChannel()
Get the the channel to which PvaClientChannel is connected.
PvaClientMonitorPtr createMonitor(std::string const &request="field(value,alarm,timeStamp)")
First call createRequest as implemented by pvDataJava and then call the next method.
epics::pvData::shared_vector< const std::string > getStringArray(std::string const &request="field(value)")
Get the value as a string array.
PvaClientProcessPtr createProcess(std::string const &request="")
First call createRequest as implemented by pvDataCPP and then call the next method.
PvaClientRPCPtr createRPC()
Create a PvaClientRPC.
epics::pvData::shared_vector< const double > getDoubleArray(std::string const &request="field(value)")
Get the value as a double array.
void connect(double timeout=5.0)
Connect to the channel.
static PvaClientGetPtr create(PvaClientPtr const &pvaClient, PvaClientChannelPtr const &pvaClientChannel, epics::pvData::PVStructurePtr const &pvRequest)
Create a PvaClientGet.
static PvaClientMonitorPtr create(PvaClientPtr const &pvaClient, PvaClientChannelPtr const &pvaClientChannel, epics::pvData::PVStructurePtr const &pvRequest)
Create a PvaClientMonitor.
static PvaClientProcessPtr create(PvaClientPtr const &pvaClient, PvaClientChannelPtr const &pvaClientChannel, epics::pvData::PVStructurePtr const &pvRequest)
Create a PvaClientProcess.
static PvaClientPutGetPtr create(PvaClientPtr const &pvaClient, PvaClientChannelPtr const &pvaClientChannel, epics::pvData::PVStructurePtr const &pvRequest)
Create a PvaClientPutGet.
static PvaClientPutPtr create(PvaClientPtr const &pvaClient, PvaClientChannelPtr const &pvaClientChannel, epics::pvData::PVStructurePtr const &pvRequest)
Create a PvaClientPut.
static PvaClientRPCPtr create(PvaClientPtr const &pvaClient, epics::pvAccess::Channel::shared_pointer const &channel)
Create a PvaClientRPC.
static bool getDebug()
Is debug set?
Definition pvaClient.cpp:97
std::tr1::shared_ptr< PvaClientPutGet > PvaClientPutGetPtr
Definition pvaClient.h:80
std::tr1::shared_ptr< PvaClientChannel > PvaClientChannelPtr
Definition pvaClient.h:60
std::tr1::shared_ptr< PvaClientGet > PvaClientGetPtr
Definition pvaClient.h:70
std::tr1::shared_ptr< PvaClientProcess > PvaClientProcessPtr
Definition pvaClient.h:65
std::tr1::shared_ptr< PvaClientMonitorRequester > PvaClientMonitorRequesterPtr
Definition pvaClient.h:84
std::tr1::shared_ptr< PvaClientRPC > PvaClientRPCPtr
Definition pvaClient.h:87
std::tr1::shared_ptr< PvaClientChannelStateChangeRequester > PvaClientChannelStateChangeRequesterPtr
Definition pvaClient.h:57
std::tr1::shared_ptr< PvaClient > PvaClientPtr
Definition pvaClient.h:47
std::tr1::shared_ptr< PvaClientMonitor > PvaClientMonitorPtr
Definition pvaClient.h:82
std::tr1::shared_ptr< PvaClientPutData > PvaClientPutDataPtr
Definition pvaClient.h:53
std::tr1::shared_ptr< PvaClientPut > PvaClientPutPtr
Definition pvaClient.h:75