This is Unofficial EPICS BASE Doxygen Site
caProvider.cpp
Go to the documentation of this file.
1 
7 #include <cadef.h>
8 #include <epicsSignal.h>
9 #include <epicsThread.h>
10 #include <epicsExit.h>
11 #include <pv/logger.h>
12 #include <pv/pvAccess.h>
13 
14 #include "channelConnectThread.h"
15 #include "monitorEventThread.h"
16 #include "getDoneThread.h"
17 #include "putDoneThread.h"
18 
19 #define epicsExportSharedSymbols
20 #include <pv/caProvider.h>
21 #include "caProviderPvt.h"
22 #include "caChannel.h"
23 
24 
25 namespace epics {
26 namespace pvAccess {
27 namespace ca {
28 
29 using namespace epics::pvData;
30 
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__); }
34 
36  : current_context(0)
37 {
38  initialize();
39 }
40 
41 CAChannelProvider::CAChannelProvider(const std::tr1::shared_ptr<Configuration>&)
42  : current_context(0),
43  channelConnectThread(ChannelConnectThread::get()),
44  monitorEventThread(MonitorEventThread::get()),
45  getDoneThread(GetDoneThread::get()),
46  putDoneThread(PutDoneThread::get())
47 {
48  if(DEBUG_LEVEL>0) {
49  std::cout<< "CAChannelProvider::CAChannelProvider\n";
50  }
51  initialize();
52 }
53 
55 {
56  if(DEBUG_LEVEL>0) {
57  std::cout << "CAChannelProvider::~CAChannelProvider()"
58  << " caChannelList.size() " << caChannelList.size()
59  << std::endl;
60  }
61  std::queue<CAChannelPtr> channelQ;
62  {
63  Lock lock(channelListMutex);
64  for(size_t i=0; i< caChannelList.size(); ++i)
65  {
66  CAChannelPtr caChannel(caChannelList[i].lock());
67  if(caChannel) channelQ.push(caChannel);
68  }
69  caChannelList.clear();
70  }
71  while(!channelQ.empty()) {
72  if(DEBUG_LEVEL>0) {
73  std::cout << "~CAChannelProvider() calling disconnectChannel "
74  << channelQ.front()->getChannelName()
75  << std::endl;
76  }
77  channelQ.front()->disconnectChannel();
78  channelQ.pop();
79  }
80  putDoneThread->stop();
81  getDoneThread->stop();
82  monitorEventThread->stop();
83  channelConnectThread->stop();
84  if(DEBUG_LEVEL>0) {
85  std::cout << "CAChannelProvider::~CAChannelProvider() calling ca_context_destroy\n";
86  }
88 //std::cout << "CAChannelProvider::~CAChannelProvider() returning\n";
89 }
90 
92 {
93  return "ca";
94 }
95 
96 ChannelFind::shared_pointer CAChannelProvider::channelFind(
97  std::string const & channelName,
98  ChannelFindRequester::shared_pointer const & channelFindRequester)
99 {
100  if (channelName.empty())
101  throw std::invalid_argument("CAChannelProvider::channelFind empty channel name");
102 
103  if (!channelFindRequester)
104  throw std::invalid_argument("CAChannelProvider::channelFind null requester");
105 
106  Status errorStatus(Status::STATUSTYPE_ERROR, "CAChannelProvider::channelFind not implemented");
107  ChannelFind::shared_pointer nullChannelFind;
108  EXCEPTION_GUARD(channelFindRequester->channelFindResult(errorStatus, nullChannelFind, false));
109  return nullChannelFind;
110 }
111 
112 ChannelFind::shared_pointer CAChannelProvider::channelList(
113  ChannelListRequester::shared_pointer const & channelListRequester)
114 {
115  if (!channelListRequester.get())
116  throw std::runtime_error("CAChannelProvider::channelList null requester");
117 
118  Status errorStatus(Status::STATUSTYPE_ERROR, "CAChannelProvider::channelList not implemented");
119  ChannelFind::shared_pointer nullChannelFind;
121  EXCEPTION_GUARD(channelListRequester->channelListResult(errorStatus, nullChannelFind, none, false));
122  return nullChannelFind;
123 }
124 
125 Channel::shared_pointer CAChannelProvider::createChannel(
126  std::string const & channelName,
127  ChannelRequester::shared_pointer const & channelRequester,
128  short priority)
129 {
130  Channel::shared_pointer channel(
131  createChannel(channelName, channelRequester, priority, std::string()));
132  return channel;
133 }
134 
135 Channel::shared_pointer CAChannelProvider::createChannel(
136  std::string const & channelName,
137  ChannelRequester::shared_pointer const & channelRequester,
138  short priority,
139  std::string const & address)
140 {
141  if (!address.empty())
142  throw std::invalid_argument("CAChannelProvider::createChannel does not support 'address' parameter");
143 
144  return CAChannel::create(shared_from_this(), channelName, priority, channelRequester);
145 }
146 
148 {
149  if(DEBUG_LEVEL>0) {
150  std::cout << "CAChannelProvider::addChannel "
151  << channel->getChannelName()
152  << std::endl;
153  }
154  Lock lock(channelListMutex);
155  for(size_t i=0; i< caChannelList.size(); ++i) {
156  if(!(caChannelList[i].lock())) {
157  caChannelList[i] = channel;
158  return;
159  }
160  }
161  caChannelList.push_back(channel);
162 }
163 
164 void CAChannelProvider::configure(epics::pvData::PVStructure::shared_pointer /*configuration*/)
165 {
166 }
167 
169 {
170 }
171 
173 {
174 }
175 
177 {
178  ca_client_context* thread_context = ca_current_context();
179  if (thread_context == current_context) return;
180  int result = ca_attach_context(current_context);
181  if(result==ECA_ISATTACHED) return;
182  if (result != ECA_NORMAL) {
183  std::string mess("CAChannelProvider::attachContext error calling ca_attach_context ");
184  mess += ca_message(result);
185  throw std::runtime_error(mess);
186  }
187 }
188 
189 void CAChannelProvider::initialize()
190 {
191  if(DEBUG_LEVEL>0) std::cout << "CAChannelProvider::initialize()\n";
193  if (result != ECA_NORMAL) {
194  std::string mess("CAChannelProvider::initialize error calling ca_context_create ");
195  mess += ca_message(result);
196  throw std::runtime_error(mess);
197  }
198  current_context = ca_current_context();
199 }
200 
202 {
203  if(DEBUG_LEVEL>0) std::cout << "CAClientFactory::start()\n";
204  if(ChannelProviderRegistry::clients()->getProvider("ca")) {
205  return;
206  }
209  if(!ChannelProviderRegistry::clients()->add<CAChannelProvider>("ca", true))
210  {
211  throw std::runtime_error("CAClientFactory::start failed");
212  }
213 }
214 
216 {
217  // unregister now done with exit hook
218 }
219 
220 }}}
#define DEBUG_LEVEL
Definition: caProviderPvt.h:25
pvac::PutEvent result
Definition: clientSync.cpp:117
void addChannel(const CAChannelPtr &channel)
Definition: caProvider.cpp:147
LIBCOM_API void epicsStdCall epicsSignalInstallSigPipeIgnore(void)
Definition: osdSignal.cpp:17
epicsMutexId lock
Definition: osiClockTime.c:37
int i
Definition: scan.c:967
virtual ChannelFind::shared_pointer channelList(ChannelListRequester::shared_pointer const &channelListRequester)
Definition: caProvider.cpp:112
virtual ChannelFind::shared_pointer channelFind(std::string const &channelName, ChannelFindRequester::shared_pointer const &channelFindRequester)
Definition: caProvider.cpp:96
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
A lock for multithreading.
Definition: lock.h:36
int epicsStdCall ca_attach_context(struct ca_client_context *pCtx)
Definition: access.cpp:746
static CAChannelPtr create(CAChannelProvider::shared_pointer const &channelProvider, std::string const &channelName, short priority, ChannelRequester::shared_pointer const &channelRequester)
Definition: caChannel.cpp:36
std::tr1::shared_ptr< CAChannel > CAChannelPtr
Definition: caChannel.h:31
int epicsStdCall ca_context_create(ca_preemptive_callback_select premptiveCallbackSelect)
Definition: access.cpp:172
pvData
Definition: monitor.h:428
#define ECA_NORMAL
Definition: caerr.h:77
Extended replacement for the Posix exit and atexit routines.
virtual void configure(epics::pvData::PVStructure::shared_pointer configuration)
Definition: caProvider.cpp:164
static ChannelProviderRegistry::shared_pointer clients()
LIBCOM_API void epicsStdCall epicsSignalInstallSigAlarmIgnore(void)
Definition: osdSignal.cpp:18
virtual Channel::shared_pointer createChannel(std::string const &channelName, ChannelRequester::shared_pointer const &channelRequester, short priority)
Definition: caProvider.cpp:125
static void stop()
stop provider ca
Definition: caProvider.cpp:215
#define ECA_ISATTACHED
Definition: caerr.h:130
const char *epicsStdCall ca_message(long ca_status)
Definition: access.cpp:561
#define EXCEPTION_GUARD(code)
Definition: caProvider.cpp:31
Definition: caget.c:48
OS-independent routines for ignoring Posix signals.
void epicsStdCall ca_context_destroy()
Definition: access.cpp:232
C++ and C descriptions for a thread.
static void start()
start provider ca
Definition: caProvider.cpp:201
struct ca_client_context *epicsStdCall ca_current_context()
Definition: access.cpp:726
virtual std::string getProviderName()
Definition: caProvider.cpp:91