pvaClientCPP 4.8.1
pvaClientMonitor.cpp
Go to the documentation of this file.
1/* pvaClientMonitor.cpp */
12#include <sstream>
13#include <pv/event.h>
14#include <pv/bitSetUtil.h>
15
16#define epicsExportSharedSymbols
17
18#include <pv/pvaClient.h>
19
20using namespace epics::pvData;
21using namespace epics::pvAccess;
22using namespace std;
23
24namespace epics { namespace pvaClient {
25
26class MonitorRequesterImpl : public MonitorRequester
27{
28 PvaClientMonitor::weak_pointer pvaClientMonitor;
29 PvaClient::weak_pointer pvaClient;
30public:
31 MonitorRequesterImpl(
32 PvaClientMonitorPtr const & pvaClientMonitor,
33 PvaClientPtr const &pvaClient)
34 : pvaClientMonitor(pvaClientMonitor),
35 pvaClient(pvaClient)
36 {}
37 virtual ~MonitorRequesterImpl() {
38 if(PvaClient::getDebug()) std::cout << "~MonitorRequesterImpl" << std::endl;
39 }
40
41 virtual std::string getRequesterName() {
42 PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
43 if(!clientMonitor) return string("pvaClientMonitor is null");
44 return clientMonitor->getRequesterName();
45 }
46
47 virtual void message(std::string const & message, MessageType messageType) {
48 PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
49 if(!clientMonitor) return;
50 clientMonitor->message(message,messageType);
51 }
52
53 virtual void monitorConnect(
54 const Status& status,
55 Monitor::shared_pointer const & monitor,
56 Structure::const_shared_pointer const & structure)
57 {
58 PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
59 if(!clientMonitor) return;
60 clientMonitor->monitorConnect(status,monitor,structure);
61 }
62
63 virtual void unlisten(MonitorPtr const & monitor)
64 {
65 PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
66 if(!clientMonitor) return;
67 clientMonitor->unlisten(monitor);
68 }
69
70 virtual void monitorEvent(MonitorPtr const & monitor)
71 {
72 PvaClientMonitorPtr clientMonitor(pvaClientMonitor.lock());
73 if(!clientMonitor) return;
74 clientMonitor->monitorEvent(monitor);
75 }
76};
77
78
80 PvaClientPtr const &pvaClient,
81 PvaClientChannelPtr const & pvaClientChannel,
82 PVStructurePtr const &pvRequest)
83{
84 PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
85 clientMonitor->monitorRequester = MonitorRequesterImplPtr(
86 new MonitorRequesterImpl(clientMonitor,pvaClient));
87 return clientMonitor;
88}
89
91 PvaClientPtr const &pvaClient,
92 std::string const & channelName,
93 std::string const & providerName,
94 std::string const & request,
95 PvaClientChannelStateChangeRequesterPtr const & stateChangeRequester,
96 PvaClientMonitorRequesterPtr const & monitorRequester)
97{
99 cout<< "PvaClientMonitor::create(pvaClient,channelName,providerName,request,stateChangeRequester,monitorRequester)\n"
100 << " channelName " << channelName
101 << " providerName " << providerName
102 << " request " << request
103 << endl;
104 }
105 CreateRequest::shared_pointer createRequest(CreateRequest::create());
106 PVStructurePtr pvRequest(createRequest->createRequest(request));
107 if(!pvRequest) throw std::runtime_error(createRequest->getMessage());
108 PvaClientChannelPtr pvaClientChannel = pvaClient->createChannel(channelName,providerName);
109 PvaClientMonitorPtr clientMonitor(new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
110 clientMonitor->monitorRequester = MonitorRequesterImplPtr(
111 new MonitorRequesterImpl(clientMonitor,pvaClient));
112 if(stateChangeRequester) clientMonitor->pvaClientChannelStateChangeRequester = stateChangeRequester;
113 if(monitorRequester) clientMonitor->pvaClientMonitorRequester = monitorRequester;
114 pvaClientChannel->setStateChangeRequester(clientMonitor);
115 pvaClientChannel->issueConnect();
116 return clientMonitor;
117}
118
119
120PvaClientMonitor::PvaClientMonitor(
121 PvaClientPtr const &pvaClient,
122 PvaClientChannelPtr const & pvaClientChannel,
123 PVStructurePtr const &pvRequest)
124: pvaClient(pvaClient),
125 pvaClientChannel(pvaClientChannel),
126 pvRequest(pvRequest),
127 isStarted(false),
128 connectState(connectIdle),
129 userPoll(false),
130 userWait(false)
131{
132 if(PvaClient::getDebug()) {
133 cout<< "PvaClientMonitor::PvaClientMonitor\n"
134 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
135 << endl;
136 }
137}
138
140{
141 if(PvaClient::getDebug()) {
142 cout<< "PvaClientMonitor::~PvaClientMonitor"
143 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
144 << endl;
145 }
146 if(monitor) {
147 if(isStarted) monitor->stop();
148 }
149}
150
151void PvaClientMonitor::channelStateChange(PvaClientChannelPtr const & channel, bool isConnected)
152{
153 if(PvaClient::getDebug()) {
154 cout<< "PvaClientMonitor::channelStateChange"
155 << " channelName " << channel->getChannelName()
156 << " isConnected " << (isConnected ? "true" : "false")
157 << endl;
158 }
159 if(isConnected&&!monitor)
160 {
161 connectState = connectActive;
162 monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
163 }
164 PvaClientChannelStateChangeRequesterPtr req(pvaClientChannelStateChangeRequester.lock());
165 if(req) {
166 req->channelStateChange(channel,isConnected);
167 }
168}
169
171{
172 if(PvaClient::getDebug()) {
173 cout << "PvaClientMonitor::event"
174 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
175 << endl;
176 }
177 PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
178 if(req) req->event(monitor);
179}
180
181void PvaClientMonitor::checkMonitorState()
182{
183 if(PvaClient::getDebug()) {
184 cout << "PvaClientMonitor::checkMonitorState"
185 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
186 << " connectState " << connectState
187 << endl;
188 }
189 if(connectState==connectIdle) {
190 connect();
191 if(!isStarted) start();
192 return;
193 }
194 if(connectState==connectActive){
195 string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
196 + " "
197 + monitorConnectStatus.getMessage();
198 throw std::runtime_error(message);
199 }
200}
201
202string PvaClientMonitor::getRequesterName()
203{
204 return pvaClientChannel->getRequesterName();
205}
206
207void PvaClientMonitor::message(string const & message,MessageType messageType)
208{
209 pvaClientChannel->message(message,messageType);
210}
211
212void PvaClientMonitor::monitorConnect(
213 const Status& status,
214 Monitor::shared_pointer const & monitor,
215 StructureConstPtr const & structure)
216{
217 if(PvaClient::getDebug()) {
218 cout << "PvaClientMonitor::monitorConnect"
219 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
220 << " status.isOK " << (status.isOK() ? "true" : "false")
221 << endl;
222 }
223 {
224 Lock xx(mutex);
225 monitorConnectStatus = status;
226 if(status.isOK()) {
227 this->monitor = monitor;
228 } else {
229 stringstream ss;
230 ss << pvRequest;
231 string message = string("\nPvaClientMonitor::monitorConnect)")
232 + "\nchannelName=" + pvaClientChannel->getChannel()->getChannelName()
233 + "\npvRequest\n" + ss.str()
234 + "\nerror\n" + status.getMessage();
235 monitorConnectStatus = Status(Status::STATUSTYPE_ERROR,message);
236 waitForConnect.signal();
237 PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
238 if(req) req->monitorConnect(status,shared_from_this(),structure);
239 return;
240 }
241 }
242 bool signal = (connectState==connectWait) ? true : false;
243 connectState = connected;
244 if(isStarted) {
245 if(PvaClient::getDebug()) {
246 cout << "PvaClientMonitor::monitorConnect"
247 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
248 << " is already started "
249 << endl;
250 }
251 waitForConnect.signal();
252 PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
253 if(req) req->monitorConnect(status,shared_from_this(),structure);
254 return;
255 }
256 pvaClientData = PvaClientMonitorData::create(structure);
257 pvaClientData->setMessagePrefix(pvaClientChannel->getChannel()->getChannelName());
258 if(signal) {
259 if(PvaClient::getDebug()) {
260 cout << "PvaClientMonitor::monitorConnect calling waitForConnect.signal\n";
261 }
262 waitForConnect.signal();
263 if(PvaClient::getDebug()) {
264 cout << "PvaClientMonitor::monitorConnect calling start\n";
265 }
266 start();
267 } else {
268 if(PvaClient::getDebug()) {
269 cout << "PvaClientMonitor::monitorConnect calling start\n";
270 }
271 start();
272 }
273 PvaClientMonitorRequesterPtr req(pvaClientMonitorRequester.lock());
274 if(req) req->monitorConnect(status,shared_from_this(),structure);
275}
276
277void PvaClientMonitor::monitorEvent(MonitorPtr const & monitor)
278{
279 if(PvaClient::getDebug()) {
280 cout << "PvaClientMonitor::monitorEvent"
281 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
282 << endl;
283 }
284 PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
285 if(req) req->event(shared_from_this());
286 if(userWait) waitForEvent.signal();
287}
288
289void PvaClientMonitor::unlisten(MonitorPtr const & monitor)
290{
291 if(PvaClient::getDebug()) cout << "PvaClientMonitor::unlisten\n";
292 PvaClientMonitorRequesterPtr req = pvaClientMonitorRequester.lock();
293 if(req) {
294 req->unlisten();
295 }
296}
297
298
300{
301 if(PvaClient::getDebug()) cout << "PvaClientMonitor::connect\n";
302 issueConnect();
303 Status status = waitConnect();
304 if(status.isOK()) return;
305 string message = string("channel ")
306 + pvaClientChannel->getChannel()->getChannelName()
307 + " PvaClientMonitor::connect "
308 + status.getMessage();
309 throw std::runtime_error(message);
310}
311
313{
314 if(PvaClient::getDebug()) cout << "PvaClientMonitor::issueConnect\n";
315 if(connectState!=connectIdle) {
316 string message = string("channel ")
317 + pvaClientChannel->getChannel()->getChannelName()
318 + " pvaClientMonitor already connected ";
319 throw std::runtime_error(message);
320 }
321 connectState = connectWait;
322 monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
323}
324
326{
327 if(PvaClient::getDebug()) {
328 cout << "PvaClientMonitor::waitConnect "
329 << pvaClientChannel->getChannel()->getChannelName()
330 << endl;
331 }
332 waitForConnect.wait();
333 if(PvaClient::getDebug()) {
334 cout << "PvaClientMonitor::waitConnect"
335 << " monitorConnectStatus " << (monitorConnectStatus.isOK() ? "connected" : "not connected")
336 << endl;
337 }
338 return monitorConnectStatus;
339}
340
342{
343 if(PvaClient::getDebug()) {
344 cout << "PvaClientMonitor::setRequester"
345 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
346 << endl;
347 }
348 this->pvaClientMonitorRequester = pvaClientMonitorRequester;
349}
350
352{
353 if(PvaClient::getDebug()) {
354 cout << "PvaClientMonitor::start"
355 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
356 << " connectState " << connectState
357 << endl;
358 }
359 if(isStarted) {
360 return;
361 }
362 if(connectState==connectIdle) connect();
363 if(connectState!=connected) {
364 string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
365 + " PvaClientMonitor::start illegal state ";
366 throw std::runtime_error(message);
367 }
368 isStarted = true;
369 monitor->start();
370}
371
372void PvaClientMonitor::start(string const & request)
373{
374 if(PvaClient::getDebug()) {
375 cout<< "PvaMonitor::start(request)"
376 << " request " << request
377 << endl;
378 }
379 PvaClientPtr client(pvaClient.lock());
380 if(!client) throw std::runtime_error("pvaClient was deleted");
381 if(!pvaClientChannel->getChannel()->isConnected()) {
382 client->message(
383 "PvaClientMonitor::start(request) but not connected",
384 errorMessage);
385 return;
386 }
387 CreateRequest::shared_pointer createRequest(CreateRequest::create());
388 PVStructurePtr pvr(createRequest->createRequest(request));
389 if(!pvr) throw std::runtime_error(createRequest->getMessage());
390 if(monitor) {
391 if(isStarted) monitor->stop();
392 }
393 monitorRequester.reset();
394 monitor.reset();
395 isStarted = false;
396 connectState = connectIdle;
397 userPoll = false;
398 userWait = false;
399 monitorRequester = MonitorRequesterImplPtr(
400 new MonitorRequesterImpl(shared_from_this(),client));
401 pvRequest = pvr;
402 connect();
403}
404
405
407{
408 if(PvaClient::getDebug()) {
409 cout << "PvaClientMonitor::stop"
410 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
411 << endl;
412 }
413 if(!isStarted) return;
414 isStarted = false;
415 monitor->stop();
416}
417
419{
420 if(PvaClient::getDebug()) {
421 cout << "PvaClientMonitor::poll"
422 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
423 << endl;
424 }
425 checkMonitorState();
426 monitorElement = monitor->poll();
427 if(!monitorElement) return false;
428 userPoll = true;
429 pvaClientData->setData(monitorElement);
430 return true;
431}
432
433bool PvaClientMonitor::waitEvent(double secondsToWait)
434{
435 if(PvaClient::getDebug()) {
436 cout << "PvaClientMonitor::waitEvent"
437 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
438 << endl;
439 }
440 if(!isStarted) {
441 string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
442 + " PvaClientMonitor::waitEvent illegal state ";
443 throw std::runtime_error(message);
444 }
445 if(poll()) return true;
446 userWait = true;
447 if(secondsToWait==0.0) {
448 waitForEvent.wait();
449 } else {
450 waitForEvent.wait(secondsToWait);
451 }
452 userWait = false;
453 return poll();
454}
455
457{
458 if(PvaClient::getDebug()) {
459 cout << "PvaClientMonitor::releaseEvent"
460 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
461 << endl;
462 }
463 if(!userPoll) {
464 string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName()
465 + " PvaClientMonitor::releaseEvent did not call poll";
466 throw std::runtime_error(message);
467 }
468 userPoll = false;
469 monitor->release(monitorElement);
470}
471
473{
474 return pvaClientChannel;
475}
476
478{
479 if(PvaClient::getDebug()) {
480 cout << "PvaClientMonitor::getData"
481 << " channelName " << pvaClientChannel->getChannel()->getChannelName()
482 << endl;
483 }
484 checkMonitorState();
485 return pvaClientData;
486}
487
488
489}}
static PvaClientMonitorDataPtr create(epics::pvData::StructureConstPtr const &structure)
virtual void unlisten()
The data source is no longer available.
Definition pvaClient.h:1495
An easy to use alternative to Monitor.
Definition pvaClient.h:1516
void releaseEvent()
Release the monitorElement returned by poll.
void event(PvaClientMonitorPtr const &monitor)
A monitor event has occurred.
void setRequester(PvaClientMonitorRequesterPtr const &pvaClientMonitorRequester)
Set a user callback.
epics::pvData::Status waitConnect()
Wait until the channelMonitor connection to the channel is complete.
PvaClientChannelPtr getPvaClientChannel()
Get the PvaClientChannel;.
static PvaClientMonitorPtr create(PvaClientPtr const &pvaClient, PvaClientChannelPtr const &pvaClientChannel, epics::pvData::PVStructurePtr const &pvRequest)
Create a PvaClientMonitor.
void issueConnect()
Issue the channelMonitor connection to the channel.
void channelStateChange(PvaClientChannelPtr const &channel, bool isConnected)
A channel connection state change has occurred.
bool waitEvent(double secondsToWait=0.0)
Wait for a monitor event.
bool poll()
Poll for a monitor event.
void connect()
Call issueConnect and then waitConnect.
PvaClientMonitorDataPtr getData()
The data in which monitor events are placed.
static bool getDebug()
Is debug set?
Definition pvaClient.cpp:97
std::tr1::shared_ptr< PvaClientMonitorData > PvaClientMonitorDataPtr
Definition pvaClient.h:55
std::tr1::shared_ptr< PvaClientChannel > PvaClientChannelPtr
Definition pvaClient.h:60
std::tr1::shared_ptr< PvaClientMonitorRequester > PvaClientMonitorRequesterPtr
Definition pvaClient.h:84
std::tr1::shared_ptr< PvaClientChannelStateChangeRequester > PvaClientChannelStateChangeRequesterPtr
Definition pvaClient.h:57
std::tr1::shared_ptr< MonitorRequesterImpl > MonitorRequesterImplPtr
Definition pvaClient.h:1506
std::tr1::shared_ptr< PvaClient > PvaClientPtr
Definition pvaClient.h:47
std::tr1::shared_ptr< PvaClientMonitor > PvaClientMonitorPtr
Definition pvaClient.h:82