8 #include <epicsVersion.h> 18 #define epicsExportSharedSymbols 31 #define EXCEPTION_GUARD(code) try { code; } \ 32 catch (std::exception &e) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d: %s", __FILE__, __LINE__, e.what()); } \ 33 catch (...) { LOG(logLevelError, "Unhandled exception caught from client code at %s:%d.", __FILE__, __LINE__); } 36 CAChannel::shared_pointer CAChannel::create(CAChannelProvider::shared_pointer
const & channelProvider,
37 std::string
const & channelName,
39 ChannelRequester::shared_pointer
const & channelRequester)
42 cout<<
"CAChannel::create " << channelName << endl;
45 new CAChannel(channelName, channelProvider, channelRequester));
46 caChannel->activate(priority);
61 void CAChannel::connect(
bool isConnected)
64 cout<<
"CAChannel::connect " << channelName << endl;
68 channelConnected = isConnected;
70 channelConnectThread->channelConnected(notifyChannelRequester);
73 void CAChannel::notifyClient()
76 cout<<
"CAChannel::notifyClient " << channelName << endl;
80 bool isConnected =
false;
83 isConnected = channelConnected;
86 ChannelRequester::shared_pointer req(channelRequester.lock());
89 shared_from_this(), Channel::DISCONNECTED));
93 while(!getFieldQueue.empty()) {
94 getFieldQueue.front()->activate();
97 while(!putQueue.empty()) {
98 putQueue.front()->activate();
101 while(!getQueue.empty()) {
102 getQueue.front()->activate();
105 while(!monitorQueue.empty()) {
111 ChannelRequester::shared_pointer req(channelRequester.lock());
114 shared_from_this(), Channel::CONNECTED));
119 CAChannel::CAChannel(std::string
const & channelName,
120 CAChannelProvider::shared_pointer
const & channelProvider,
121 ChannelRequester::shared_pointer
const & channelRequester) :
122 channelName(channelName),
123 channelProvider(channelProvider),
124 channelRequester(channelRequester),
126 channelCreated(
false),
127 channelConnected(
false),
131 cout<<
"CAChannel::CAChannel " << channelName << endl;
135 void CAChannel::activate(
short priority)
137 ChannelRequester::shared_pointer req(channelRequester.lock());
140 cout<<
"CAChannel::activate " << channelName << endl;
143 notifyChannelRequester->setChannel(shared_from_this());
146 ca_connection_handler,
152 channelCreated =
true;
154 if(provider) provider->addChannel(shared_from_this());
162 CAChannel::~CAChannel()
165 cout <<
"CAChannel::~CAChannel() " << channelName
166 <<
" channelCreated " << (channelCreated ?
"true" :
"false")
171 if(!channelCreated)
return;
176 void CAChannel::disconnectChannel()
179 cout <<
"CAChannel::disconnectChannel() " 181 <<
" channelCreated " << (channelCreated ?
"true" :
"false")
186 if(!channelCreated)
return;
187 channelCreated =
false;
189 std::vector<CAChannelMonitorWPtr>::iterator it;
190 for(it = monitorlist.begin(); it!=monitorlist.end(); ++it)
196 monitorlist.resize(0);
204 string mess(
"CAChannel::disconnectChannel() ");
206 cerr << mess << endl;
214 std::tr1::shared_ptr<ChannelProvider> CAChannel::getProvider()
216 return channelProvider.lock();
220 std::string CAChannel::getRemoteAddress()
228 Channel::NEVER_CONNECTED,
229 Channel::DISCONNECTED,
240 std::string CAChannel::getChannelName()
246 std::tr1::shared_ptr<ChannelRequester> CAChannel::getChannelRequester()
248 return channelRequester.lock();
251 void CAChannel::getField(GetFieldRequester::shared_pointer
const &
requester,
252 std::string
const & subField)
255 cout <<
"CAChannel::getField " << channelName << endl;
261 if(getConnectionState()!=Channel::CONNECTED) {
262 getFieldQueue.push(getField);
266 getField->callRequester(shared_from_this());
270 AccessRights CAChannel::getAccessRights(PVField::shared_pointer
const & )
281 ChannelGet::shared_pointer CAChannel::createChannelGet(
282 ChannelGetRequester::shared_pointer
const & channelGetRequester,
283 PVStructure::shared_pointer
const & pvRequest)
286 cout <<
"CAChannel::createChannelGet " << channelName << endl;
289 CAChannelGet::create(shared_from_this(), channelGetRequester, pvRequest);
292 if(getConnectionState()!=Channel::CONNECTED) {
293 getQueue.push(channelGet);
297 channelGet->activate();
302 ChannelPut::shared_pointer CAChannel::createChannelPut(
303 ChannelPutRequester::shared_pointer
const & channelPutRequester,
304 PVStructure::shared_pointer
const & pvRequest)
307 cout <<
"CAChannel::createChannelPut " << channelName << endl;
310 CAChannelPut::create(shared_from_this(), channelPutRequester, pvRequest);
313 if(getConnectionState()!=Channel::CONNECTED) {
314 putQueue.push(channelPut);
318 channelPut->activate();
323 Monitor::shared_pointer CAChannel::createMonitor(
324 MonitorRequester::shared_pointer
const & monitorRequester,
325 PVStructure::shared_pointer
const & pvRequest)
328 cout <<
"CAChannel::createMonitor " << channelName << endl;
331 CAChannelMonitor::create(shared_from_this(), monitorRequester, pvRequest);
334 if(getConnectionState()!=Channel::CONNECTED) {
335 monitorQueue.push(channelMonitor);
336 return channelMonitor;
339 channelMonitor->activate();
340 addMonitor(channelMonitor);
341 return channelMonitor;
346 std::vector<CAChannelMonitorWPtr>::iterator it;
347 for(it = monitorlist.begin(); it!=monitorlist.end(); ++it)
350 if(mon.lock())
continue;
354 monitorlist.push_back(monitor);
357 void CAChannel::printInfo(std::ostream& out)
359 out <<
"CHANNEL : " << getChannelName() << std::endl;
362 out <<
"STATE : " << ConnectionStateNames[state] << std::endl;
363 if (state == CONNECTED)
365 out <<
"ADDRESS : " << getRemoteAddress() << std::endl;
371 CAChannelGetField::CAChannelGetField(
373 GetFieldRequester::shared_pointer
const &
requester,std::string
const & subField)
375 getFieldRequester(requester),
379 cout <<
"CAChannelGetField::CAChannelGetField()\n";
392 cout <<
"CAChannelGetField::~CAChannelGetField()\n";
399 cout <<
"CAChannelGetField::callRequester\n";
401 GetFieldRequester::shared_pointer
requester(getFieldRequester.lock());
405 Structure::const_shared_pointer
structure(dbdToPv->getStructure());
406 Field::const_shared_pointer field =
431 string mess(
"CAChannel::attachContext provider does not exist ");
432 mess += getChannelName();
433 throw std::runtime_error(mess);
437 CAChannel::shared_pointer
const & channel,
438 ChannelGetRequester::shared_pointer
const & channelGetRequester,
439 PVStructure::shared_pointer
const & pvRequest)
442 cout <<
"CAChannelGet::create " << channel->getChannelName() << endl;
447 CAChannelGet::CAChannelGet(CAChannel::shared_pointer
const & channel,
448 ChannelGetRequester::shared_pointer
const & channelGetRequester,
449 PVStructure::shared_pointer
const & pvRequest)
452 channelGetRequester(channelGetRequester),
453 pvRequest(pvRequest),
461 std::cout <<
"CAChannelGet::~CAChannelGet() " << channel->getChannelName() << endl;
467 ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock());
468 if(!getRequester)
return;
470 std::cout <<
"CAChannelGet::activate " << channel->getChannelName() << endl;
473 dbdToPv->getChoices(channel);
474 pvStructure = dbdToPv->createPVStructure();
475 bitSet =
BitSetPtr(
new BitSet(pvStructure->getStructure()->getNumberFields()));
477 notifyGetRequester->setChannelGet(shared_from_this());
479 pvStructure->getStructure()));
499 std::cout <<
"CAChannelGet::getDone " 500 << channel->getChannelName() << endl;
503 ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock());
504 if(!getRequester)
return;
505 getStatus = dbdToPv->getFromDBD(pvStructure,bitSet,args);
506 getDoneThread->getDone(notifyGetRequester);
512 std::cout <<
"CAChannelGet::notifyClient " << channel->getChannelName() << endl;
514 ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock());
515 if(!getRequester)
return;
516 EXCEPTION_GUARD(getRequester->getDone(getStatus, shared_from_this(), pvStructure, bitSet));
522 std::cout <<
"CAChannelGet::get " << channel->getChannelName() << endl;
524 ChannelGetRequester::shared_pointer getRequester(channelGetRequester.lock());
525 if(!getRequester)
return;
526 channel->attachContext();
530 channel->getChannelID(), ca_get_handler,
this);
537 string mess(
"CAChannelGet::get ");
538 mess += channel->getChannelName() +
" message " +
ca_message(result);
558 CAChannel::shared_pointer
const & channel,
559 ChannelPutRequester::shared_pointer
const & channelPutRequester,
560 PVStructure::shared_pointer
const & pvRequest)
563 cout <<
"CAChannelPut::create " << channel->getChannelName() << endl;
568 CAChannelPut::CAChannelPut(CAChannel::shared_pointer
const & channel,
569 ChannelPutRequester::shared_pointer
const & channelPutRequester,
570 PVStructure::shared_pointer
const & pvRequest)
573 channelPutRequester(channelPutRequester),
574 pvRequest(pvRequest),
585 std::cout <<
"CAChannelPut::~CAChannelPut() " << channel->getChannelName() << endl;
592 ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock());
593 if(!putRequester)
return;
595 cout <<
"CAChannelPut::activate " << channel->getChannelName() << endl;
598 dbdToPv->getChoices(channel);
599 pvStructure = dbdToPv->createPVStructure();
600 bitSet =
BitSetPtr(
new BitSet(pvStructure->getStructure()->getNumberFields()));
603 std::string val = pvString->
get();
604 if(val.compare(
"true")==0) block =
true;
607 notifyPutRequester->setChannelPut(shared_from_this());
609 pvStructure->getStructure()));
635 BitSet::shared_pointer
const & )
638 cout <<
"CAChannelPut::put " << channel->getChannelName() << endl;
640 ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock());
641 if(!putRequester)
return;
646 putStatus = dbdToPv->putToDBD(channel,pvPutStructure,block,&ca_put_handler,
this);
647 if(!block || !putStatus.isOK()) {
656 cout <<
"CAChannelPut::putDone " << channel->getChannelName() << endl;
658 ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock());
659 if(!putRequester)
return;
666 putDoneThread->putDone(notifyPutRequester);
672 cout <<
"CAChannelPut::getDone " << channel->getChannelName() << endl;
675 ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock());
676 if(!putRequester)
return;
677 getStatus = dbdToPv->getFromDBD(pvStructure,bitSet,args);
678 putDoneThread->putDone(notifyPutRequester);
683 ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock());
684 if(!putRequester)
return;
688 EXCEPTION_GUARD(putRequester->getDone(getStatus, shared_from_this(), pvStructure, bitSet));
696 std::cout <<
"CAChannelPut::get " << channel->getChannelName() << endl;
698 ChannelPutRequester::shared_pointer putRequester(channelPutRequester.lock());
699 if(!putRequester)
return;
705 channel->attachContext();
709 channel->getChannelID(), ca_put_get_handler,
this);
716 string mess(
"CAChannelPut::get ");
717 mess += channel->getChannelName() +
" message " +
ca_message(result);
719 EXCEPTION_GUARD(putRequester->getDone(status, shared_from_this(), pvStructure, bitSet));
748 public std::tr1::enable_shared_from_this<CACMonitorQueue>
757 std::queue<MonitorElementPtr> monitorElementQueue;
761 : queueSize(queueSize),
770 while(!monitorElementQueue.empty()) monitorElementQueue.pop();
776 while(!monitorElementQueue.empty()) monitorElementQueue.pop();
785 if(!isStarted)
return false;
786 if(monitorElementQueue.size()==queueSize)
return false;
787 PVStructure::shared_pointer pvs =
790 *(monitorElement->changedBitSet) = *(activeElement->changedBitSet);
791 *(monitorElement->overrunBitSet) = *(activeElement->overrunBitSet);
792 monitorElementQueue.push(monitorElement);
806 if(!isStarted)
return;
807 if(monitorElementQueue.empty()) {
808 string mess(
"CAChannelMonitor::release client error calling release ");
809 throw std::runtime_error(mess);
811 monitorElementQueue.pop();
816 CAChannel::shared_pointer
const & channel,
817 MonitorRequester::shared_pointer
const & monitorRequester,
818 PVStructure::shared_pointer
const & pvRequest)
821 cout <<
"CAChannelMonitor::create " << channel->getChannelName() << endl;
826 CAChannelMonitor::CAChannelMonitor(
827 CAChannel::shared_pointer
const & channel,
828 MonitorRequester::shared_pointer
const & monitorRequester,
832 monitorRequester(monitorRequester),
833 pvRequest(pvRequest),
843 std::cout <<
"CAChannelMonitor::~CAChannelMonitor() " 844 << channel->getChannelName()
845 <<
" isStarted " << (isStarted ?
"true" :
"false")
853 MonitorRequester::shared_pointer
requester(monitorRequester.lock());
856 std::cout <<
"CAChannelMonitor::activate " << channel->getChannelName() << endl;
859 dbdToPv->getChoices(channel);
860 pvStructure = dbdToPv->createPVStructure();
868 std::stringstream ss;
869 ss << pvString->
get();
871 if (size > 1) queueSize = size;
873 pvString = pvOptions->getSubField<
PVString>(
"DBE");
875 std::string
value(pvString->get());
884 notifyMonitorRequester->setChannelMonitor(shared_from_this());
887 pvStructure->getStructure()));
895 std::cout <<
"CAChannelMonitor::subscriptionEvent " 896 << channel->getChannelName() << endl;
900 if(!isStarted)
return;
902 MonitorRequester::shared_pointer
requester(monitorRequester.lock());
904 Status status = dbdToPv->getFromDBD(pvStructure,activeElement->changedBitSet,args);
907 if(monitorQueue->event(pvStructure,activeElement)) {
908 activeElement->changedBitSet->clear();
909 activeElement->overrunBitSet->clear();
911 *(activeElement->overrunBitSet) |= *(activeElement->changedBitSet);
913 monitorEventThread->event(notifyMonitorRequester);
917 string mess(
"CAChannelMonitor::subscriptionEvent ");
918 mess += channel->getChannelName();
920 throw std::runtime_error(mess);
929 if(!isStarted)
return;
931 MonitorRequester::shared_pointer
requester(monitorRequester.lock());
933 requester->monitorEvent(shared_from_this());
939 std::cout <<
"CAChannelMonitor::start " << channel->getChannelName() << endl;
949 monitorQueue->start();
951 channel->attachContext();
954 channel->getChannelID(), eventMask,
955 ca_subscription_handler,
this,
970 std::cout <<
"CAChannelMonitor::stop " 971 << channel->getChannelName()
972 <<
" isStarted " << (isStarted ?
"true" :
"false")
980 monitorQueue->stop();
990 std::cout <<
"CAChannelMonitor::poll " << channel->getChannelName() << endl;
996 return monitorQueue->poll();
1003 std::cout <<
"CAChannelMonitor::release " << channel->getChannelName() << endl;
1005 monitorQueue->release(monitorElement);
virtual Channel::shared_pointer getChannel()
LIBCA_API int epicsStdCall ca_array_get_callback(chtype type, unsigned long count, chid chanId, caEventCallBackFunc *pFunc, void *pArg)
bool event(const PVStructurePtr &pvStructure, const MonitorElementPtr &activeElement)
LIBCA_API unsigned epicsStdCall ca_write_access(chid chan)
virtual Channel::shared_pointer getChannel()
std::tr1::shared_ptr< CACMonitorQueue > CACMonitorQueuePtr
int epicsStdCall ca_create_channel(const char *name_str, caCh *conn_func, void *puser, capri priority, chid *chanptr)
void release(MonitorElementPtr const &monitorElement)
LIBCA_API enum channel_state epicsStdCall ca_state(chid chan)
void getDone(struct event_handler_args &args)
shared_ptr< T > static_pointer_cast(shared_ptr< U > const &r) BOOST_NOEXCEPT
POINTER_DEFINITIONS(CAChannelGetField)
LIBCA_API const char *epicsStdCall ca_host_name(chid channel)
static CAChannelGet::shared_pointer create(CAChannel::shared_pointer const &channel, ChannelGetRequester::shared_pointer const &channelGetRequester, epics::pvData::PVStructurePtr const &pvRequest)
std::tr1::shared_ptr< NotifyChannelRequester > NotifyChannelRequesterPtr
TODO only here because of the Lockable.
virtual epics::pvData::Status stop()
LIBCA_API void *epicsStdCall ca_puser(chid chan)
A lock for multithreading.
virtual void lastRequest()
virtual std::string getRequesterName()
An element for a monitorQueue.
static PutDoneThreadPtr get()
void putDone(struct event_handler_args &args)
PVStructure::shared_pointer createRequest(std::string const &request)
storage_t::arg_type get() const
virtual void put(epics::pvData::PVStructure::shared_pointer const &pvPutStructure, epics::pvData::BitSet::shared_pointer const &putBitSet)
std::tr1::shared_ptr< CAChannel > CAChannelPtr
This class implements introspection object for field.
static CAChannelPut::shared_pointer create(CAChannel::shared_pointer const &channel, ChannelPutRequester::shared_pointer const &channelPutRequester, epics::pvData::PVStructurePtr const &pvRequest)
PVString is special case, since it implements SerializableArray.
std::tr1::shared_ptr< CAChannelProvider > CAChannelProviderPtr
std::tr1::shared_ptr< CAChannelGetField > CAChannelGetFieldPtr
void subscriptionEvent(struct event_handler_args &args)
std::tr1::shared_ptr< NotifyGetRequester > NotifyGetRequesterPtr
virtual void lastRequest()
int epicsStdCall ca_flush_io()
CACMonitorQueue(int32 queueSize)
std::tr1::shared_ptr< NotifyMonitorRequester > NotifyMonitorRequesterPtr
static GetDoneThreadPtr get()
const ChannelProcessRequester::weak_pointer requester
LIBCA_API int epicsStdCall ca_clear_subscription(evid pMon)
std::tr1::shared_ptr< CAChannelPut > CAChannelPutPtr
std::tr1::weak_ptr< CAChannelMonitor > CAChannelMonitorWPtr
static MonitorEventThreadPtr get()
LIBCA_API unsigned epicsStdCall ca_read_access(chid chan)
std::tr1::shared_ptr< CAChannelMonitor > CAChannelMonitorPtr
virtual MonitorElementPtr poll()
Data interface for a structure,.
std::tr1::shared_ptr< const Field > FieldConstPtr
int epicsStdCall ca_clear_channel(chid pChan)
virtual ~CAChannelMonitor()
static CAChannelMonitor::shared_pointer create(CAChannel::shared_pointer const &channel, MonitorRequester::shared_pointer const &monitorRequester, epics::pvData::PVStructurePtr const &pvRequest)
std::tr1::shared_ptr< PVStructure > PVStructurePtr
std::tr1::shared_ptr< PVString > PVStringPtr
const char *epicsStdCall ca_message(long ca_status)
std::tr1::shared_ptr< NotifyPutRequester > NotifyPutRequesterPtr
#define EXCEPTION_GUARD(code)
virtual epics::pvData::Status start()
std::tr1::shared_ptr< DbdToPv > DbdToPvPtr
std::tr1::shared_ptr< CAChannelGet > CAChannelGetPtr
std::tr1::shared_ptr< MonitorElement > MonitorElementPtr
virtual std::string getRequesterName()
std::tr1::shared_ptr< BitSet > BitSetPtr
void connect(bool isConnected)
static DbdToPvPtr create(CAChannelPtr const &caChannel, epics::pvData::PVStructurePtr const &pvRequest, IOType ioType)
void callRequester(CAChannelPtr const &caChannel)
LIBCA_API int epicsStdCall ca_create_subscription(chtype type, unsigned long count, chid chanId, long mask, caEventCallBackFunc *pFunc, void *pArg, evid *pEventID)
FORCE_INLINE const PVDataCreatePtr & getPVDataCreate()
void getDone(struct event_handler_args &args)
virtual void release(MonitorElementPtr const &monitorElement)
virtual std::string getRequesterName()