From 66f2995a71e9490418872926dedc58727de0851c Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Wed, 15 Oct 2014 14:13:55 +0200 Subject: [PATCH] pvlist for servers w/ multiple providers --- src/server/responseHandlers.cpp | 56 +++++++++++++++++++++++---------- src/server/serverContext.cpp | 2 +- src/server/serverContext.h | 2 +- 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/src/server/responseHandlers.cpp b/src/server/responseHandlers.cpp index 86dd22b..ec7a892 100644 --- a/src/server/responseHandlers.cpp +++ b/src/server/responseHandlers.cpp @@ -451,6 +451,10 @@ public: return _waitEvent.wait(timeoutSec); } + void resetEvent() { + _waitEvent.tryWait(); + } + private: epics::pvData::Mutex _waitMutex; epics::pvData::Event _waitEvent; @@ -504,24 +508,44 @@ public: string op = opField->get(); if (op == "channels") { - ChannelListRequesterImpl::shared_pointer listListener(new ChannelListRequesterImpl()); - m_serverContext->getChannelProviders()[0]->channelList(listListener); // TODO multiple channel providers !!!! - if (!listListener->waitForCompletion(TIMEOUT_SEC)) - throw RPCRequestException(Status::STATUSTYPE_ERROR, "failed to fetch channel list due to timeout"); - - Status& status = listListener->status; - if (!status.isSuccess()) - { - string errorMessage = "failed to fetch channel list: " + status.getMessage(); - if (!status.getStackDump().empty()) - errorMessage += "\n" + status.getStackDump(); - throw RPCRequestException(Status::STATUSTYPE_ERROR, errorMessage); - } - PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(channelListStructure); - PVStringArray::shared_pointer pvArray = result->getSubField("value"); - pvArray->replace(listListener->channelNames); + PVStringArray::shared_pointer allChannelNames = result->getSubField("value"); + + ChannelListRequesterImpl::shared_pointer listListener(new ChannelListRequesterImpl()); + std::vector providers = m_serverContext->getChannelProviders(); + + size_t providerCount = providers.size(); + for (size_t i = 0; i < providerCount; i++) + { + providers[i]->channelList(listListener); + if (!listListener->waitForCompletion(TIMEOUT_SEC)) + throw RPCRequestException(Status::STATUSTYPE_ERROR, "failed to fetch channel list due to timeout"); + + Status& status = listListener->status; + if (!status.isSuccess()) + { + string errorMessage = "failed to fetch channel list: " + status.getMessage(); + if (!status.getStackDump().empty()) + errorMessage += "\n" + status.getStackDump(); + throw RPCRequestException(Status::STATUSTYPE_ERROR, errorMessage); + } + + // optimization + if (providerCount == 1) + { + allChannelNames->replace(listListener->channelNames); + } + else + { + PVStringArray::svector list(allChannelNames->reuse()); + std::copy(listListener->channelNames.begin(), listListener->channelNames.end(), + back_inserter(list)); + allChannelNames->replace(freeze(list)); + } + + listListener->resetEvent(); + } return result; } diff --git a/src/server/serverContext.cpp b/src/server/serverContext.cpp index fc3b453..460bcae 100644 --- a/src/server/serverContext.cpp +++ b/src/server/serverContext.cpp @@ -645,7 +645,7 @@ void ServerContextImpl::setChannelProviderName(std::string channelProviderName) _channelProviderNames = channelProviderName; } -std::vector ServerContextImpl::getChannelProviders() +std::vector& ServerContextImpl::getChannelProviders() { return _channelProviders; } diff --git a/src/server/serverContext.h b/src/server/serverContext.h index 7336bdb..61fb5e2 100644 --- a/src/server/serverContext.h +++ b/src/server/serverContext.h @@ -291,7 +291,7 @@ public: * Get channel providers. * @return channel providers. */ - std::vector getChannelProviders(); + std::vector& getChannelProviders(); /** * Return true if channel provider name is provided by configuration (e.g. system env. var.).