ServerContext ref. loop breaking and threading
Drop unnecessary "worker" thread which does no work. Ensure that returned shared_ptr is unique()==true. Add ServerContext::create() to start a new server with specific config and/or providers
This commit is contained in:
@@ -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<PipelineChannelProvider> 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<ThreadRunnerParam*>(usr);
|
||||
ThreadRunnerParam param = *pusr;
|
||||
delete pusr;
|
||||
|
||||
param.server->run(param.timeToRun);
|
||||
}
|
||||
|
||||
/// Method requires usage of std::tr1::shared_ptr<PipelineServer>. This instance must be
|
||||
/// owned by a shared_ptr instance.
|
||||
void PipelineServer::runInNewThread(int seconds)
|
||||
{
|
||||
std::auto_ptr<ThreadRunnerParam> 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)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/pipelineService.h>
|
||||
#include <pv/serverContextImpl.h>
|
||||
#include <pv/serverContext.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -36,7 +36,6 @@ class epicsShareClass RPCServer :
|
||||
private:
|
||||
|
||||
std::tr1::shared_ptr<ServerContext> m_serverContext;
|
||||
ChannelProviderFactory::shared_pointer m_channelProviderFactory;
|
||||
ChannelProvider::shared_pointer m_channelProviderImpl;
|
||||
|
||||
// TODO no thread poll implementation
|
||||
|
||||
@@ -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<RPCChannelProvider> 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<ServerContextImpl*>(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)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <pv/pvaConstants.h>
|
||||
#include <pv/pvaVersion.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/configuration.h>
|
||||
|
||||
#include <shareLib.h>
|
||||
|
||||
@@ -26,8 +27,7 @@ namespace pvAccess {
|
||||
class epicsShareClass ServerContext
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerContext> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerContext> const_shared_pointer;
|
||||
POINTER_DEFINITIONS(ServerContext);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
@@ -46,37 +46,22 @@ public:
|
||||
*/
|
||||
virtual const Version& getVersion() = 0;
|
||||
|
||||
/**
|
||||
* Set <code>ChannelProviderRegistry</code> 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 <code>0</code>
|
||||
* the method would block until <code>destroy()</code> 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 <code>destroy()</code> 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<ChannelProvider::shared_pointer> _providers;
|
||||
public:
|
||||
Config() {}
|
||||
Config& config(const Configuration::const_shared_pointer& c) { _conf = c; return *this; }
|
||||
Config& providers(const std::vector<ChannelProvider::shared_pointer>& 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(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef SERVERCONTEXTIMPL_H
|
||||
#define SERVERCONTEXTIMPL_H
|
||||
|
||||
#include <pv/thread.h>
|
||||
#include <pv/blockingUDP.h>
|
||||
#include <pv/blockingTCP.h>
|
||||
#include <pv/beaconEmitter.h>
|
||||
@@ -15,33 +16,27 @@ class epicsShareClass ServerContextImpl :
|
||||
public Context,
|
||||
public std::tr1::enable_shared_from_this<ServerContextImpl>
|
||||
{
|
||||
friend class ServerContext;
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerContextImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerContextImpl> 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<std::string, std::tr1::shared_ptr<SecurityPlugin> >& 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 <code>State</code>
|
||||
*/
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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<ChannelProviderRegistry::stringVector_t> 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<ChannelProviderRegistry::stringVector_t> 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<ChannelProvider::shared_pointer>::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<ChannelProvider::shared_pointer>& ServerContextImpl::getChannelProviders()
|
||||
{
|
||||
return _channelProviders;
|
||||
@@ -620,60 +470,69 @@ std::map<std::string, std::tr1::shared_ptr<SecurityPlugin> >& ServerContextImpl:
|
||||
|
||||
|
||||
|
||||
struct ThreadRunnerParam {
|
||||
ServerContextImpl::shared_pointer ctx;
|
||||
int timeToRun;
|
||||
};
|
||||
|
||||
static void threadRunner(void* usr)
|
||||
{
|
||||
ThreadRunnerParam* pusr = static_cast<ThreadRunnerParam*>(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<ThreadRunnerParam> 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;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -21,7 +21,7 @@ testChannelConnect_SRCS += testChannelConnect.cpp
|
||||
|
||||
TESTPROD_HOST += testServerContext
|
||||
testServerContext_SRCS += testServerContext.cpp
|
||||
|
||||
TESTS += testServerContext
|
||||
|
||||
|
||||
PROD_HOST += testServer
|
||||
|
||||
@@ -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<SyncChannelRequesterImpl> 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;
|
||||
|
||||
@@ -53,7 +53,7 @@ class SumServiceImpl :
|
||||
|
||||
// create return structure and set data
|
||||
PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure);
|
||||
result->getSubField<PVDouble>("c")->put(a+b);
|
||||
result->getSubFieldT<PVDouble>("c")->put(a+b);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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<epics::pvData::Event> 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<epics::pvData::Event> 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);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
// disable buggy boost enable_shared_from_this assert code
|
||||
#define BOOST_DISABLE_ASSERTS
|
||||
|
||||
#include <pv/serverContextImpl.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/clientContextImpl.h>
|
||||
#include <epicsExit.h>
|
||||
#include <pv/standardPVField.h>
|
||||
@@ -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<MockServerChannelProvider*>(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<epicsUInt32>(timeToRun));
|
||||
|
||||
cout << "Done" << endl;
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
* testServerContext.cpp
|
||||
*/
|
||||
|
||||
#include <pv/serverContextImpl.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <epicsExit.h>
|
||||
#include <testMain.h>
|
||||
|
||||
#include <epicsUnitTest.h>
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvData;
|
||||
@@ -17,7 +20,7 @@ public:
|
||||
return "local";
|
||||
};
|
||||
|
||||
TestChannelProvider(const std::tr1::shared_ptr<Configuration>&) {}
|
||||
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<TestChannelProvider>("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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user