14#include <pv/bitSetUtil.h>
16#define epicsExportSharedSymbols
20using namespace epics::pvData;
21using namespace epics::pvAccess;
24namespace epics {
namespace pvaClient {
26class MonitorRequesterImpl :
public MonitorRequester
28 PvaClientMonitor::weak_pointer pvaClientMonitor;
29 PvaClient::weak_pointer pvaClient;
34 : pvaClientMonitor(pvaClientMonitor),
37 virtual ~MonitorRequesterImpl() {
41 virtual std::string getRequesterName() {
43 if(!clientMonitor)
return string(
"pvaClientMonitor is null");
44 return clientMonitor->getRequesterName();
47 virtual void message(std::string
const & message, MessageType messageType) {
49 if(!clientMonitor)
return;
50 clientMonitor->message(message,messageType);
53 virtual void monitorConnect(
55 Monitor::shared_pointer
const & monitor,
56 Structure::const_shared_pointer
const & structure)
59 if(!clientMonitor)
return;
60 clientMonitor->monitorConnect(status,monitor,structure);
63 virtual void unlisten(MonitorPtr
const & monitor)
66 if(!clientMonitor)
return;
67 clientMonitor->unlisten(monitor);
70 virtual void monitorEvent(MonitorPtr
const & monitor)
73 if(!clientMonitor)
return;
74 clientMonitor->monitorEvent(monitor);
82 PVStructurePtr
const &pvRequest)
84 PvaClientMonitorPtr clientMonitor(
new PvaClientMonitor(pvaClient,pvaClientChannel,pvRequest));
92 std::string
const & channelName,
93 std::string
const & providerName,
94 std::string
const & request,
99 cout<<
"PvaClientMonitor::create(pvaClient,channelName,providerName,request,stateChangeRequester,monitorRequester)\n"
100 <<
" channelName " << channelName
101 <<
" providerName " << providerName
102 <<
" request " << request
105 CreateRequest::shared_pointer createRequest(CreateRequest::create());
106 PVStructurePtr pvRequest(createRequest->createRequest(request));
107 if(!pvRequest)
throw std::runtime_error(createRequest->getMessage());
112 if(stateChangeRequester) clientMonitor->pvaClientChannelStateChangeRequester = stateChangeRequester;
113 if(monitorRequester) clientMonitor->pvaClientMonitorRequester = monitorRequester;
114 pvaClientChannel->setStateChangeRequester(clientMonitor);
115 pvaClientChannel->issueConnect();
116 return clientMonitor;
120PvaClientMonitor::PvaClientMonitor(
123 PVStructurePtr
const &pvRequest)
124: pvaClient(pvaClient),
125 pvaClientChannel(pvaClientChannel),
126 pvRequest(pvRequest),
128 connectState(connectIdle),
133 cout<<
"PvaClientMonitor::PvaClientMonitor\n"
134 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
142 cout<<
"PvaClientMonitor::~PvaClientMonitor"
143 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
147 if(isStarted) monitor->stop();
154 cout<<
"PvaClientMonitor::channelStateChange"
155 <<
" channelName " << channel->getChannelName()
156 <<
" isConnected " << (isConnected ?
"true" :
"false")
159 if(isConnected&&!monitor)
161 connectState = connectActive;
162 monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
166 req->channelStateChange(channel,isConnected);
173 cout <<
"PvaClientMonitor::event"
174 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
178 if(req) req->event(monitor);
181void PvaClientMonitor::checkMonitorState()
184 cout <<
"PvaClientMonitor::checkMonitorState"
185 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
186 <<
" connectState " << connectState
189 if(connectState==connectIdle) {
191 if(!isStarted)
start();
194 if(connectState==connectActive){
195 string message = string(
"channel ") + pvaClientChannel->getChannel()->getChannelName()
197 + monitorConnectStatus.getMessage();
198 throw std::runtime_error(message);
202string PvaClientMonitor::getRequesterName()
204 return pvaClientChannel->getRequesterName();
207void PvaClientMonitor::message(
string const & message,MessageType messageType)
209 pvaClientChannel->message(message,messageType);
212void PvaClientMonitor::monitorConnect(
213 const Status& status,
214 Monitor::shared_pointer
const & monitor,
215 StructureConstPtr
const & structure)
218 cout <<
"PvaClientMonitor::monitorConnect"
219 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
220 <<
" status.isOK " << (status.isOK() ?
"true" :
"false")
225 monitorConnectStatus = status;
227 this->monitor = monitor;
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();
238 if(req) req->monitorConnect(status,shared_from_this(),structure);
242 bool signal = (connectState==connectWait) ?
true : false;
243 connectState = connected;
246 cout <<
"PvaClientMonitor::monitorConnect"
247 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
248 <<
" is already started "
251 waitForConnect.signal();
253 if(req) req->monitorConnect(status,shared_from_this(),structure);
257 pvaClientData->setMessagePrefix(pvaClientChannel->getChannel()->getChannelName());
260 cout <<
"PvaClientMonitor::monitorConnect calling waitForConnect.signal\n";
262 waitForConnect.signal();
264 cout <<
"PvaClientMonitor::monitorConnect calling start\n";
269 cout <<
"PvaClientMonitor::monitorConnect calling start\n";
274 if(req) req->monitorConnect(status,shared_from_this(),structure);
277void PvaClientMonitor::monitorEvent(MonitorPtr
const & monitor)
280 cout <<
"PvaClientMonitor::monitorEvent"
281 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
285 if(req) req->event(shared_from_this());
286 if(userWait) waitForEvent.signal();
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);
315 if(connectState!=connectIdle) {
316 string message = string(
"channel ")
317 + pvaClientChannel->getChannel()->getChannelName()
318 +
" pvaClientMonitor already connected ";
319 throw std::runtime_error(message);
321 connectState = connectWait;
322 monitor = pvaClientChannel->getChannel()->createMonitor(monitorRequester,pvRequest);
328 cout <<
"PvaClientMonitor::waitConnect "
329 << pvaClientChannel->getChannel()->getChannelName()
332 waitForConnect.wait();
334 cout <<
"PvaClientMonitor::waitConnect"
335 <<
" monitorConnectStatus " << (monitorConnectStatus.isOK() ?
"connected" :
"not connected")
338 return monitorConnectStatus;
344 cout <<
"PvaClientMonitor::setRequester"
345 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
348 this->pvaClientMonitorRequester = pvaClientMonitorRequester;
354 cout <<
"PvaClientMonitor::start"
355 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
356 <<
" connectState " << connectState
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);
375 cout<<
"PvaMonitor::start(request)"
376 <<
" request " << request
380 if(!client)
throw std::runtime_error(
"pvaClient was deleted");
381 if(!pvaClientChannel->getChannel()->isConnected()) {
383 "PvaClientMonitor::start(request) but not connected",
387 CreateRequest::shared_pointer createRequest(CreateRequest::create());
388 PVStructurePtr pvr(createRequest->createRequest(request));
389 if(!pvr)
throw std::runtime_error(createRequest->getMessage());
391 if(isStarted) monitor->stop();
393 monitorRequester.reset();
396 connectState = connectIdle;
409 cout <<
"PvaClientMonitor::stop"
410 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
413 if(!isStarted)
return;
421 cout <<
"PvaClientMonitor::poll"
422 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
426 monitorElement = monitor->poll();
427 if(!monitorElement)
return false;
429 pvaClientData->setData(monitorElement);
436 cout <<
"PvaClientMonitor::waitEvent"
437 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
441 string message = string(
"channel ") + pvaClientChannel->getChannel()->getChannelName()
442 +
" PvaClientMonitor::waitEvent illegal state ";
443 throw std::runtime_error(message);
445 if(
poll())
return true;
447 if(secondsToWait==0.0) {
450 waitForEvent.wait(secondsToWait);
459 cout <<
"PvaClientMonitor::releaseEvent"
460 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
464 string message = string(
"channel ") + pvaClientChannel->getChannel()->getChannelName()
465 +
" PvaClientMonitor::releaseEvent did not call poll";
466 throw std::runtime_error(message);
469 monitor->release(monitorElement);
474 return pvaClientChannel;
480 cout <<
"PvaClientMonitor::getData"
481 <<
" channelName " << pvaClientChannel->getChannel()->getChannelName()
485 return pvaClientData;
static PvaClientMonitorDataPtr create(epics::pvData::StructureConstPtr const &structure)
virtual void unlisten()
The data source is no longer available.
An easy to use alternative to Monitor.
friend class MonitorRequesterImpl
void stop()
Stop monitoring.
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.
~PvaClientMonitor()
Destructor.
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.
void start()
Start monitoring.
static bool getDebug()
Is debug set?
std::tr1::shared_ptr< PvaClientMonitorData > PvaClientMonitorDataPtr
std::tr1::shared_ptr< PvaClientChannel > PvaClientChannelPtr
std::tr1::shared_ptr< PvaClientMonitorRequester > PvaClientMonitorRequesterPtr
std::tr1::shared_ptr< PvaClientChannelStateChangeRequester > PvaClientChannelStateChangeRequesterPtr
std::tr1::shared_ptr< MonitorRequesterImpl > MonitorRequesterImplPtr
std::tr1::shared_ptr< PvaClient > PvaClientPtr
std::tr1::shared_ptr< PvaClientMonitor > PvaClientMonitorPtr