/* pvaClient.cpp */ /** * Copyright - See the COPYRIGHT that is included with this distribution. * EPICS pvData is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ /** * @author mrk * @date 2015.02 */ #include #include #include #include #define epicsExportSharedSymbols #include using std::tr1::static_pointer_cast; using namespace epics::pvData; using namespace epics::pvAccess; using namespace epics::pvAccess::ca; using namespace std; namespace epics { namespace pvaClient { class epicsShareClass PvaClientChannelCache { public: PvaClientChannelCache(){} ~PvaClientChannelCache(){ if(PvaClient::getDebug()) cout << "PvaClientChannelCache::~PvaClientChannelCache\n"; } PvaClientChannelPtr getChannel( string const & channelName, string const & providerName); void addChannel(PvaClientChannelPtr const & pvaClientChannel); void showCache(); size_t cacheSize(); private: map pvaClientChannelMap; }; PvaClientChannelPtr PvaClientChannelCache::getChannel( string const & channelName, string const & providerName) { string name = channelName + providerName; map::iterator iter = pvaClientChannelMap.find(name); if(iter!=pvaClientChannelMap.end()) return iter->second; return PvaClientChannelPtr(); } void PvaClientChannelCache::addChannel(PvaClientChannelPtr const & pvaClientChannel) { Channel::shared_pointer channel = pvaClientChannel->getChannel(); string name = channel->getChannelName() + channel->getProvider()->getProviderName(); map::iterator iter = pvaClientChannelMap.find(name); if(iter!=pvaClientChannelMap.end()) { throw std::runtime_error("pvaClientChannelCache::addChannel channel already cached"); } pvaClientChannelMap.insert(std::pair( name,pvaClientChannel)); } void PvaClientChannelCache::showCache() { map::iterator iter; for(iter = pvaClientChannelMap.begin(); iter != pvaClientChannelMap.end(); ++iter) { PvaClientChannelPtr pvaChannel = iter->second; Channel::shared_pointer channel = pvaChannel->getChannel(); string channelName = channel->getChannelName(); string providerName = channel->getProvider()->getProviderName(); cout << "channel " << channelName << " provider " << providerName << endl; pvaChannel->showCache(); } } size_t PvaClientChannelCache::cacheSize() { return pvaClientChannelMap.size(); } bool PvaClient::debug = false; PvaClientPtr PvaClient::get(std::string const & providerNames) { static PvaClientPtr master; static Mutex mutex; Lock xx(mutex); if(!master) { master = PvaClientPtr(new PvaClient(providerNames)); } return master; } PvaClient::PvaClient(std::string const & providerNames) : pvaClientChannelCache(new PvaClientChannelCache()), pvaStarted(false), caStarted(false), channelRegistry(ChannelProviderRegistry::clients()) { stringstream ss(providerNames); string providerName; if(PvaClient::debug) { cout<< "PvaClient::PvaClient()\n"; } while (getline(ss, providerName, ' ')) { if(providerName=="pva") { if(PvaClient::debug) { cout<< "calling ClientFactory::start()\n"; } ClientFactory::start(); pvaStarted = true; } else if(providerName=="ca") { if(PvaClient::debug) { cout<< "calling CAClientFactory::start()\n"; } CAClientFactory::start(); caStarted = true; } else { if(!channelRegistry->getProvider(providerName)) { cerr << "PvaClient::get provider " << providerName << " not known" << endl; } } } } PvaClient::~PvaClient() { if(PvaClient::debug) { cout<< "PvaClient::~PvaClient()\n" << "pvaChannel cache:\n"; showCache(); } if(pvaStarted){ if(PvaClient::debug) cout<< "calling ClientFactory::stop()\n"; ClientFactory::stop(); if(PvaClient::debug) cout<< "after calling ClientFactory::stop()\n"; } if(caStarted) { if(PvaClient::debug) cout<< "calling CAClientFactory::stop()\n"; CAClientFactory::stop(); if(PvaClient::debug) cout<< "after calling CAClientFactory::stop()\n"; } channelRegistry.reset(); } string PvaClient:: getRequesterName() { static string name("pvaClient"); RequesterPtr req = requester.lock(); if(req) { return req->getRequesterName(); } return name; } void PvaClient::message( string const & message, MessageType messageType) { RequesterPtr req = requester.lock(); if(req) { req->message(message,messageType); return; } cout << getMessageTypeName(messageType) << " " << message << endl; } PvaClientChannelPtr PvaClient::channel( std::string const & channelName, std::string const & providerName, double timeOut) { PvaClientChannelPtr pvaClientChannel = pvaClientChannelCache->getChannel(channelName,providerName); if(pvaClientChannel) return pvaClientChannel; pvaClientChannel = createChannel(channelName,providerName); pvaClientChannel->connect(timeOut); pvaClientChannelCache->addChannel(pvaClientChannel); return pvaClientChannel; } PvaClientChannelPtr PvaClient::createChannel(string const & channelName, string const & providerName) { return PvaClientChannel::create(shared_from_this(),channelName,providerName); } void PvaClient::setRequester(RequesterPtr const & requester) { this->requester = requester; } void PvaClient::clearRequester() { requester.reset(); } void PvaClient::showCache() { if(pvaClientChannelCache->cacheSize()>=1) { pvaClientChannelCache->showCache(); } else { cout << "pvaClientChannelCache is empty\n"; } } size_t PvaClient::cacheSize() { return pvaClientChannelCache->cacheSize(); } }}