diff --git a/src/pipelineService/pipelineServer.cpp b/src/pipelineService/pipelineServer.cpp index 7c770c9..501fa5a 100644 --- a/src/pipelineService/pipelineServer.cpp +++ b/src/pipelineService/pipelineServer.cpp @@ -691,52 +691,11 @@ string PipelineChannelProvider::PROVIDER_NAME("PipelineService"); Status PipelineChannelProvider::noSuchChannelStatus(Status::STATUSTYPE_ERROR, "no such channel"); - -class PipelineChannelProviderFactory : public ChannelProviderFactory -{ -public: - POINTER_DEFINITIONS(PipelineChannelProviderFactory); - - PipelineChannelProviderFactory() : - m_channelProviderImpl(new PipelineChannelProvider()) - { - } - - virtual std::string getFactoryName() - { - return PipelineChannelProvider::PROVIDER_NAME; - } - - virtual ChannelProvider::shared_pointer sharedInstance() - { - return m_channelProviderImpl; - } - - virtual ChannelProvider::shared_pointer newInstance() - { - // TODO use std::make_shared - std::tr1::shared_ptr tp(new PipelineChannelProvider()); - ChannelProvider::shared_pointer channelProvider = tp; - return channelProvider; - } - -private: - PipelineChannelProvider::shared_pointer m_channelProviderImpl; -}; - - PipelineServer::PipelineServer() { - // TODO factory is never deregistered, multiple PipelineServer instances create multiple factories, etc. - m_channelProviderFactory.reset(new PipelineChannelProviderFactory()); - registerChannelProviderFactory(m_channelProviderFactory); - - m_channelProviderImpl = m_channelProviderFactory->sharedInstance(); - - m_serverContext = ServerContextImpl::create(); - m_serverContext->setChannelProviderName(m_channelProviderImpl->getProviderName()); - - m_serverContext->initialize(getChannelProviderRegistry()); + ChannelProvider::shared_pointer prov(new PipelineChannelProvider); + m_serverContext = ServerContext::create(ServerContext::Config() + .provider(m_channelProviderImpl)); } PipelineServer::~PipelineServer() @@ -756,40 +715,17 @@ void PipelineServer::run(int seconds) m_serverContext->run(seconds); } -struct ThreadRunnerParam { - PipelineServer::shared_pointer server; - int timeToRun; -}; - -static void threadRunner(void* usr) -{ - ThreadRunnerParam* pusr = static_cast(usr); - ThreadRunnerParam param = *pusr; - delete pusr; - - param.server->run(param.timeToRun); -} - /// Method requires usage of std::tr1::shared_ptr. This instance must be /// owned by a shared_ptr instance. void PipelineServer::runInNewThread(int seconds) { - std::auto_ptr param(new ThreadRunnerParam()); - param->server = shared_from_this(); - param->timeToRun = seconds; - - epicsThreadCreate("PipelineServer thread", - epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackSmall), - threadRunner, param.get()); - - // let the thread delete 'param' - param.release(); + if(seconds!=0) + std::cerr<<"PipelineServer::runInNewThread() only suppose seconds=0\n"; } void PipelineServer::destroy() { - m_serverContext->destroy(); + m_serverContext->shutdown(); } void PipelineServer::registerService(std::string const & serviceName, PipelineService::shared_pointer const & service) diff --git a/src/pipelineService/pv/pipelineServer.h b/src/pipelineService/pv/pipelineServer.h index 8b00033..0198b30 100644 --- a/src/pipelineService/pv/pipelineServer.h +++ b/src/pipelineService/pv/pipelineServer.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include @@ -33,8 +33,7 @@ class epicsShareClass PipelineServer : { private: - ServerContextImpl::shared_pointer m_serverContext; - ChannelProviderFactory::shared_pointer m_channelProviderFactory; + ServerContext::shared_pointer m_serverContext; ChannelProvider::shared_pointer m_channelProviderImpl; // TODO no thread poll implementation diff --git a/src/remote/pv/remote.h b/src/remote/pv/remote.h index c0a35ee..ce4d2b5 100644 --- a/src/remote/pv/remote.h +++ b/src/remote/pv/remote.h @@ -328,7 +328,7 @@ public: - virtual Configuration::shared_pointer getConfiguration() = 0; + virtual Configuration::const_shared_pointer getConfiguration() = 0; /** * Get map of available security plug-ins. diff --git a/src/remoteClient/clientContextImpl.cpp b/src/remoteClient/clientContextImpl.cpp index b5a2033..0104ee0 100644 --- a/src/remoteClient/clientContextImpl.cpp +++ b/src/remoteClient/clientContextImpl.cpp @@ -3744,9 +3744,9 @@ private: resubscribeSubscriptions(); setConnectionState(CONNECTED); } - catch (...) { + catch (std::exception& e) { + LOG(logLevelError, "connectionCompleted() %d '%s' unhandled exception: %s\n", sid, m_name.c_str(), e.what()); // noop - // TODO at least log something?? } // NOTE: always call cancel @@ -4300,7 +4300,7 @@ public: loadConfiguration(); } - virtual Configuration::shared_pointer getConfiguration() { + virtual Configuration::const_shared_pointer getConfiguration() { return m_configuration; } @@ -4746,8 +4746,8 @@ private: pvAccessID cid = generateCID(); return InternalChannelImpl::create(shared_from_this(), cid, name, requester, priority, addresses); } - catch(...) { - // TODO + catch(std::exception& e) { + LOG(logLevelError, "createChannelInternal() exception: %s\n", e.what()); return ChannelImpl::shared_pointer(); } // TODO namedLocker.releaseSynchronizationObject(name); diff --git a/src/rpcService/pv/rpcServer.h b/src/rpcService/pv/rpcServer.h index 454bce0..f552d1c 100644 --- a/src/rpcService/pv/rpcServer.h +++ b/src/rpcService/pv/rpcServer.h @@ -36,7 +36,6 @@ class epicsShareClass RPCServer : private: std::tr1::shared_ptr m_serverContext; - ChannelProviderFactory::shared_pointer m_channelProviderFactory; ChannelProvider::shared_pointer m_channelProviderImpl; // TODO no thread poll implementation diff --git a/src/rpcService/rpcServer.cpp b/src/rpcService/rpcServer.cpp index e87ce35..9df2d5d 100644 --- a/src/rpcService/rpcServer.cpp +++ b/src/rpcService/rpcServer.cpp @@ -483,52 +483,12 @@ string RPCChannelProvider::PROVIDER_NAME("rpcService"); Status RPCChannelProvider::noSuchChannelStatus(Status::STATUSTYPE_ERROR, "no such channel"); - -class RPCChannelProviderFactory : public ChannelProviderFactory -{ -public: - POINTER_DEFINITIONS(RPCChannelProviderFactory); - - RPCChannelProviderFactory() : - m_channelProviderImpl(new RPCChannelProvider()) - { - } - - virtual std::string getFactoryName() - { - return RPCChannelProvider::PROVIDER_NAME; - } - - virtual ChannelProvider::shared_pointer sharedInstance() - { - return m_channelProviderImpl; - } - - virtual ChannelProvider::shared_pointer newInstance() - { - // TODO use std::make_shared - std::tr1::shared_ptr tp(new RPCChannelProvider()); - ChannelProvider::shared_pointer channelProvider = tp; - return channelProvider; - } - -private: - RPCChannelProvider::shared_pointer m_channelProviderImpl; -}; - - RPCServer::RPCServer() + :m_channelProviderImpl(new RPCChannelProvider) { - // TODO factory is never deregistered, multiple RPCServer instances create multiple factories, etc. - m_channelProviderFactory.reset(new RPCChannelProviderFactory()); - registerChannelProviderFactory(m_channelProviderFactory); - - m_channelProviderImpl = m_channelProviderFactory->sharedInstance(); - - m_serverContext = ServerContextImpl::create(); - static_cast(m_serverContext.get())->setChannelProviderName(m_channelProviderImpl->getProviderName()); - - m_serverContext->initialize(getChannelProviderRegistry()); + ChannelProvider::shared_pointer prov(new RPCChannelProvider); + m_serverContext = ServerContext::create(ServerContext::Config() + .provider(m_channelProviderImpl)); } RPCServer::~RPCServer() @@ -581,7 +541,7 @@ void RPCServer::runInNewThread(int seconds) void RPCServer::destroy() { - m_serverContext->destroy(); + m_serverContext->shutdown(); } void RPCServer::registerService(std::string const & serviceName, RPCService::shared_pointer const & service) diff --git a/src/server/pv/serverContext.h b/src/server/pv/serverContext.h index 42147a9..d30be56 100644 --- a/src/server/pv/serverContext.h +++ b/src/server/pv/serverContext.h @@ -14,6 +14,7 @@ #include #include #include +#include #include @@ -26,8 +27,7 @@ namespace pvAccess { class epicsShareClass ServerContext { public: - typedef std::tr1::shared_ptr shared_pointer; - typedef std::tr1::shared_ptr const_shared_pointer; + POINTER_DEFINITIONS(ServerContext); /** * Destructor @@ -46,37 +46,22 @@ public: */ virtual const Version& getVersion() = 0; - /** - * Set ChannelProviderRegistry implementation and initialize server. - * @param channelProviderRegistry channel providers registry to be used. - */ - virtual void initialize(ChannelProviderRegistry::shared_pointer const & channelProviderRegistry) = 0; - /** * Run server (process events). * @param seconds time in seconds the server will process events (method will block), if 0 * the method would block until destroy() is called. * @throws BaseException if server is already destroyed. */ - virtual void run(epics::pvData::int32 seconds) = 0; + virtual void run(epics::pvData::uint32 seconds) = 0; - /** - * Shutdown (stop executing run() method) of this context. - * After shutdown Context cannot be rerun again, destroy() has to be called to clear all used resources. - * @throws BaseException if the context has been destroyed. - */ virtual void shutdown() = 0; - /** - * Clear all resources attached to this context. - * @throws BaseException if the context has been destroyed. - */ - virtual void destroy() = 0; + void destroy() EPICS_DEPRECATED { this->shutdown(); } /** * Prints detailed information about the context to the standard output stream. */ - virtual void printInfo() = 0; + void printInfo(); /** * Prints detailed information about the context to the specified output stream. @@ -84,14 +69,22 @@ public: */ virtual void printInfo(std::ostream& str) = 0; - /** - * Dispose (destroy) server context. - * This calls destroy() and silently handles all exceptions. - */ - virtual void dispose() = 0; + void dispose(); virtual epicsTimeStamp& getStartTime() = 0; + /** + * Get server port. + * @return server port. + */ + virtual epics::pvData::int32 getServerPort() = 0; + + /** + * Get broadcast port. + * @return broadcast port. + */ + virtual epics::pvData::int32 getBroadcastPort() = 0; + // ************************************************************************** // // **************************** [ Plugins ] ********************************* // // ************************************************************************** // @@ -102,6 +95,29 @@ public: */ virtual void setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer const & beaconServerStatusProvider) = 0; + class Config { + friend class ServerContext; + Configuration::const_shared_pointer _conf; + std::vector _providers; + public: + Config() {} + Config& config(const Configuration::const_shared_pointer& c) { _conf = c; return *this; } + Config& providers(const std::vector& p) { _providers = p; return *this; } + Config& provider(const ChannelProvider::shared_pointer& p) { _providers.push_back(p); return *this; } + }; + + /** Start a new PVA server + * + * By default the server will select ChannelProviders using the + * EPICS_PVA_PROVIDER_NAMES or EPICS_PVAS_PROVIDER_NAMES Configuration key. + * + * If a list of provided is given with Config::providers() then this + * overrides any Configuration. + * + * If a specific Configuration is given with Config::config() then + * this overrides the default Configuration. + */ + static ServerContext::shared_pointer create(const Config& conf = Config()); }; epicsShareFunc ServerContext::shared_pointer startPVAServer( diff --git a/src/server/pv/serverContextImpl.h b/src/server/pv/serverContextImpl.h index a5df9ba..b6fef86 100644 --- a/src/server/pv/serverContextImpl.h +++ b/src/server/pv/serverContextImpl.h @@ -1,6 +1,7 @@ #ifndef SERVERCONTEXTIMPL_H #define SERVERCONTEXTIMPL_H +#include #include #include #include @@ -15,33 +16,27 @@ class epicsShareClass ServerContextImpl : public Context, public std::tr1::enable_shared_from_this { + friend class ServerContext; public: typedef std::tr1::shared_ptr shared_pointer; typedef std::tr1::shared_ptr const_shared_pointer; -private: - ServerContextImpl(); -public: - static shared_pointer create(); - static shared_pointer create(const Configuration::shared_pointer& conf); + ServerContextImpl(); virtual ~ServerContextImpl(); //**************** derived from ServerContext ****************// const GUID& getGUID(); const Version& getVersion(); - void initialize(ChannelProviderRegistry::shared_pointer const & channelProviderRegistry); - void run(epics::pvData::int32 seconds); + void initialize(); + void run(epics::pvData::uint32 seconds); void shutdown(); - void destroy(); - void printInfo(); void printInfo(std::ostream& str); - void dispose(); void setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer const & beaconServerStatusProvider); //**************** derived from Context ****************// epics::pvData::Timer::shared_pointer getTimer(); Channel::shared_pointer getChannel(pvAccessID id); Transport::shared_pointer getSearchTransport(); - Configuration::shared_pointer getConfiguration(); + Configuration::const_shared_pointer getConfiguration(); TransportRegistry::shared_pointer getTransportRegistry(); std::map >& getSecurityPlugins(); @@ -56,53 +51,6 @@ public: */ static const Version VERSION; - - /** - * Server state enum. - */ - enum State { - /** - * State value of non-initialized context. - */ - NOT_INITIALIZED, - - /** - * State value of initialized context. - */ - INITIALIZED, - - /** - * State value of running context. - */ - RUNNING, - - /** - * State value of shutdown (once running) context. - */ - SHUTDOWN, - - /** - * State value of destroyed context. - */ - DESTROYED - }; - /** - * Names of the enum State - */ - static const char* StateNames[]; - - /** - * Get initialization status. - * @return initialization status. - */ - bool isInitialized(); - - /** - * Get destruction status. - * @return destruction status. - */ - bool isDestroyed(); - /** * Get beacon address list. * @return beacon address list. @@ -163,24 +111,6 @@ public: */ BlockingUDPTransport::shared_pointer getBroadcastTransport(); - /** - * Get channel provider registry implementation used by this instance. - * @return channel provider registry used by this instance. - */ - ChannelProviderRegistry::shared_pointer getChannelProviderRegistry(); - - /** - * Get channel provider name. - * @return channel provider name. - */ - std::string getChannelProviderName(); - - /** - * Set channel provider name. - * This method can only be called before initialize. - */ - void setChannelProviderName(std::string providerName); - /** * Get channel providers. * @return channel providers. @@ -200,11 +130,6 @@ private: */ GUID _guid; - /** - * Initialization status. - */ - State _state; - /** * A space-separated list of broadcast address which to send beacons. * Each address must be of the form: ip.number:port or host.name:port @@ -285,16 +210,6 @@ private: */ ResponseHandler::shared_pointer _responseHandler; - /** - * Channel access. - */ - ChannelProviderRegistry::shared_pointer _channelProviderRegistry; - - /** - * Channel provider name. - */ - std::string _channelProviderNames; - /** * Channel provider. */ @@ -330,30 +245,14 @@ private: */ void loadConfiguration(); - /** - * Internal initialization. - */ - void internalInitialize(); - - /** - * Initialize broadcast DP transport (broadcast socket and repeater connection). - */ - void initializeBroadcastTransport(); - - /** - * Internal destroy. - */ - void internalDestroy(); - /** * Destroy all transports. */ void destroyAllTransports(); - Configuration::shared_pointer configuration; + Configuration::const_shared_pointer configuration; epicsTimeStamp _startTime; - }; } diff --git a/src/server/responseHandlers.cpp b/src/server/responseHandlers.cpp index 04369cf..18b8d49 100644 --- a/src/server/responseHandlers.cpp +++ b/src/server/responseHandlers.cpp @@ -823,7 +823,7 @@ void ServerChannelRequesterImpl::channelCreated(const Status& status, Channel::s } catch (std::exception& e) { - LOG(logLevelDebug, "Exception caught when creating channel: %s", _channelName.c_str()); + LOG(logLevelDebug, "Exception caught when creating channel '%s': %s", _channelName.c_str(), e.what()); { Lock guard(_mutex); _status = Status(Status::STATUSTYPE_FATAL, "failed to create channel", e.what()); diff --git a/src/server/serverContext.cpp b/src/server/serverContext.cpp index d66b1c5..e735f79 100644 --- a/src/server/serverContext.cpp +++ b/src/server/serverContext.cpp @@ -24,12 +24,10 @@ using std::tr1::static_pointer_cast; namespace epics { namespace pvAccess { -const char* ServerContextImpl::StateNames[] = { "NOT_INITIALIZED", "INITIALIZED", "RUNNING", "SHUTDOWN", "DESTROYED"}; const Version ServerContextImpl::VERSION("pvAccess Server", "cpp", EPICS_PVA_MAJOR_VERSION, EPICS_PVA_MINOR_VERSION, EPICS_PVA_MAINTENANCE_VERSION, EPICS_PVA_DEVELOPMENT_FLAG); ServerContextImpl::ServerContextImpl(): - _state(NOT_INITIALIZED), _beaconAddressList(), _ignoreAddressList(), _autoBeaconAddressList(true), @@ -41,12 +39,9 @@ ServerContextImpl::ServerContextImpl(): _beaconEmitter(), _acceptor(), _transportRegistry(), - _channelProviderRegistry(), - _channelProviderNames(PVACCESS_DEFAULT_PROVIDER), _channelProviders(), _beaconServerStatusProvider(), _startTime() - { epicsTimeGetCurrent(&_startTime); @@ -58,22 +53,6 @@ ServerContextImpl::ServerContextImpl(): initializeLogger(); } -ServerContextImpl::shared_pointer ServerContextImpl::create() -{ - ServerContextImpl::shared_pointer thisPointer(new ServerContextImpl()); - thisPointer->loadConfiguration(); - return thisPointer; -} - -ServerContextImpl::shared_pointer ServerContextImpl::create( - const Configuration::shared_pointer& conf) -{ - ServerContextImpl::shared_pointer thisPointer(new ServerContextImpl()); - thisPointer->configuration = conf; - thisPointer->loadConfiguration(); - return thisPointer; -} - ServerContextImpl::~ServerContextImpl() { dispose(); @@ -89,16 +68,6 @@ const Version& ServerContextImpl::getVersion() return ServerContextImpl::VERSION; } -/* -#ifdef WIN32 - UUID uuid; - UuidCreate ( &uuid ); -#else - uuid_t uuid; - uuid_generate_random ( uuid ); -#endif -*/ - void ServerContextImpl::generateGUID() { // TODO use UUID @@ -115,7 +84,7 @@ void ServerContextImpl::initializeLogger() //createFileLogger("serverContextImpl.log"); } -Configuration::shared_pointer ServerContextImpl::getConfiguration() +Configuration::const_shared_pointer ServerContextImpl::getConfiguration() { Lock guard(_mutex); if (configuration.get() == 0) @@ -135,7 +104,7 @@ Configuration::shared_pointer ServerContextImpl::getConfiguration() */ void ServerContextImpl::loadConfiguration() { - Configuration::shared_pointer config = getConfiguration(); + Configuration::const_shared_pointer config = configuration; // TODO for now just a simple switch int32 debugLevel = config->getPropertyAsInteger(PVACCESS_DEBUG, 0); @@ -167,8 +136,45 @@ void ServerContextImpl::loadConfiguration() _receiveBufferSize = config->getPropertyAsInteger("EPICS_PVA_MAX_ARRAY_BYTES", _receiveBufferSize); _receiveBufferSize = config->getPropertyAsInteger("EPICS_PVAS_MAX_ARRAY_BYTES", _receiveBufferSize); - _channelProviderNames = config->getPropertyAsString("EPICS_PVA_PROVIDER_NAMES", _channelProviderNames); - _channelProviderNames = config->getPropertyAsString("EPICS_PVAS_PROVIDER_NAMES", _channelProviderNames); + if(_channelProviders.empty()) { + std::string providers = config->getPropertyAsString("EPICS_PVA_PROVIDER_NAMES", PVACCESS_DEFAULT_PROVIDER); + providers = config->getPropertyAsString("EPICS_PVAS_PROVIDER_NAMES", providers); + + ChannelProviderRegistry::shared_pointer reg(getChannelProviderRegistry()); + + if (providers == PVACCESS_ALL_PROVIDERS) + { + providers.resize(0); // VxWorks 5.5 omits clear() + + std::auto_ptr names = reg->getProviderNames(); + for (ChannelProviderRegistry::stringVector_t::iterator iter = names->begin(); iter != names->end(); iter++) + { + ChannelProvider::shared_pointer channelProvider = reg->getProvider(*iter); + if (channelProvider) { + _channelProviders.push_back(channelProvider); + } else { + LOG(logLevelDebug, "Provider '%s' all, but missing\n", iter->c_str()); + } + } + + } else { + // split space separated names + std::stringstream ss(providers); + std::string providerName; + while (std::getline(ss, providerName, ' ')) + { + ChannelProvider::shared_pointer channelProvider(reg->getProvider(providerName)); + if (channelProvider) { + _channelProviders.push_back(channelProvider); + } else { + LOG(logLevelWarn, "Requested provider '%s' not found", providerName.c_str()); + } + } + } + } + + if(_channelProviders.empty()) + LOG(logLevelError, "ServerContext configured with not Providers will do nothing!\n"); // // introspect network interfaces @@ -194,77 +200,14 @@ void ServerContextImpl::loadConfiguration() bool ServerContextImpl::isChannelProviderNamePreconfigured() { - Configuration::shared_pointer config = getConfiguration(); + Configuration::const_shared_pointer config = getConfiguration(); return config->hasProperty("EPICS_PVA_PROVIDER_NAMES") || config->hasProperty("EPICS_PVAS_PROVIDER_NAMES"); } -void ServerContextImpl::initialize(ChannelProviderRegistry::shared_pointer const & channelProviderRegistry) +void ServerContextImpl::initialize() { Lock guard(_mutex); - if (!channelProviderRegistry.get()) - { - THROW_BASE_EXCEPTION("channelProviderRegistry == NULL"); - } - if (_state == DESTROYED) - { - THROW_BASE_EXCEPTION("Context destroyed."); - } - else if (_state != NOT_INITIALIZED) - { - THROW_BASE_EXCEPTION("Context already initialized."); - } - - _channelProviderRegistry = channelProviderRegistry; - - - // user all providers - if (_channelProviderNames == PVACCESS_ALL_PROVIDERS) - { - _channelProviderNames.resize(0); // VxWorks 5.5 omits clear() - - std::auto_ptr names = _channelProviderRegistry->getProviderNames(); - for (ChannelProviderRegistry::stringVector_t::iterator iter = names->begin(); iter != names->end(); iter++) - { - ChannelProvider::shared_pointer channelProvider = _channelProviderRegistry->getProvider(*iter); - if (channelProvider) - { - _channelProviders.push_back(channelProvider); - - // compile a list - if (!_channelProviderNames.empty()) - _channelProviderNames += ' '; - _channelProviderNames += *iter; - } - } - } - else - { - // split space separated names - std::stringstream ss(_channelProviderNames); - std::string providerName; - while (std::getline(ss, providerName, ' ')) - { - ChannelProvider::shared_pointer channelProvider = _channelProviderRegistry->getProvider(providerName); - if (channelProvider) - _channelProviders.push_back(channelProvider); - } - } - - //_channelProvider = _channelProviderRegistry->getProvider(_channelProviderNames); - if (_channelProviders.size() == 0) - { - std::string msg = "None of the specified channel providers are available: " + _channelProviderNames + "."; - THROW_BASE_EXCEPTION(msg.c_str()); - } - - internalInitialize(); - - _state = INITIALIZED; -} - -void ServerContextImpl::internalInitialize() -{ // already called in loadConfiguration //osiSockAttach(); @@ -278,51 +221,16 @@ void ServerContextImpl::internalInitialize() _serverPort = ntohs(_acceptor->getBindAddress()->ia.sin_port); // setup broadcast UDP transport - initializeBroadcastTransport(); - - // TODO introduce "tcp" a constant - _beaconEmitter.reset(new BeaconEmitter("tcp", _broadcastTransport, thisServerContext)); -} - -void ServerContextImpl::initializeBroadcastTransport() -{ initializeUDPTransports(true, _udpTransports, _ifaceList, _responseHandler, _broadcastTransport, _broadcastPort, _autoBeaconAddressList, _beaconAddressList, _ignoreAddressList); + + _beaconEmitter.reset(new BeaconEmitter("tcp", _broadcastTransport, thisServerContext)); + + _beaconEmitter->start(); } -void ServerContextImpl::run(int32 seconds) +void ServerContextImpl::run(uint32 seconds) { - if (seconds < 0) - { - THROW_BASE_EXCEPTION("seconds cannot be negative."); - } - - { - Lock guard(_mutex); - - if (_state == NOT_INITIALIZED) - { - THROW_BASE_EXCEPTION("Context not initialized."); - } - else if (_state == DESTROYED) - { - THROW_BASE_EXCEPTION("Context destroyed."); - } - else if (_state == RUNNING) - { - THROW_BASE_EXCEPTION("Context is already running."); - } - else if (_state == SHUTDOWN) - { - THROW_BASE_EXCEPTION("Context was shutdown."); - } - - _state = RUNNING; - } - - // run... - _beaconEmitter->start(); - //TODO review this if(seconds == 0) { @@ -332,48 +240,9 @@ void ServerContextImpl::run(int32 seconds) { _runEvent.wait(seconds); } - - { - Lock guard(_mutex); - _state = SHUTDOWN; - } } void ServerContextImpl::shutdown() -{ - Lock guard(_mutex); - if(_state == DESTROYED) - { - THROW_BASE_EXCEPTION("Context already destroyed."); - } - - // notify to stop running... - _runEvent.signal(); -} - -void ServerContextImpl::destroy() -{ - Lock guard(_mutex); - if (_state == DESTROYED) - { - // silent return - return; - // exception is not OK, since we use - // shared_pointer-s auto-cleanup/destruction - // THROW_BASE_EXCEPTION("Context already destroyed."); - } - - // shutdown if not already - shutdown(); - - // go into destroyed state ASAP - _state = DESTROYED; - - internalDestroy(); -} - - -void ServerContextImpl::internalDestroy() { // stop responding to search requests for (BlockingUDPTransportVector::const_iterator iter = _udpTransports.begin(); @@ -404,6 +273,12 @@ void ServerContextImpl::internalDestroy() // this will also destroy all channels destroyAllTransports(); + + // response handlers hold strong references to us, + // so must break the cycles + _responseHandler.reset(); + + _runEvent.signal(); } void ServerContextImpl::destroyAllTransports() @@ -449,7 +324,7 @@ void ServerContextImpl::destroyAllTransports() } -void ServerContextImpl::printInfo() +void ServerContext::printInfo() { printInfo(cout); } @@ -457,24 +332,29 @@ void ServerContextImpl::printInfo() void ServerContextImpl::printInfo(ostream& str) { Lock guard(_mutex); - str << "VERSION : " << getVersion().getVersionString() << endl \ - << "PROVIDER_NAMES : " << _channelProviderNames << endl \ - << "BEACON_ADDR_LIST : " << _beaconAddressList << endl \ - << "AUTO_BEACON_ADDR_LIST : " << _autoBeaconAddressList << endl \ - << "BEACON_PERIOD : " << _beaconPeriod << endl \ - << "BROADCAST_PORT : " << _broadcastPort << endl \ - << "SERVER_PORT : " << _serverPort << endl \ - << "RCV_BUFFER_SIZE : " << _receiveBufferSize << endl \ - << "IGNORE_ADDR_LIST: " << _ignoreAddressList << endl \ - << "INTF_ADDR_LIST : " << inetAddressToString(_ifaceAddr, false) << endl \ - << "STATE : " << ServerContextImpl::StateNames[_state] << endl; + str << "VERSION : " << getVersion().getVersionString() << endl + << "PROVIDER_NAMES : "; + for(std::vector::const_iterator it = _channelProviders.begin(); + it != _channelProviders.end(); ++it) + { + str<<(*it)->getProviderName()<<", "; + } + str << endl + << "BEACON_ADDR_LIST : " << _beaconAddressList << endl + << "AUTO_BEACON_ADDR_LIST : " << _autoBeaconAddressList << endl + << "BEACON_PERIOD : " << _beaconPeriod << endl + << "BROADCAST_PORT : " << _broadcastPort << endl + << "SERVER_PORT : " << _serverPort << endl + << "RCV_BUFFER_SIZE : " << _receiveBufferSize << endl + << "IGNORE_ADDR_LIST: " << _ignoreAddressList << endl + << "INTF_ADDR_LIST : " << inetAddressToString(_ifaceAddr, false) << endl; } -void ServerContextImpl::dispose() +void ServerContext::dispose() { try { - destroy(); + shutdown(); } catch(std::exception& e) { @@ -491,18 +371,6 @@ void ServerContextImpl::setBeaconServerStatusProvider(BeaconServerStatusProvider _beaconServerStatusProvider = beaconServerStatusProvider; } -bool ServerContextImpl::isInitialized() -{ - Lock guard(_mutex); - return _state == INITIALIZED || _state == RUNNING || _state == SHUTDOWN; -} - -bool ServerContextImpl::isDestroyed() -{ - Lock guard(_mutex); - return _state == DESTROYED; -} - std::string ServerContextImpl::getBeaconAddressList() { return _beaconAddressList; @@ -557,24 +425,6 @@ BlockingUDPTransport::shared_pointer ServerContextImpl::getBroadcastTransport() return _broadcastTransport; } -ChannelProviderRegistry::shared_pointer ServerContextImpl::getChannelProviderRegistry() -{ - return _channelProviderRegistry; -} - -std::string ServerContextImpl::getChannelProviderName() -{ - return _channelProviderNames; -} - -// NOTE: not synced -void ServerContextImpl::setChannelProviderName(std::string channelProviderName) -{ - if (_state != NOT_INITIALIZED) - throw std::logic_error("must be called before initialize"); - _channelProviderNames = channelProviderName; -} - std::vector& ServerContextImpl::getChannelProviders() { return _channelProviders; @@ -620,60 +470,69 @@ std::map >& ServerContextImpl: -struct ThreadRunnerParam { - ServerContextImpl::shared_pointer ctx; - int timeToRun; -}; - -static void threadRunner(void* usr) -{ - ThreadRunnerParam* pusr = static_cast(usr); - ThreadRunnerParam param = *pusr; - delete pusr; - - param.ctx->run(param.timeToRun); -} - - - ServerContext::shared_pointer startPVAServer(std::string const & providerNames, int timeToRun, bool runInSeparateThread, bool printInfo) { - ServerContextImpl::shared_pointer ctx = ServerContextImpl::create(); + ServerContext::shared_pointer ret(ServerContext::create(ServerContext::Config() + .config(ConfigurationBuilder() + .add("EPICS_PVAS_PROVIDER_NAMES", providerNames) + .push_map() + .push_env() + .build()))); + if(printInfo) + ret->printInfo(); - // do not override configuration - if (!ctx->isChannelProviderNamePreconfigured()) - ctx->setChannelProviderName(providerNames); - - ChannelProviderRegistry::shared_pointer channelProviderRegistry = getChannelProviderRegistry(); - ctx->initialize(channelProviderRegistry); - - if (printInfo) - ctx->printInfo(); - - - if (runInSeparateThread) - { - // delete left to the thread (which doesn't) - auto_ptr param(new ThreadRunnerParam()); - param->ctx = ctx; - param->timeToRun = timeToRun; - - // TODO can this fail? - epicsThreadCreate("startPVAServer", - epicsThreadPriorityMedium, - epicsThreadGetStackSize(epicsThreadStackBig), - threadRunner, param.get()); - - param.release(); - // leak... - } - else - { - ctx->run(timeToRun); + if(!runInSeparateThread) { + ret->run(timeToRun); + ret->shutdown(); + } else if(timeToRun!=0) { + LOG(logLevelWarn, "startPVAServer() timeToRun!=0 only supported when runInSeparateThread==false\n"); } - return ctx; + return ret; } +namespace { +struct shutdown_dtor { + ServerContextImpl::shared_pointer wrapped; + shutdown_dtor(const ServerContextImpl::shared_pointer& wrapped) :wrapped(wrapped) {} + void operator()(ServerContext* self) { + wrapped->shutdown(); + if(!wrapped.unique()) + LOG(logLevelWarn, "ServerContextImpl::shutdown() doesn't break all internal ref. loops. use_count=%u\n", (unsigned)wrapped.use_count()); + wrapped.reset(); + } +}; } + +ServerContext::shared_pointer ServerContext::create(const Config &conf) +{ + ServerContextImpl::shared_pointer ret(new ServerContextImpl()); + ret->configuration = conf._conf; + ret->_channelProviders = conf._providers; + + if (!ret->configuration) + { + ConfigurationProvider::shared_pointer configurationProvider = ConfigurationFactory::getProvider(); + ret->configuration = configurationProvider->getConfiguration("pvAccess-server"); + if (!ret->configuration) + { + ret->configuration = configurationProvider->getConfiguration("system"); + } + } + if(!ret->configuration) { + ret->configuration = ConfigurationBuilder().push_env().build(); + } + + ret->loadConfiguration(); + ret->initialize(); + + // wrap the returned shared_ptr so that it's dtor calls ->shutdown() to break internal referance loops + { + ServerContextImpl::shared_pointer wrapper(ret.get(), shutdown_dtor(ret)); + wrapper.swap(ret); + } + + return ret; } + +}} diff --git a/testApp/remote/Makefile b/testApp/remote/Makefile index 83c6f4c..9784d3c 100644 --- a/testApp/remote/Makefile +++ b/testApp/remote/Makefile @@ -21,7 +21,7 @@ testChannelConnect_SRCS += testChannelConnect.cpp TESTPROD_HOST += testServerContext testServerContext_SRCS += testServerContext.cpp - +TESTS += testServerContext PROD_HOST += testServer diff --git a/testApp/remote/channelAccessIFTest.cpp b/testApp/remote/channelAccessIFTest.cpp index 58919f2..e35d731 100644 --- a/testApp/remote/channelAccessIFTest.cpp +++ b/testApp/remote/channelAccessIFTest.cpp @@ -76,13 +76,14 @@ int ChannelAccessIFTest::runAllTest() { .build()); TestServer::shared_pointer tstserv(new TestServer(base_config)); - tstserv->start(); - testDiag("TestServer on ports TCP=%u UDP=%u\n", + + testDiag("TestServer on ports TCP=%u UDP=%u", tstserv->getServerPort(), tstserv->getBroadcastPort()); ConfigurationFactory::registerConfiguration("pvAccess-client", ConfigurationBuilder() .push_config(base_config) + //.add("EPICS_PVA_DEBUG", "3") .add("EPICS_PVA_BROADCAST_PORT", tstserv->getBroadcastPort()) .push_map() .build()); @@ -352,6 +353,7 @@ void ChannelAccessIFTest::test_createChannel() { TR1::shared_ptr channelReq(new SyncChannelRequesterImpl()); Channel::shared_pointer channel = getChannelProvider()->createChannel(TEST_COUNTER_CHANNEL_NAME, channelReq); + testDiag("Channel to '%s', wait for connect", TEST_COUNTER_CHANNEL_NAME.c_str()); bool succStatus = channelReq->waitUntilStateChange(getTimeoutSec()); if (!succStatus) { std::cerr << "[" << TEST_COUNTER_CHANNEL_NAME << "] failed to connect. " << std::endl; diff --git a/testApp/remote/rpcServiceExample.cpp b/testApp/remote/rpcServiceExample.cpp index a62c4bf..5dab449 100644 --- a/testApp/remote/rpcServiceExample.cpp +++ b/testApp/remote/rpcServiceExample.cpp @@ -53,7 +53,7 @@ class SumServiceImpl : // create return structure and set data PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure); - result->getSubField("c")->put(a+b); + result->getSubFieldT("c")->put(a+b); return result; } }; diff --git a/testApp/remote/syncTestRequesters.h b/testApp/remote/syncTestRequesters.h index 8bb9a23..0781cea 100644 --- a/testApp/remote/syncTestRequesters.h +++ b/testApp/remote/syncTestRequesters.h @@ -19,11 +19,10 @@ public: bool waitUntilGetDone(double timeOut) { - bool signaled = waitUntilEvent(timeOut); - if (!signaled) + if (!waitUntilEvent(timeOut)) return false; - Lock lock(m_getStatusMutex); + Lock lock(m_lock); return m_getStatus; } @@ -31,143 +30,123 @@ public: bool waitUntilConnected(double timeOut) { - bool signaled = waitUntilEvent(timeOut); - if (!signaled) + if (!waitUntilEvent(timeOut)) return false; - Lock lock(m_connectedStatusMutex); + Lock lock(m_lock); return m_connectedStatus; } - virtual ~SyncBaseRequester() {} ; + virtual ~SyncBaseRequester() {} protected: - const bool m_debug; - - SyncBaseRequester(bool debug = false): - m_debug(debug), - m_event(new Event()), - m_connectedStatus(false), - m_getStatus(false), - m_putStatus(false) {} + SyncBaseRequester(bool debug = false) + :m_event() + ,m_connectedStatus(false) + ,m_getStatus(false) + ,m_putStatus(false) + ,m_processStatus(false) + {} bool waitUntilPutDone(double timeOut) { - - bool signaled = waitUntilEvent(timeOut); - if (!signaled) + if (!waitUntilEvent(timeOut)) return false; - Lock lock(m_putStatusMutex); + Lock lock(m_lock); return m_putStatus; } bool waitUntilProcessDone(double timeOut) { - - bool signaled = waitUntilEvent(timeOut); - if (!signaled) + if (!waitUntilEvent(timeOut)) return false; - Lock lock(m_processStatusMutex); + Lock lock(m_lock); return m_processStatus; } void setConnectedStatus(bool status) { - Lock lock(m_connectedStatusMutex); + Lock lock(m_lock); m_connectedStatus = status; } bool getConnectedStatus() { - Lock lock(m_connectedStatusMutex); + Lock lock(m_lock); return m_connectedStatus; } void setGetStatus(bool status) { - Lock lock(m_getStatusMutex); + Lock lock(m_lock); m_getStatus = status; } bool getGetStatus() { - Lock lock(m_getStatusMutex); + Lock lock(m_lock); return m_getStatus; } void setPutStatus(bool status) { - Lock lock(m_putStatusMutex); + Lock lock(m_lock); m_putStatus = status; } bool getPutStatus() { - Lock lock(m_putStatusMutex); + Lock lock(m_lock); return m_putStatus; } void setProcessStatus(bool status) { - Lock lock(m_processStatusMutex); + Lock lock(m_lock); m_processStatus = status; } bool getProcessStatus() { - Lock lock(m_processStatusMutex); + Lock lock(m_lock); return m_processStatus; } void resetEvent() { - Lock lock(m_eventMutex); - m_event.reset(new Event()); + m_event.tryWait(); } void signalEvent() { - Lock lock(m_eventMutex); - m_event->signal(); + m_event.signal(); } + // return true if event occurs, false on timeout bool waitUntilEvent(double timeOut) { - std::tr1::shared_ptr event; - { - Lock lock(m_eventMutex); - event = m_event; - } - - bool signaled = event->wait(timeOut); + bool signaled = m_event.wait(timeOut); if (!signaled) { - if (m_debug) - std::cerr << "wait until event timeout" << std::endl; - - return false; + std::cout << "# waited until event timeout" << std::endl; } - return true; + return signaled; } private: - std::tr1::shared_ptr m_event; + epics::pvData::Event m_event; bool m_connectedStatus; bool m_getStatus; bool m_putStatus; bool m_processStatus; - Mutex m_connectedStatusMutex; - Mutex m_getStatusMutex; - Mutex m_putStatusMutex; - Mutex m_processStatusMutex; - Mutex m_eventMutex; + Mutex m_lock; }; @@ -218,8 +197,7 @@ public: const epics::pvData::Status& status, epics::pvAccess::Channel::shared_pointer const & channel) { - if (m_debug) - std::cout << getRequesterName() << "." << "channelCreated(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "channelCreated(" << status << ")" << std::endl; Lock lock(m_pointerMutex); m_status = status; @@ -230,8 +208,7 @@ public: } else { - if (m_debug) - std::cerr << "[" << channel->getChannelName() << "] failed to create a channel: " << std::endl; + std::cerr << "#" << "[" << channel->getChannelName() << "] failed to create a channel: " << std::endl; } } @@ -241,8 +218,7 @@ public: epics::pvAccess::Channel::ConnectionState connectionState) { - if (m_debug) - std::cout << getRequesterName() << "." << "channelStateChange:" << connectionState << std::endl; + std::cout << "#" << getRequesterName() << "." << "channelStateChange:" << connectionState << std::endl; { Lock lock(m_pointerMutex); @@ -288,8 +264,7 @@ public: virtual void channelFindResult(const epics::pvData::Status& status, const epics::pvAccess::ChannelFind::shared_pointer&, bool wasFound) { - if (m_debug) - std::cout << "channelFindResult(" << status << ")" << std::endl; + std::cout << "#" << "channelFindResult(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -355,8 +330,7 @@ public: virtual void message(string const & message, MessageType messageType) { - if (m_debug) - std::cerr << "[" + std::cerr << "# [" << getRequesterName() << "] message(" << message << ", " @@ -370,8 +344,7 @@ public: const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet, epics::pvData::Structure::const_shared_pointer const & /*structure*/) { - if (m_debug) - std::cout << getRequesterName() << "." << "channelGetConnect(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "channelGetConnect(" << status << ")" << std::endl; if (status.isSuccess()) { @@ -393,8 +366,7 @@ public: epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet) { - if (m_debug) - std::cout << getRequesterName() << "." << "getDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "getDone(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -484,8 +456,7 @@ public: virtual void message(string const & message,MessageType messageType) { - if (m_debug) - std::cout << "[" << getRequesterName() << "] message(" << message << ", " + std::cout << "#" << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } @@ -495,8 +466,7 @@ public: epics::pvData::Structure::const_shared_pointer const & /*structure*/) { - if (m_debug) - std::cout << getRequesterName() << "." << "channelPutConnect(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "channelPutConnect(" << status << ")" << std::endl; if (status.isSuccess()) { @@ -521,8 +491,7 @@ public: epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet) { - if (m_debug) - std::cout << getRequesterName() << "." << "getDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "getDone(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -539,8 +508,7 @@ public: virtual void putDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const & channelPut) { - if (m_debug) - std::cout << getRequesterName() << "." << "putDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "putDone(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -586,16 +554,14 @@ public: virtual void message(string const & message,MessageType /*messageType*/) { - if (m_debug) - std::cout << "[" << getRequesterName() << "] message(" << message << endl; + std::cout << "# [" << getRequesterName() << "] message(" << message << endl; } virtual void getDone(const epics::pvData::Status& status,epics::pvData::FieldConstPtr const & field) { - if (m_debug) - std::cout << getRequesterName() << "." << "getDone(" << status << endl; + std::cout << "#" << getRequesterName() << "." << "getDone(" << status << endl; if (status.isSuccess() && field) { @@ -655,8 +621,7 @@ public: virtual void message(string const & message,MessageType /*messageType*/) { - if (m_debug) - std::cout << "[" << getRequesterName() << "] message(" << message << std::endl; + std::cout << "# [" << getRequesterName() << "] message(" << message << std::endl; } @@ -664,8 +629,7 @@ public: ChannelProcess::shared_pointer const & channelProcess) { - if (m_debug) - std::cout << getRequesterName() << "." << "channelProcessConnect(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "channelProcessConnect(" << status << ")" << std::endl; if (status.isSuccess()) { @@ -687,8 +651,7 @@ public: virtual void processDone(const epics::pvData::Status& status, ChannelProcess::shared_pointer const & channelProcess) { - if (m_debug) - std::cout << getRequesterName() << "." << "processDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "processDone(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -799,8 +762,7 @@ public: virtual void message(string const & message,MessageType messageType) { - if (m_debug) - std::cout << "[" << getRequesterName() << "] message(" << + std::cout << "# [" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } @@ -810,8 +772,7 @@ public: epics::pvData::Structure::const_shared_pointer const & /*putStructure*/, epics::pvData::Structure::const_shared_pointer const & /*getStructure*/) { - if (m_debug) - std::cout << getRequesterName() << "." << "channelGetPutConnect(" + std::cout << "#" << getRequesterName() << "." << "channelGetPutConnect(" << status << ")" << std::endl; if (status.isSuccess()) @@ -838,8 +799,7 @@ public: epics::pvData::PVStructure::shared_pointer const & getData, epics::pvData::BitSet::shared_pointer const & getBitSet) { - if (m_debug) - std::cout << getRequesterName() << "." << "getGetDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "getGetDone(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -860,8 +820,7 @@ public: epics::pvData::PVStructure::shared_pointer const & putData, epics::pvData::BitSet::shared_pointer const & putBitSet) { - if (m_debug) - std::cout << getRequesterName() << "." << "getPutDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "getPutDone(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -882,8 +841,7 @@ public: epics::pvData::PVStructure::shared_pointer const & getData, epics::pvData::BitSet::shared_pointer const & getBitSet) { - if (m_debug) - std::cout << getRequesterName() << "." << "putGetDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "putGetDone(" << status << ")" << std::endl; { Lock lock(m_pointerMutex); @@ -997,8 +955,7 @@ public: virtual void message(string const & message, MessageType messageType) { - if (m_debug) - std::cerr << "[" << getRequesterName() << "] message(" << message << ", " + std::cerr << "# [" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } @@ -1007,8 +964,7 @@ public: ChannelRPC::shared_pointer const & channelRPC) { - if (m_debug) - std::cout << getRequesterName() << "." << "channelRPCConnect(" + std::cout << "#" << getRequesterName() << "." << "channelRPCConnect(" << status << ")" << std::endl; if (status.isSuccess()) @@ -1034,8 +990,7 @@ public: epics::pvData::PVStructure::shared_pointer const &pvResponse) { - if (m_debug) - std::cout << getRequesterName() << "." << "requestDone(" + std::cout << "#" << getRequesterName() << "." << "requestDone(" << status << ")" << std::endl; { @@ -1126,8 +1081,7 @@ public: bool signaled = waitUntilEvent(timeOut); if (!signaled) { - if (m_debug) - std::cerr << getRequesterName() << ".waitUntilMonitor:" << " timeout occurred" << endl; + std::cerr << "#" << getRequesterName() << ".waitUntilMonitor:" << " timeout occurred" << endl; return false; } @@ -1152,8 +1106,7 @@ public: bool signaled = waitUntilEvent(timeOut); if (!signaled) { - if (m_debug) - std::cerr << getRequesterName() << ".waitUntilMonitor:" << " timeout occurred" << endl; + std::cerr << "#" << getRequesterName() << ".waitUntilMonitor:" << " timeout occurred" << endl; return false; } @@ -1170,8 +1123,7 @@ public: virtual void message(string const & message, MessageType messageType) { - if (m_debug) - std::cerr << "[" << getRequesterName() << "] message(" << message << ", " + std::cerr << "# [" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } @@ -1179,8 +1131,7 @@ public: virtual void monitorConnect(const epics::pvData::Status& status, Monitor::shared_pointer const & monitor, StructureConstPtr const & /*structure*/) { - if (m_debug) - std::cout << getRequesterName() << "." << "monitorConnect(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << "." << "monitorConnect(" << status << ")" << std::endl; if (status.isSuccess()) { @@ -1202,8 +1153,7 @@ public: virtual void monitorEvent(MonitorPtr const & monitor) { - if (m_debug) - std::cout << getRequesterName() << "." << "monitorEvent" << std::endl; + std::cout << "#" << getRequesterName() << "." << "monitorEvent" << std::endl; MonitorElement::shared_pointer element = monitor->poll(); @@ -1223,8 +1173,7 @@ public: virtual void unlisten(MonitorPtr const & /*monitor*/) { - if (m_debug) - std::cout << getRequesterName() << "." << "unlisten" << std::endl; + std::cout << "#" << getRequesterName() << "." << "unlisten" << std::endl; } @@ -1337,8 +1286,7 @@ public: virtual void message(std::string const & message,MessageType messageType) { - if (m_debug) - std::cout << "[" << getRequesterName() << "] message(" << message << ", " + std::cout << "# [" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl; } @@ -1347,8 +1295,7 @@ public: ChannelArray::shared_pointer const & channelArray, epics::pvData::Array::const_shared_pointer const & /*array*/) { - if (m_debug) - std::cout << getRequesterName() << ".channelArrayConnect(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << ".channelArrayConnect(" << status << ")" << std::endl; if (status.isSuccess()) { { @@ -1371,8 +1318,7 @@ public: ChannelArray::shared_pointer const & channelArray, epics::pvData::PVArray::shared_pointer const & pvArray) { - if (m_debug) - std::cout << getRequesterName() << ".getArrayDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << ".getArrayDone(" << status << ")" << std::endl; Lock lock(m_pointerMutex); @@ -1387,8 +1333,7 @@ public: virtual void putArrayDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray) { - if (m_debug) - std::cout << getRequesterName() << ".putArrayDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << ".putArrayDone(" << status << ")" << std::endl; Lock lock(m_pointerMutex); @@ -1402,8 +1347,7 @@ public: virtual void setLengthDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray) { - if (m_debug) - std::cout << getRequesterName() << ".setLengthDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << ".setLengthDone(" << status << ")" << std::endl; Lock lock(m_pointerMutex); @@ -1417,8 +1361,7 @@ public: ChannelArray::shared_pointer const & channelArray, size_t length) { - if (m_debug) - std::cout << getRequesterName() << ".getLengthDone(" << status << ")" << std::endl; + std::cout << "#" << getRequesterName() << ".getLengthDone(" << status << ")" << std::endl; Lock lock(m_pointerMutex); diff --git a/testApp/remote/testServer.cpp b/testApp/remote/testServer.cpp index c191bda..ab46846 100644 --- a/testApp/remote/testServer.cpp +++ b/testApp/remote/testServer.cpp @@ -9,7 +9,7 @@ // disable buggy boost enable_shared_from_this assert code #define BOOST_DISABLE_ASSERTS -#include +#include #include #include #include @@ -2755,73 +2755,26 @@ private: string MockServerChannelProvider::PROVIDER_NAME = "local"; -class MockChannelProviderFactory : public ChannelProviderFactory -{ -public: - POINTER_DEFINITIONS(MockChannelProviderFactory); - - virtual std::string getFactoryName() - { - return MockServerChannelProvider::PROVIDER_NAME; - } - - virtual ChannelProvider::shared_pointer sharedInstance() - { - // no shared instance support for mock... - return newInstance(); - } - - virtual ChannelProvider::shared_pointer newInstance() - { - MockServerChannelProvider::shared_pointer channelProvider(new MockServerChannelProvider()); - channelProvider->initialize(); - return channelProvider; - } - -}; - -struct TestServer : public Runnable +struct TestServer { POINTER_DEFINITIONS(TestServer); static TestServer::shared_pointer ctx; - epics::pvAccess::Configuration::shared_pointer conf; - ServerContextImpl::shared_pointer context; - Event startup; - epics::pvData::Thread runner; - MockChannelProviderFactory::shared_pointer factory; + ServerContext::shared_pointer context; TestServer(const epics::pvAccess::Configuration::shared_pointer& conf) - :conf(conf) - ,runner(epics::pvData::Thread::Config(this).name("TestServer").autostart(false)) - ,factory(new MockChannelProviderFactory()) { - registerChannelProviderFactory(factory); - - context = ServerContextImpl::create(conf); - context->initialize(getChannelProviderRegistry()); - } - void start(bool inSameThread = false) - { - if (inSameThread) - { - context->run(conf->getPropertyAsInteger("timeToRun", 0)); // default is no timeout - } - else - { - runner.start(); - startup.wait(); // wait for thread to start - } + ChannelProvider::shared_pointer prov(new MockServerChannelProvider); + static_cast(prov.get())->initialize(); + context = ServerContext::create(ServerContext::Config() + .config(conf) + .provider(prov)); } ~TestServer() { context->shutdown(); - runner.exitWait(); - context->destroy(); - - unregisterChannelProviderFactory(factory); structureChangedListeners.clear(); { @@ -2830,9 +2783,6 @@ struct TestServer : public Runnable } ctx.reset(); - unregisterChannelProviderFactory(factory); - - shutdownSimADCs(); } // Use with EPICS_PVA_SERVER_PORT==0 for dynamic port (unit-tests) @@ -2844,11 +2794,7 @@ struct TestServer : public Runnable { return context->getBroadcastPort(); } - virtual void run() - { - startup.signal(); - context->run(conf->getPropertyAsInteger("timeToRun", 0)); // default is no timeout - } + void waitForShutdown() { context->shutdown(); } @@ -2932,7 +2878,7 @@ int main(int argc, char *argv[]) .build())); TestServer::ctx = srv; srv->context->printInfo(); - srv->start(true); + srv->context->run(epics::pvData::castUnsafe(timeToRun)); cout << "Done" << endl; diff --git a/testApp/remote/testServerContext.cpp b/testApp/remote/testServerContext.cpp index 24332ed..786c87a 100644 --- a/testApp/remote/testServerContext.cpp +++ b/testApp/remote/testServerContext.cpp @@ -2,8 +2,11 @@ * testServerContext.cpp */ -#include +#include #include +#include + +#include using namespace epics::pvAccess; using namespace epics::pvData; @@ -17,7 +20,7 @@ public: return "local"; }; - TestChannelProvider(const std::tr1::shared_ptr&) {} + TestChannelProvider() {} ChannelFind::shared_pointer channelFind(std::string const & /*channelName*/, ChannelFindRequester::shared_pointer const & channelFindRequester) @@ -60,25 +63,27 @@ public: void testServerContext() { - ServerContextImpl::shared_pointer ctx = ServerContextImpl::create(); + ChannelProvider::shared_pointer prov(new TestChannelProvider); + ServerContext::shared_pointer ctx(ServerContext::create(ServerContext::Config() + .provider(prov))); + ServerContext::weak_pointer wctx(ctx); - ChannelProviderRegistry::shared_pointer ca(ChannelProviderRegistry::build()); - ca->add("local"); - ctx->initialize(ca); + testOk(ctx.unique(), "# ServerContext::create() returned non-unique instance use_count=%u", (unsigned)ctx.use_count()); ctx->printInfo(); ctx->run(1); - ctx->destroy(); + ctx.reset(); + + testOk(!wctx.lock(), "# ServerContext cleanup leaves use_count=%u", (unsigned)wctx.use_count()); } -int main() +MAIN(testServerContext) { + testPlan(0); + testServerContext(); - cout << "Done" << endl; - - //epicsExitCallAtExits(); - return (0); + return testDone(); }