diff options
Diffstat (limited to 'cpp/src/Ice/Instance.cpp')
-rw-r--r-- | cpp/src/Ice/Instance.cpp | 1431 |
1 files changed, 1431 insertions, 0 deletions
diff --git a/cpp/src/Ice/Instance.cpp b/cpp/src/Ice/Instance.cpp new file mode 100644 index 00000000000..220da4c0d25 --- /dev/null +++ b/cpp/src/Ice/Instance.cpp @@ -0,0 +1,1431 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <IceUtil/DisableWarnings.h> +#include <Ice/Instance.h> +#include <Ice/TraceLevels.h> +#include <Ice/DefaultsAndOverrides.h> +#include <Ice/RouterInfo.h> +#include <Ice/Router.h> +#include <Ice/LocatorInfo.h> +#include <Ice/Locator.h> +#include <Ice/ReferenceFactory.h> +#include <Ice/ProxyFactory.h> +#include <Ice/ThreadPool.h> +#include <Ice/ConnectionFactory.h> +#include <Ice/ConnectionMonitor.h> +#include <Ice/ObjectFactoryManager.h> +#include <Ice/LocalException.h> +#include <Ice/ObjectAdapterFactory.h> +#include <Ice/Exception.h> +#include <Ice/PropertiesI.h> +#include <Ice/LoggerI.h> +#include <Ice/Network.h> +#include <Ice/EndpointFactoryManager.h> +#include <Ice/RetryQueue.h> +#include <Ice/TcpEndpointI.h> +#include <Ice/UdpEndpointI.h> +#include <Ice/DynamicLibrary.h> +#include <Ice/PluginManagerI.h> +#include <Ice/Initialize.h> +#include <Ice/LoggerUtil.h> +#include <IceUtil/StringUtil.h> +#include <Ice/PropertiesI.h> +#include <IceUtil/UUID.h> +#include <Ice/Communicator.h> +#include <IceUtil/Mutex.h> +#include <IceUtil/MutexPtrLock.h> + +#include <stdio.h> + +#ifndef _WIN32 +# include <Ice/SysLoggerI.h> + +# include <signal.h> +# include <syslog.h> +# include <pwd.h> +# include <sys/types.h> +#endif + +using namespace std; +using namespace Ice; +using namespace IceInternal; + +namespace IceUtilInternal +{ + +extern bool ICE_DECLSPEC_IMPORT nullHandleAbort; +extern bool ICE_DECLSPEC_IMPORT printStackTraces; + +}; + +namespace +{ + +IceUtil::Mutex* staticMutex = 0; +bool oneOffDone = false; +int instanceCount = 0; +#ifndef _WIN32 +struct sigaction oldAction; +#endif +bool printProcessIdDone = false; +string identForOpenlog; + +class Init +{ +public: + + Init() + { + staticMutex = new IceUtil::Mutex; + } + + ~Init() + { + delete staticMutex; + staticMutex = 0; + } +}; + +Init init; + +} + +IceUtil::Shared* IceInternal::upCast(Instance* p) { return p; } + +bool +IceInternal::Instance::destroyed() const +{ + IceUtil::RecMutex::Lock sync(*this); + return _state == StateDestroyed; +} + +TraceLevelsPtr +IceInternal::Instance::traceLevels() const +{ + // No mutex lock, immutable. + assert(_traceLevels); + return _traceLevels; +} + +DefaultsAndOverridesPtr +IceInternal::Instance::defaultsAndOverrides() const +{ + // No mutex lock, immutable. + assert(_defaultsAndOverrides); + return _defaultsAndOverrides; +} + +RouterManagerPtr +IceInternal::Instance::routerManager() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_routerManager); + return _routerManager; +} + +LocatorManagerPtr +IceInternal::Instance::locatorManager() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_locatorManager); + return _locatorManager; +} + +ReferenceFactoryPtr +IceInternal::Instance::referenceFactory() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_referenceFactory); + return _referenceFactory; +} + +ProxyFactoryPtr +IceInternal::Instance::proxyFactory() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_proxyFactory); + return _proxyFactory; +} + +OutgoingConnectionFactoryPtr +IceInternal::Instance::outgoingConnectionFactory() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_outgoingConnectionFactory); + return _outgoingConnectionFactory; +} + +ConnectionMonitorPtr +IceInternal::Instance::connectionMonitor() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_connectionMonitor); + return _connectionMonitor; +} + +ObjectFactoryManagerPtr +IceInternal::Instance::servantFactoryManager() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_servantFactoryManager); + return _servantFactoryManager; +} + +ObjectAdapterFactoryPtr +IceInternal::Instance::objectAdapterFactory() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_objectAdapterFactory); + return _objectAdapterFactory; +} + +ProtocolSupport +IceInternal::Instance::protocolSupport() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + return _protocolSupport; +} + +ThreadPoolPtr +IceInternal::Instance::clientThreadPool() +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_clientThreadPool); + return _clientThreadPool; +} + +ThreadPoolPtr +IceInternal::Instance::serverThreadPool() +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + if(!_serverThreadPool) // Lazy initialization. + { + int timeout = _initData.properties->getPropertyAsInt("Ice.ServerIdleTime"); + _serverThreadPool = new ThreadPool(this, "Ice.ThreadPool.Server", timeout); + } + + return _serverThreadPool; +} + +EndpointHostResolverPtr +IceInternal::Instance::endpointHostResolver() +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_endpointHostResolver); + return _endpointHostResolver; +} + +RetryQueuePtr +IceInternal::Instance::retryQueue() +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_retryQueue); + return _retryQueue; +} + +IceUtil::TimerPtr +IceInternal::Instance::timer() +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + assert(_timer); + return _timer; +} + +EndpointFactoryManagerPtr +IceInternal::Instance::endpointFactoryManager() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_endpointFactoryManager); + return _endpointFactoryManager; +} + +DynamicLibraryListPtr +IceInternal::Instance::dynamicLibraryList() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_dynamicLibraryList); + return _dynamicLibraryList; +} + +PluginManagerPtr +IceInternal::Instance::pluginManager() const +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + assert(_pluginManager); + return _pluginManager; +} + +int +IceInternal::Instance::clientACM() const +{ + // No mutex lock, immutable. + return _clientACM; +} + +int +IceInternal::Instance::serverACM() const +{ + // No mutex lock, immutable. + return _serverACM; +} + +Identity +IceInternal::Instance::stringToIdentity(const string& s) const +{ + // + // This method only accepts printable ascii. Since printable ascii is a subset + // of all narrow string encodings, it is not necessary to convert the string + // from the native string encoding. Any characters other than printable-ASCII + // will cause an IllegalArgumentException. Note that it can contain Unicode + // encoded in the escaped form which is the reason why we call fromUTF8 after + // unespcaping the printable ASCII string. + // + + Identity ident; + + // + // Find unescaped separator. + // + string::size_type slash = string::npos, pos = 0; + while((pos = s.find('/', pos)) != string::npos) + { + if(pos == 0 || s[pos - 1] != '\\') + { + if(slash == string::npos) + { + slash = pos; + } + else + { + // + // Extra unescaped slash found. + // + IdentityParseException ex(__FILE__, __LINE__); + ex.str = "unescaped backslash in identity `" + s + "'"; + throw ex; + } + } + pos++; + } + + if(slash == string::npos) + { + try + { + ident.name = IceUtilInternal::unescapeString(s, 0, s.size()); + } + catch(const IceUtil::IllegalArgumentException& e) + { + IdentityParseException ex(__FILE__, __LINE__); + ex.str = "invalid identity name `" + s + "': " + e.reason(); + throw ex; + } + } + else + { + try + { + ident.category = IceUtilInternal::unescapeString(s, 0, slash); + } + catch(const IceUtil::IllegalArgumentException& e) + { + IdentityParseException ex(__FILE__, __LINE__); + ex.str = "invalid category in identity `" + s + "': " + e.reason(); + throw ex; + } + if(slash + 1 < s.size()) + { + try + { + ident.name = IceUtilInternal::unescapeString(s, slash + 1, s.size()); + } + catch(const IceUtil::IllegalArgumentException& e) + { + IdentityParseException ex(__FILE__, __LINE__); + ex.str = "invalid name in identity `" + s + "': " + e.reason(); + throw ex; + } + } + } + + ident.name = Ice::UTF8ToNative(_initData.stringConverter, ident.name); + ident.category = Ice::UTF8ToNative(_initData.stringConverter, ident.category); + + return ident; +} + +string +IceInternal::Instance::identityToString(const Identity& ident) const +{ + // + // This method returns the stringified identity. The returned string only + // contains printable ascii. It can contain UTF8 in the escaped form. + // + string name = Ice::nativeToUTF8(_initData.stringConverter, ident.name); + string category = Ice::nativeToUTF8(_initData.stringConverter, ident.category); + + if(category.empty()) + { + return IceUtilInternal::escapeString(name, "/"); + } + else + { + return IceUtilInternal::escapeString(category, "/") + '/' + IceUtilInternal::escapeString(name, "/"); + } +} + +Ice::ObjectPrx +IceInternal::Instance::getAdmin() +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + const string adminOA = "Ice.Admin"; + + if(_adminAdapter != 0) + { + return _adminAdapter->createProxy(_adminIdentity); + } + else if(_initData.properties->getProperty(adminOA + ".Endpoints") == "") + { + return 0; + } + else + { + string serverId = _initData.properties->getProperty("Ice.Admin.ServerId"); + string instanceName = _initData.properties->getProperty("Ice.Admin.InstanceName"); + + Ice::LocatorPrx defaultLocator = _referenceFactory->getDefaultLocator(); + + if((defaultLocator != 0 && serverId != "") || instanceName != "") + { + if(_adminIdentity.name == "") + { + _adminIdentity.name = "admin"; + if(instanceName == "") + { + instanceName = IceUtil::generateUUID(); + } + _adminIdentity.category = instanceName; + + // + // Afterwards, _adminIdentity is read-only + // + } + + // + // Create OA + // + _adminAdapter = _objectAdapterFactory->createObjectAdapter(adminOA, 0); + + // + // Add all facets to OA + // + FacetMap filteredFacets; + + for(FacetMap::iterator p = _adminFacets.begin(); p != _adminFacets.end(); ++p) + { + if(_adminFacetFilter.empty() || _adminFacetFilter.find(p->first) != _adminFacetFilter.end()) + { + _adminAdapter->addFacet(p->second, _adminIdentity, p->first); + } + else + { + filteredFacets[p->first] = p->second; + } + } + _adminFacets.swap(filteredFacets); + + ObjectAdapterPtr adapter = _adminAdapter; + sync.release(); + + // + // Activate OA + // + try + { + adapter->activate(); + } + catch(...) + { + // + // We cleanup _adminAdapter, however this error is not recoverable + // (can't call again getAdmin() after fixing the problem) + // since all the facets (servants) in the adapter are lost + // + adapter->destroy(); + sync.acquire(); + _adminAdapter = 0; + throw; + } + + Ice::ObjectPrx admin = adapter->createProxy(_adminIdentity); + if(defaultLocator != 0 && serverId != "") + { + ProcessPrx process = ProcessPrx::uncheckedCast(admin->ice_facet("Process")); + try + { + // + // Note that as soon as the process proxy is registered, the communicator might be + // shutdown by a remote client and admin facets might start receiving calls. + // + defaultLocator->getRegistry()->setServerProcessProxy(serverId, process); + } + catch(const ServerNotFoundException&) + { + if(_traceLevels->location >= 1) + { + Trace out(_initData.logger, _traceLevels->locationCat); + out << "couldn't register server `" + serverId + "' with the locator registry:\n"; + out << "the server is not known to the locator registry"; + } + + throw InitializationException(__FILE__, __LINE__, "Locator knows nothing about server '" + + serverId + "'"); + } + catch(const LocalException& ex) + { + if(_traceLevels->location >= 1) + { + Trace out(_initData.logger, _traceLevels->locationCat); + out << "couldn't register server `" + serverId + "' with the locator registry:\n" << ex; + } + throw; + } + } + + if(_traceLevels->location >= 1) + { + Trace out(_initData.logger, _traceLevels->locationCat); + out << "registered server `" + serverId + "' with the locator registry"; + } + + return admin; + } + else + { + return 0; + } + } +} + +void +IceInternal::Instance::addAdminFacet(const Ice::ObjectPtr& servant, const string& facet) +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + if(_adminAdapter == 0 || (!_adminFacetFilter.empty() && _adminFacetFilter.find(facet) == _adminFacetFilter.end())) + { + if(_adminFacets.insert(FacetMap::value_type(facet, servant)).second == false) + { + throw AlreadyRegisteredException(__FILE__, __LINE__, "facet", facet); + } + } + else + { + _adminAdapter->addFacet(servant, _adminIdentity, facet); + } +} + +Ice::ObjectPtr +IceInternal::Instance::removeAdminFacet(const string& facet) +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + ObjectPtr result; + + if(_adminAdapter == 0 || (!_adminFacetFilter.empty() && _adminFacetFilter.find(facet) == _adminFacetFilter.end())) + { + FacetMap::iterator p = _adminFacets.find(facet); + if(p == _adminFacets.end()) + { + throw NotRegisteredException(__FILE__, __LINE__, "facet", facet); + } + else + { + result = p->second; + _adminFacets.erase(p); + } + } + else + { + result = _adminAdapter->removeFacet(_adminIdentity, facet); + } + return result; +} + +void +IceInternal::Instance::setDefaultLocator(const Ice::LocatorPrx& defaultLocator) +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + _referenceFactory = _referenceFactory->setDefaultLocator(defaultLocator); +} + +void +IceInternal::Instance::setDefaultRouter(const Ice::RouterPrx& defaultRouter) +{ + IceUtil::RecMutex::Lock sync(*this); + + if(_state == StateDestroyed) + { + throw CommunicatorDestroyedException(__FILE__, __LINE__); + } + + _referenceFactory = _referenceFactory->setDefaultRouter(defaultRouter); +} + +void +IceInternal::Instance::setStringConverter(const Ice::StringConverterPtr& stringConverter) +{ + // + // No locking, as it can only be called during plug-in loading + // + _initData.stringConverter = stringConverter; +} + +void +IceInternal::Instance::setWstringConverter(const Ice::WstringConverterPtr& wstringConverter) +{ + // + // No locking, as it can only be called during plug-in loading + // + _initData.wstringConverter = wstringConverter; +} + +void +IceInternal::Instance::setLogger(const Ice::LoggerPtr& logger) +{ + // + // No locking, as it can only be called during plug-in loading + // + _initData.logger = logger; +} + +void +IceInternal::Instance::setThreadHook(const Ice::ThreadNotificationPtr& threadHook) +{ + // + // No locking, as it can only be called during plug-in loading + // + _initData.threadHook = threadHook; +} + +IceInternal::Instance::Instance(const CommunicatorPtr& communicator, const InitializationData& initData) : + _state(StateActive), + _initData(initData), + _messageSizeMax(0), + _clientACM(0), + _serverACM(0), + _implicitContext(0) +{ + try + { + __setNoDelete(true); + { + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(staticMutex); + instanceCount++; + + if(!_initData.properties) + { + _initData.properties = createProperties(); + } + + if(!oneOffDone) + { + // + // StdOut and StdErr redirection + // + string stdOutFilename = _initData.properties->getProperty("Ice.StdOut"); + string stdErrFilename = _initData.properties->getProperty("Ice.StdErr"); + + if(stdOutFilename != "") + { +#ifdef _LARGEFILE64_SOURCE + FILE* file = freopen64(stdOutFilename.c_str(), "a", stdout); +#else +#ifdef _WIN32 + FILE* file = _wfreopen(IceUtil::stringToWstring(nativeToUTF8(_initData.stringConverter, + stdOutFilename)).c_str(), + L"a", stdout); +#else + FILE* file = freopen(stdOutFilename.c_str(), "a", stdout); +#endif +#endif + if(file == 0) + { + FileException ex(__FILE__, __LINE__); + ex.path = stdOutFilename; + ex.error = getSystemErrno(); + throw ex; + } + } + + if(stdErrFilename != "") + { +#ifdef _LARGEFILE64_SOURCE + FILE* file = freopen64(stdErrFilename.c_str(), "a", stderr); +#else +#ifdef _WIN32 + FILE* file = _wfreopen(IceUtil::stringToWstring(nativeToUTF8(_initData.stringConverter, + stdErrFilename)).c_str(), + L"a", stderr); +#else + FILE* file = freopen(stdErrFilename.c_str(), "a", stderr); +#endif +#endif + if(file == 0) + { + FileException ex(__FILE__, __LINE__); + ex.path = stdErrFilename; + ex.error = getSystemErrno(); + throw ex; + } + } + + if(_initData.properties->getPropertyAsInt("Ice.NullHandleAbort") > 0) + { + IceUtilInternal::nullHandleAbort = true; + } + +#ifdef NDEBUG + if(_initData.properties->getPropertyAsIntWithDefault("Ice.PrintStackTraces", 0) > 0) +#else + if(_initData.properties->getPropertyAsIntWithDefault("Ice.PrintStackTraces", 1) > 0) +#endif + { + IceUtilInternal::printStackTraces = true; + } + +#ifndef _WIN32 + string newUser = _initData.properties->getProperty("Ice.ChangeUser"); + if(!newUser.empty()) + { + struct passwd* pw = getpwnam(newUser.c_str()); + if(!pw) + { + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } + + if(setgid(pw->pw_gid) == -1) + { + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } + + if(setuid(pw->pw_uid) == -1) + { + SyscallException ex(__FILE__, __LINE__); + ex.error = getSystemErrno(); + throw ex; + } + } +#endif + oneOffDone = true; + } + + if(instanceCount == 1) + { + +#ifdef _WIN32 + WORD version = MAKEWORD(1, 1); + WSADATA data; + if(WSAStartup(version, &data) != 0) + { + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } +#endif + +#ifndef _WIN32 + struct sigaction action; + action.sa_handler = SIG_IGN; + sigemptyset(&action.sa_mask); + action.sa_flags = 0; + sigaction(SIGPIPE, &action, &oldAction); + if(_initData.properties->getPropertyAsInt("Ice.UseSyslog") > 0) + { + identForOpenlog = _initData.properties->getProperty("Ice.ProgramName"); + if(identForOpenlog.empty()) + { + identForOpenlog = "<Unknown Ice Program>"; + } + openlog(identForOpenlog.c_str(), LOG_PID, LOG_USER); + } +#endif + } + } + + + if(!_initData.logger) + { + string logfile = _initData.properties->getProperty("Ice.LogFile"); +#ifndef _WIN32 + if(_initData.properties->getPropertyAsInt("Ice.UseSyslog") > 0) + { + if(!logfile.empty()) + { + throw InitializationException(__FILE__, __LINE__, "Both syslog and file logger cannot be enabled."); + } + + _initData.logger = + new SysLoggerI(_initData.properties->getProperty("Ice.ProgramName"), + _initData.properties->getPropertyWithDefault("Ice.SyslogFacility", "LOG_USER")); + } + else +#endif + if(!logfile.empty()) + { + _initData.logger = new LoggerI(_initData.properties->getProperty("Ice.ProgramName"), + nativeToUTF8(_initData.stringConverter, logfile)); + } + else + { + _initData.logger = getProcessLogger(); + } + } + + const_cast<TraceLevelsPtr&>(_traceLevels) = new TraceLevels(_initData.properties); + + const_cast<DefaultsAndOverridesPtr&>(_defaultsAndOverrides) = new DefaultsAndOverrides(_initData.properties); + + { + static const int defaultMessageSizeMax = 1024; + Int num = _initData.properties->getPropertyAsIntWithDefault("Ice.MessageSizeMax", defaultMessageSizeMax); + if(num < 1) + { + const_cast<size_t&>(_messageSizeMax) = defaultMessageSizeMax * 1024; // Ignore non-sensical values. + } + else if(static_cast<size_t>(num) > (size_t)(0x7fffffff / 1024)) + { + const_cast<size_t&>(_messageSizeMax) = static_cast<size_t>(0x7fffffff); + } + else + { + // Property is in kilobytes, _messageSizeMax in bytes. + const_cast<size_t&>(_messageSizeMax) = static_cast<size_t>(num) * 1024; + } + } + + // + // Client ACM enabled by default. Server ACM disabled by default. + // + const_cast<Int&>(_clientACM) = _initData.properties->getPropertyAsIntWithDefault("Ice.ACM.Client", 60); + const_cast<Int&>(_serverACM) = _initData.properties->getPropertyAsInt("Ice.ACM.Server"); + const_cast<ImplicitContextIPtr&>(_implicitContext) = + ImplicitContextI::create(_initData.properties->getProperty("Ice.ImplicitContext")); + + _routerManager = new RouterManager; + + _locatorManager = new LocatorManager(_initData.properties); + + _referenceFactory = new ReferenceFactory(this, communicator); + + _proxyFactory = new ProxyFactory(this); + + bool ipv4 = _initData.properties->getPropertyAsIntWithDefault("Ice.IPv4", 1) > 0; + bool ipv6 = _initData.properties->getPropertyAsIntWithDefault("Ice.IPv6", 0) > 0; + if(!ipv4 && !ipv6) + { + throw InitializationException(__FILE__, __LINE__, "Both IPV4 and IPv6 support cannot be disabled."); + } + else if(ipv4 && ipv6) + { + _protocolSupport = EnableBoth; + } + else if(ipv4) + { + _protocolSupport = EnableIPv4; + } + else + { + _protocolSupport = EnableIPv6; + } + _endpointFactoryManager = new EndpointFactoryManager(this); + EndpointFactoryPtr tcpEndpointFactory = new TcpEndpointFactory(this); + _endpointFactoryManager->add(tcpEndpointFactory); + EndpointFactoryPtr udpEndpointFactory = new UdpEndpointFactory(this); + _endpointFactoryManager->add(udpEndpointFactory); + + _dynamicLibraryList = new DynamicLibraryList; + + _pluginManager = new PluginManagerI(communicator, _dynamicLibraryList); + + _outgoingConnectionFactory = new OutgoingConnectionFactory(this); + + _servantFactoryManager = new ObjectFactoryManager(); + + _objectAdapterFactory = new ObjectAdapterFactory(this, communicator); + + _retryQueue = new RetryQueue(this); + + + if(_initData.wstringConverter == 0) + { + _initData.wstringConverter = new UnicodeWstringConverter(); + } + + // + // Add Process and Properties facets + // + + StringSeq facetSeq = _initData.properties->getPropertyAsList("Ice.Admin.Facets"); + + if(!facetSeq.empty()) + { + _adminFacetFilter.insert(facetSeq.begin(), facetSeq.end()); + } + + _adminFacets.insert(FacetMap::value_type("Properties", new PropertiesAdminI(_initData.properties))); + _adminFacets.insert(FacetMap::value_type("Process", new ProcessI(communicator))); + + __setNoDelete(false); + } + catch(...) + { + { + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(staticMutex); + --instanceCount; + } + destroy(); + __setNoDelete(false); + throw; + } +} + +IceInternal::Instance::~Instance() +{ + assert(_state == StateDestroyed); + assert(!_referenceFactory); + assert(!_proxyFactory); + assert(!_outgoingConnectionFactory); + + assert(!_connectionMonitor); + assert(!_servantFactoryManager); + assert(!_objectAdapterFactory); + assert(!_clientThreadPool); + assert(!_serverThreadPool); + assert(!_endpointHostResolver); + assert(!_retryQueue); + assert(!_timer); + assert(!_routerManager); + assert(!_locatorManager); + assert(!_endpointFactoryManager); + assert(!_dynamicLibraryList); + assert(!_pluginManager); + + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(staticMutex); + if(--instanceCount == 0) + { +#ifdef _WIN32 + WSACleanup(); +#endif + +#ifndef _WIN32 + sigaction(SIGPIPE, &oldAction, 0); + + if(!identForOpenlog.empty()) + { + closelog(); + identForOpenlog.clear(); + } +#endif + } +} + +void +IceInternal::Instance::finishSetup(int& argc, char* argv[]) +{ + // + // Load plug-ins. + // + assert(!_serverThreadPool); + PluginManagerI* pluginManagerImpl = dynamic_cast<PluginManagerI*>(_pluginManager.get()); + assert(pluginManagerImpl); + pluginManagerImpl->loadPlugins(argc, argv); + + + // + // Create threads. + // + try + { + bool hasPriority = _initData.properties->getProperty("Ice.ThreadPriority") != ""; + int priority = _initData.properties->getPropertyAsInt("Ice.ThreadPriority"); + if(hasPriority) + { + _timer = new IceUtil::Timer(priority); + } + else + { + _timer = new IceUtil::Timer; + } + } + catch(const IceUtil::Exception& ex) + { + Error out(_initData.logger); + out << "cannot create thread for timer:\n" << ex; + throw; + } + + try + { + _endpointHostResolver = new EndpointHostResolver(this); + } + catch(const IceUtil::Exception& ex) + { + Error out(_initData.logger); + out << "cannot create thread for endpoint host resolver:\n" << ex; + throw; + } + + _clientThreadPool = new ThreadPool(this, "Ice.ThreadPool.Client", 0); + + // + // Get default router and locator proxies. Don't move this + // initialization before the plug-in initialization!!! The proxies + // might depend on endpoint factories to be installed by plug-ins. + // + RouterPrx router = RouterPrx::uncheckedCast(_proxyFactory->propertyToProxy("Ice.Default.Router")); + if(router) + { + _referenceFactory = _referenceFactory->setDefaultRouter(router); + } + + LocatorPrx locator = LocatorPrx::uncheckedCast(_proxyFactory->propertyToProxy("Ice.Default.Locator")); + if(locator) + { + _referenceFactory = _referenceFactory->setDefaultLocator(locator); + } + + // + // Show process id if requested (but only once). + // + bool printProcessId = false; + if(!printProcessIdDone && _initData.properties->getPropertyAsInt("Ice.PrintProcessId") > 0) + { + // + // Safe double-check locking (no dependent variable!) + // + IceUtilInternal::MutexPtrLock<IceUtil::Mutex> sync(staticMutex); + printProcessId = !printProcessIdDone; + + // + // We anticipate: we want to print it once, and we don't care when. + // + printProcessIdDone = true; + } + + if(printProcessId) + { +#ifdef _MSC_VER + cout << _getpid() << endl; +#else + cout << getpid() << endl; +#endif + } + + // + // Create the connection monitor and ensure the interval for + // monitoring connections is appropriate for client & server + // ACM. + // + _connectionMonitor = new ConnectionMonitor(this, _initData.properties->getPropertyAsInt("Ice.MonitorConnections")); + _connectionMonitor->checkIntervalForACM(_clientACM); + _connectionMonitor->checkIntervalForACM(_serverACM); + + // + // Server thread pool initialization is lazy in serverThreadPool(). + // + + // + // An application can set Ice.InitPlugins=0 if it wants to postpone + // initialization until after it has interacted directly with the + // plug-ins. + // + if(_initData.properties->getPropertyAsIntWithDefault("Ice.InitPlugins", 1) > 0) + { + pluginManagerImpl->initializePlugins(); + } + + // + // This must be done last as this call creates the Ice.Admin object adapter + // and eventually register a process proxy with the Ice locator (allowing + // remote clients to invoke on Ice.Admin facets as soon as it's registered). + // + if(_initData.properties->getPropertyAsIntWithDefault("Ice.Admin.DelayCreation", 0) <= 0) + { + getAdmin(); + } +} + +bool +IceInternal::Instance::destroy() +{ + { + IceUtil::RecMutex::Lock sync(*this); + + // + // If the _state is not StateActive then the instance is + // either being destroyed, or has already been destroyed. + // + if(_state != StateActive) + { + return false; + } + + // + // We cannot set state to StateDestroyed otherwise instance + // methods called during the destroy process (such as + // outgoingConnectionFactory() from + // ObjectAdapterI::deactivate() will cause an exception. + // + _state = StateDestroyInProgress; + } + + if(_objectAdapterFactory) + { + _objectAdapterFactory->shutdown(); + } + + if(_outgoingConnectionFactory) + { + _outgoingConnectionFactory->destroy(); + } + + if(_objectAdapterFactory) + { + _objectAdapterFactory->destroy(); + } + + if(_outgoingConnectionFactory) + { + _outgoingConnectionFactory->waitUntilFinished(); + } + + if(_retryQueue) + { + _retryQueue->destroy(); + } + + ThreadPoolPtr serverThreadPool; + ThreadPoolPtr clientThreadPool; + EndpointHostResolverPtr endpointHostResolver; + + { + IceUtil::RecMutex::Lock sync(*this); + + _objectAdapterFactory = 0; + _outgoingConnectionFactory = 0; + _retryQueue = 0; + + if(_connectionMonitor) + { + _connectionMonitor->destroy(); + _connectionMonitor = 0; + } + + if(_serverThreadPool) + { + _serverThreadPool->destroy(); + std::swap(_serverThreadPool, serverThreadPool); + } + + if(_clientThreadPool) + { + _clientThreadPool->destroy(); + std::swap(_clientThreadPool, clientThreadPool); + } + + if(_endpointHostResolver) + { + _endpointHostResolver->destroy(); + std::swap(endpointHostResolver, _endpointHostResolver); + } + + if(_timer) + { + _timer->destroy(); + _timer = 0; + } + + if(_servantFactoryManager) + { + _servantFactoryManager->destroy(); + _servantFactoryManager = 0; + } + + //_referenceFactory->destroy(); // No destroy function defined. + _referenceFactory = 0; + + // _proxyFactory->destroy(); // No destroy function defined. + _proxyFactory = 0; + + if(_routerManager) + { + _routerManager->destroy(); + _routerManager = 0; + } + + if(_locatorManager) + { + _locatorManager->destroy(); + _locatorManager = 0; + } + + if(_endpointFactoryManager) + { + _endpointFactoryManager->destroy(); + _endpointFactoryManager = 0; + } + + if(_pluginManager) + { + _pluginManager->destroy(); + _pluginManager = 0; + } + + // No destroy function defined. + // _dynamicLibraryList->destroy(); + _dynamicLibraryList = 0; + + _adminAdapter = 0; + _adminFacets.clear(); + + _state = StateDestroyed; + } + + // + // Join with the thread pool threads outside the synchronization. + // + if(clientThreadPool) + { + clientThreadPool->joinWithAllThreads(); + } + if(serverThreadPool) + { + serverThreadPool->joinWithAllThreads(); + } + if(endpointHostResolver) + { + endpointHostResolver->getThreadControl().join(); + } + + if(_initData.properties->getPropertyAsInt("Ice.Warn.UnusedProperties") > 0) + { + set<string> unusedProperties = static_cast<PropertiesI*>(_initData.properties.get())->getUnusedProperties(); + if(unusedProperties.size() != 0) + { + Warning out(_initData.logger); + out << "The following properties were set but never read:"; + for(set<string>::const_iterator p = unusedProperties.begin(); p != unusedProperties.end(); ++p) + { + out << "\n " << *p; + } + } + } + return true; +} + +IceInternal::UTF8BufferI::UTF8BufferI() : + _buffer(0), + _offset(0) +{ +} + +IceInternal::UTF8BufferI::~UTF8BufferI() +{ + free(_buffer); +} + +Byte* +IceInternal::UTF8BufferI::getMoreBytes(size_t howMany, Byte* firstUnused) +{ + if(_buffer == 0) + { + _buffer = (Byte*)malloc(howMany); + } + else + { + assert(firstUnused != 0); + _offset = firstUnused - _buffer; + _buffer = (Byte*)realloc(_buffer, _offset + howMany); + } + + return _buffer + _offset; +} + +Byte* +IceInternal::UTF8BufferI::getBuffer() +{ + return _buffer; +} + +void +IceInternal::UTF8BufferI::reset() +{ + free(_buffer); + _buffer = 0; + _offset = 0; +} + + +IceInternal::ProcessI::ProcessI(const CommunicatorPtr& communicator) : + _communicator(communicator) +{ +} + +void +IceInternal::ProcessI::shutdown(const Current&) +{ + _communicator->shutdown(); +} + +void +IceInternal::ProcessI::writeMessage(const string& message, Int fd, const Current&) +{ + switch(fd) + { + case 1: + { + cout << message << endl; + break; + } + case 2: + { + cerr << message << endl; + break; + } + } +} |