This is Unofficial EPICS BASE Doxygen Site
pvaClient.cpp
Go to the documentation of this file.
1 /* pvaClient.cpp */
12 #include <map>
13 #include <pv/createRequest.h>
14 #include <pv/clientFactory.h>
15 #include <pv/caProvider.h>
16 
17 #define epicsExportSharedSymbols
18 
19 #include <pv/pvaClient.h>
20 
21 using namespace epics::pvData;
22 using namespace epics::pvAccess;
23 using namespace epics::pvAccess::ca;
24 using namespace std;
25 
26 namespace epics { namespace pvaClient {
27 
28 
30 {
31 public:
34  if(PvaClient::getDebug()) cout << "PvaClientChannelCache::~PvaClientChannelCache\n";
35  }
36  PvaClientChannelPtr getChannel(
37  string const & channelName,
38  string const & providerName);
39  void addChannel(PvaClientChannelPtr const & pvaClientChannel);
40  void showCache();
41  size_t cacheSize();
42 private:
43  map<string,PvaClientChannelPtr> pvaClientChannelMap;
44 };
45 
46 PvaClientChannelPtr PvaClientChannelCache::getChannel(
47  string const & channelName,
48  string const & providerName)
49 {
50  string name = channelName + providerName;
51  map<string,PvaClientChannelPtr>::iterator iter = pvaClientChannelMap.find(name);
52  if(iter!=pvaClientChannelMap.end()) return iter->second;
53  return PvaClientChannelPtr();
54 }
55 
56 void PvaClientChannelCache::addChannel(PvaClientChannelPtr const & pvaClientChannel)
57 {
58  Channel::shared_pointer channel = pvaClientChannel->getChannel();
59  string name = channel->getChannelName()
60  + channel->getProvider()->getProviderName();
61  map<string,PvaClientChannelPtr>::iterator iter = pvaClientChannelMap.find(name);
62  if(iter!=pvaClientChannelMap.end()) {
63  throw std::runtime_error("pvaClientChannelCache::addChannel channel already cached");
64  }
65  pvaClientChannelMap.insert(std::pair<string,PvaClientChannelPtr>(
66  name,pvaClientChannel));
67 }
68 
69 void PvaClientChannelCache::showCache()
70 {
71  map<string,PvaClientChannelPtr>::iterator iter;
72  for(iter = pvaClientChannelMap.begin(); iter != pvaClientChannelMap.end(); ++iter)
73  {
74  PvaClientChannelPtr pvaChannel = iter->second;
75  Channel::shared_pointer channel = pvaChannel->getChannel();
76  string channelName = channel->getChannelName();
77  string providerName = channel->getProvider()->getProviderName();
78  cout << "channel " << channelName << " provider " << providerName << endl;
79  pvaChannel->showCache();
80  }
81 }
82 
83 size_t PvaClientChannelCache::cacheSize()
84 {
85  return pvaClientChannelMap.size();
86 
87 }
88 
89 // MSVC doesn't like making this a class static data member:
90 static bool debug = 0;
91 
92 void PvaClient::setDebug(bool value)
93 {
94  debug = value;
95 }
96 
97 bool PvaClient::getDebug()
98 {
99  return debug;
100 }
101 
102 PvaClientPtr PvaClient::get(std::string const & providerNames)
103 {
104  static PvaClientPtr master;
105  static Mutex mutex;
106  Lock xx(mutex);
107  if(!master) {
108  master = PvaClientPtr(new PvaClient(providerNames));
109  }
110  return master;
111 }
112 
113 PvaClientPtr PvaClient::create() {return get();}
114 
115 PvaClient::PvaClient(std::string const & providerNames)
116 : pvaClientChannelCache(new PvaClientChannelCache()),
117  pvaStarted(false),
118  caStarted(false),
119  channelRegistry(ChannelProviderRegistry::clients())
120 {
121  stringstream ss(providerNames);
122  string providerName;
123  if(getDebug()) {
124  cout<< "PvaClient::PvaClient()\n";
125  }
126  while (getline(ss, providerName, ' '))
127  {
128  if(providerName=="pva") {
129  if(getDebug()) {
130  cout<< "calling ClientFactory::start()\n";
131  }
132  ClientFactory::start();
133  pvaStarted = true;
134  } else if(providerName=="ca") {
135  if(getDebug()) {
136  cout<< "calling CAClientFactory::start()\n";
137  }
138  CAClientFactory::start();
139  caStarted = true;
140  } else {
141  if(!channelRegistry->getProvider(providerName)) {
142  cerr << "PvaClient::get provider " << providerName << " not known" << endl;
143  }
144  }
145  }
146 }
147 
148 PvaClient::~PvaClient() {
149  if(getDebug()) {
150  cout<< "PvaClient::~PvaClient()\n"
151  << "pvaChannel cache:\n";
152  showCache();
153  }
154  if(pvaStarted){
155  if(getDebug()) cout<< "calling ClientFactory::stop()\n";
156  ClientFactory::stop();
157  if(getDebug()) cout<< "after calling ClientFactory::stop()\n";
158  }
159  if(caStarted) {
160  if(getDebug()) cout<< "calling CAClientFactory::stop()\n";
161  CAClientFactory::stop();
162  if(getDebug()) cout<< "after calling CAClientFactory::stop()\n";
163  }
164 channelRegistry.reset();
165 }
166 
167 string PvaClient:: getRequesterName()
168 {
169  static string name("pvaClient");
170  RequesterPtr req = requester.lock();
171  if(req) {
172  return req->getRequesterName();
173  }
174  return name;
175 }
176 
177 void PvaClient::message(
178  string const & message,
179  MessageType messageType)
180 {
181  RequesterPtr req = requester.lock();
182  if(req) {
183  req->message(message,messageType);
184  return;
185  }
186  cout << getMessageTypeName(messageType) << " " << message << endl;
187 }
188 
189 PvaClientChannelPtr PvaClient::channel(
190  std::string const & channelName,
191  std::string const & providerName,
192  double timeOut)
193 {
194  PvaClientChannelPtr pvaClientChannel =
195  pvaClientChannelCache->getChannel(channelName,providerName);
196  if(pvaClientChannel) return pvaClientChannel;
197  pvaClientChannel = createChannel(channelName,providerName);
198  pvaClientChannel->connect(timeOut);
199  pvaClientChannelCache->addChannel(pvaClientChannel);
200  return pvaClientChannel;
201 }
202 
203 PvaClientChannelPtr PvaClient::createChannel(string const & channelName, string const & providerName)
204 {
205  return PvaClientChannel::create(shared_from_this(),channelName,providerName);
206 }
207 
208 void PvaClient::setRequester(RequesterPtr const & requester)
209 {
210  this->requester = requester;
211 }
212 
213 void PvaClient::clearRequester()
214 {
215  requester.reset();
216 }
217 
218 void PvaClient::showCache()
219 {
220  if(pvaClientChannelCache->cacheSize()>=1) {
221  pvaClientChannelCache->showCache();
222  } else {
223  cout << "pvaClientChannelCache is empty\n";
224  }
225 }
226 
227 
228 size_t PvaClient::cacheSize()
229 {
230  return pvaClientChannelCache->cacheSize();
231 }
232 
233 }}
std::tr1::shared_ptr< PvaClient > PvaClientPtr
Definition: pvaClient.h:46
Definition: link.h:174
epicsShareExtern std::string getMessageTypeName(MessageType messageType)
Definition: requester.cpp:25
std::tr1::shared_ptr< PvaClientChannel > PvaClientChannelPtr
Definition: pvaClient.h:59
std::tr1::shared_ptr< Requester > RequesterPtr
Definition: requester.h:31
Definition: memory.hpp:41
TODO only here because of the Lockable.
Definition: ntaggregate.cpp:16
A lock for multithreading.
Definition: lock.h:36
Holds all PVA related.
Definition: pvif.h:34
pvData
Definition: monitor.h:428
epicsMutex mutex
Definition: pvAccess.cpp:71
ChannelProviderRegistry::shared_pointer clients
const ChannelProcessRequester::weak_pointer requester
Definition: pvAccess.cpp:68
#define epicsShareClass
Definition: shareLib.h:206
pvaClient is a synchronous wrapper for the pvAccess API, which is a callback based API...
Definition: pvaClient.h:106
Definition: caget.c:48
epicsMutex Mutex
Definition: lock.h:28