3 #include <epicsAtomic.h>
4 #include <epicsString.h>
5 #include <epicsTimer.h>
8 #include <pv/pvIntrospect.h>
9 #include <pv/epicsException.h>
10 #include <pv/serverContext.h>
11 #include <pv/logger.h>
13 #define epicsExportSharedSymbols
18 #if defined(PVDATA_VERSION_INT)
19 #if PVDATA_VERSION_INT > VERSION_INT(7,0,0,0)
24 namespace pva = epics::pvAccess;
25 namespace pvd = epics::pvData;
27 std::tr1::shared_ptr<pva::ChannelProvider>
28 GWServerChannelProvider::getChannelProvider()
30 return shared_from_this();
35 pva::ChannelFind::shared_pointer
36 GWServerChannelProvider::channelFind(std::string
const & channelName,
37 pva::ChannelFindRequester::shared_pointer
const & channelFindRequester)
39 pva::ChannelFind::shared_pointer ret;
42 if(!channelName.empty())
44 LOG(pva::logLevelDebug,
"Searching for '%s'", channelName.c_str());
45 ChannelCacheEntry::shared_pointer ent(cache.lookup(channelName));
48 ret = shared_from_this();
54 channelFindRequester->channelFindResult(pvd::Status::Ok, ret, found);
61 pva::Channel::shared_pointer
62 GWServerChannelProvider::createChannel(std::string
const & channelName,
63 pva::ChannelRequester::shared_pointer
const & channelRequester,
64 short priority, std::string
const & addressx)
66 GWChannel::shared_pointer ret;
67 std::string address = channelRequester->getRequesterName();
69 if(!channelName.empty())
71 Guard G(cache.cacheLock);
73 ChannelCacheEntry::shared_pointer ent(cache.lookup(channelName));
77 ret.reset(
new GWChannel(ent, shared_from_this(), channelRequester, address));
78 ent->interested.insert(ret);
84 pvd::Status S(pvd::Status::STATUSTYPE_ERROR,
"Not found");
85 channelRequester->channelCreated(S, ret);
87 channelRequester->channelCreated(pvd::Status::Ok, ret);
88 channelRequester->channelStateChange(ret, pva::Channel::CONNECTED);
94 void GWServerChannelProvider::destroy() {}
96 GWServerChannelProvider::GWServerChannelProvider(
const pva::ChannelProvider::shared_pointer& prov)
100 GWServerChannelProvider::~GWServerChannelProvider() {}
102 void ServerConfig::drop(
const char *client,
const char *channel)
110 FOREACH(clients_t::const_iterator, it, end, clients)
112 if(client[0]!=
'\0' && client[0]!=
'*' && it->first!=client)
115 const GWServerChannelProvider::shared_pointer& prov(it->second);
117 ChannelCacheEntry::shared_pointer entry;
121 Guard G(prov->cache.cacheLock);
123 ChannelCache::entries_t::iterator it = prov->cache.entries.find(channel);
124 if(it==prov->cache.entries.end())
127 std::cout<<
"Drop from "<<it->first<<
" : "<<it->second->channelName<<
"\n";
130 prov->cache.entries.erase(it);
135 entry->channel->destroy();
140 void ServerConfig::status_server(
int lvl,
const char *server)
145 FOREACH(servers_t::const_iterator, it, end, servers)
147 if(server[0]!=
'\0' && server[0]!=
'*' && it->first!=server)
150 const pva::ServerContext::shared_pointer& serv(it->second);
151 std::cout<<
"==> Server: "<<it->first<<
"\n";
152 serv->printInfo(std::cout);
153 std::cout<<
"<== Server: "<<it->first<<
"\n\n";
158 void ServerConfig::status_client(
int lvl,
const char *client,
const char *channel)
165 bool iswild = strchr(channel,
'?') || strchr(channel,
'*');
167 FOREACH(clients_t::const_iterator, it, end, clients)
169 if(client[0]!=
'\0' && client[0]!=
'*' && it->first!=client)
172 const GWServerChannelProvider::shared_pointer& prov(it->second);
174 std::cout<<
"==> Client: "<<it->first<<
"\n";
176 ChannelCache::entries_t entries;
178 size_t ncache, ncleaned, ndust;
180 Guard G(prov->cache.cacheLock);
182 ncache = prov->cache.entries.size();
183 ncleaned = prov->cache.cleanerRuns;
184 ndust = prov->cache.cleanerDust;
188 entries = prov->cache.entries;
190 ChannelCache::entries_t::iterator it(prov->cache.entries.find(channel));
191 if(it!=prov->cache.entries.end())
192 entries[it->first] = it->second;
197 std::cout<<
"Cache has "<<ncache<<
" channels. Cleaned "
198 <<ncleaned<<
" times closing "<<ndust<<
" channels\n";
203 FOREACH(ChannelCache::entries_t::const_iterator, it2, end2, entries)
205 const std::string& channame = it2->first;
206 if(iswild && !epicsStrGlobMatch(channame.c_str(), channel))
210 ChannelCacheEntry::mon_entries_t::lock_vector_type mons;
216 chstate = pva::Channel::ConnectionStateNames[E.channel->getConnectionState()];
217 nsrv = E.interested.
size();
218 nmon = E.mon_entries.
size();
219 dropflag = E.dropPoke;
226 <<
" Client Channel '"<<channame
227 <<
"' used by "<<nsrv<<
" Server channel(s) with "
228 <<nmon<<
" unique subscription(s) "
229 <<(dropflag?
'!':
'_')<<
"\n";
234 FOREACH(ChannelCacheEntry::mon_entries_t::lock_vector_type::const_iterator, it2, end2, mons) {
237 MonitorCacheEntry::interested_t::vector_type usrs;
240 pvd::Monitor::Stats mstats;
242 bool hastype, hasdata, isdone;
246 nsrvmon = ME.interested.
size();
247 hastype = !!ME.typedesc;
253 ME.mon->getStats(mstats);
261 std::cout<<
" Client Monitor used by "<<nsrvmon<<
" Server monitors, "
262 <<
"Has "<<(hastype?
"":
"not ")
263 <<
"opened, Has "<<(hasdata?
"":
"not ")
264 <<
"recv'd some data, Has "<<(isdone?
"":
"not ")<<
"finalized\n"
265 " "<< epicsAtomicGetSizeT(&ME.nwakeups)<<
" wakeups "
266 <<epicsAtomicGetSizeT(&ME.nevents)<<
" events\n";
268 if(mstats.nempty || mstats.nfilled || mstats.noutstanding)
269 std::cout<<
" US monitor queue "<<mstats.nfilled
270 <<
" filled, "<<mstats.noutstanding
271 <<
" outstanding, "<<mstats.nempty<<
" empty\n";
276 FOREACH(MonitorCacheEntry::interested_t::vector_type::const_iterator, it3, end3, usrs) {
279 size_t nempty, nfilled, nused, total;
285 nempty = MU.empty.size();
286 nfilled = MU.filled.size();
287 nused = MU.inuse.size();
288 isrunning = MU.running;
290 GWChannel::shared_pointer srvchan(MU.srvchan.lock());
292 remote = srvchan->address;
294 remote =
"<unknown>";
296 total = nempty + nfilled + nused;
298 std::cout<<
" Server monitor from "
300 <<(isrunning?
"":
" Paused")
301 <<
" buffer "<<nfilled<<
"/"<<total
302 <<
" out "<<nused<<
"/"<<total
303 <<
" "<<epicsAtomicGetSizeT(&MU.nwakeups)<<
" wakeups "
304 <<epicsAtomicGetSizeT(&MU.nevents)<<
" events "
305 <<epicsAtomicGetSizeT(&MU.ndropped)<<
" drops\n";
314 std::cout<<
"<== Client: "<<it->first<<
"\n\n";
epics::pvData::MonitorElement::shared_pointer lastelem
lock_vector_type lock_vector() const
vector_type lock_vector() const