diff options
Diffstat (limited to 'cpp/src/IceBox/ServiceManagerI.cpp')
-rw-r--r-- | cpp/src/IceBox/ServiceManagerI.cpp | 189 |
1 files changed, 82 insertions, 107 deletions
diff --git a/cpp/src/IceBox/ServiceManagerI.cpp b/cpp/src/IceBox/ServiceManagerI.cpp index 0a2a5908543..f91e9cd8da2 100644 --- a/cpp/src/IceBox/ServiceManagerI.cpp +++ b/cpp/src/IceBox/ServiceManagerI.cpp @@ -22,47 +22,18 @@ using namespace std; typedef IceBox::Service* (*SERVICE_FACTORY)(CommunicatorPtr); -namespace +namespace { -template<class T> -class AMICallbackT : public T -{ -public: - - AMICallbackT(const ServiceManagerIPtr& serviceManager, const ServiceObserverPrx& observer) : - _serviceManager(serviceManager), - _observer(observer) - { - } - - virtual void ice_response() - { - // ok, success - } - - virtual void ice_exception(const Ice::Exception& ex) - { - // - // Drop this observer - // - _serviceManager->removeObserver(_observer, ex); - } - -private: - ServiceManagerIPtr _serviceManager; - ServiceObserverPrx _observer; -}; - class PropertiesAdminI : public PropertiesAdmin { public: - + PropertiesAdminI(const PropertiesPtr& properties) : _properties(properties) { } - + virtual string getProperty(const string& name, const Current&) { return _properties->getProperty(name); @@ -72,10 +43,10 @@ public: { return _properties->getPropertiesForPrefix(prefix); } - + private: - const PropertiesPtr _properties; + const PropertiesPtr _properties; }; struct StartServiceInfo @@ -85,28 +56,28 @@ struct StartServiceInfo name = service; // - // Separate the entry point from the arguments. + // Split the entire property value into arguments. An entry point containing spaces + // must be enclosed in quotes. // - string::size_type pos = value.find_first_of(" \t\n"); - if(pos == string::npos) + try { - entryPoint = value; + args = IceUtilInternal::Options::split(value); } - else + catch(const IceUtilInternal::BadOptException& ex) { - entryPoint = value.substr(0, pos); - try - { - args = IceUtilInternal::Options::split(value.substr(pos + 1)); - } - catch(const IceUtilInternal::BadOptException& ex) - { - FailureException e(__FILE__, __LINE__); - e.reason = "ServiceManager: invalid arguments for service `" + name + "':\n" + ex.reason; - throw e; - } + PluginInitializationException e(__FILE__, __LINE__); + e.reason = "invalid arguments for service `" + name + "':\n" + ex.reason; + throw e; } + assert(!args.empty()); + + // + // Shift the arguments. + // + entryPoint = args[0]; + args.erase(args.begin()); + for(Ice::StringSeq::const_iterator p = serverArgs.begin(); p != serverArgs.end(); ++p) { if(p->find("--" + name + ".") == 0) @@ -121,13 +92,13 @@ struct StartServiceInfo Ice::StringSeq args; }; - } -IceBox::ServiceManagerI::ServiceManagerI(CommunicatorPtr communicator, int& argc, char* argv[]) : +IceBox::ServiceManagerI::ServiceManagerI(CommunicatorPtr communicator, int& argc, char* argv[]) : _communicator(communicator), _pendingStatusChanges(false), - _traceServiceObserver(0) + _traceServiceObserver(0), + _observerCompletedCB(newCallback(this, &ServiceManagerI::observerCompleted)) { _logger = _communicator->getLogger(); _traceServiceObserver = _communicator->getProperties()->getPropertyAsInt("IceBox.Trace.ServiceObserver"); @@ -197,7 +168,7 @@ IceBox::ServiceManagerI::startService(const string& name, const Current&) Warning out(_logger); out << "ServiceManager: unknown exception in start for service " << info.name; } - + { IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); @@ -318,7 +289,7 @@ IceBox::ServiceManagerI::addObserver(const ServiceObserverPrx& observer, const I { Trace out(_logger, "IceBox.ServiceObserver"); out << "Added service observer " << _communicator->proxyToString(observer); - } + } vector<string> activeServices; for(vector<ServiceInfo>::iterator p = _services.begin(); p != _services.end(); ++p) @@ -329,35 +300,15 @@ IceBox::ServiceManagerI::addObserver(const ServiceObserverPrx& observer, const I activeServices.push_back(info.name); } } - + if(activeServices.size() > 0) { - observer->servicesStarted_async(new AMICallbackT<AMI_ServiceObserver_servicesStarted>(this, observer), - activeServices); + observer->begin_servicesStarted(activeServices, _observerCompletedCB); } } } void -IceBox::ServiceManagerI::removeObserver(const ServiceObserverPrx& observer, const Ice::Exception& ex) -{ - IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); - - // - // It's possible to remove several times the same observer, e.g. multiple concurrent - // requests that fail - // - - set<ServiceObserverPrx>::iterator p = _observers.find(observer); - if(p != _observers.end()) - { - ServiceObserverPrx observer = *p; - _observers.erase(p); - observerRemoved(observer, ex); - } -} - -void IceBox::ServiceManagerI::shutdown(const Current&) { _communicator->shutdown(); @@ -393,7 +344,7 @@ IceBox::ServiceManagerI::start() // // IceBox.Service.Foo=entry_point [args] // - // We parse the service properties specified in IceBox.LoadOrder + // We parse the service properties specified in IceBox.LoadOrder // first, then the ones from remaining services. // const string prefix = "IceBox.Service."; @@ -417,7 +368,7 @@ IceBox::ServiceManagerI::start() { servicesInfo.push_back(StartServiceInfo(p->first.substr(prefix.size()), p->second, _argv)); } - + // // Check if some services are using the shared communicator in which // case we create the shared communicator now with a property set which @@ -464,12 +415,12 @@ IceBox::ServiceManagerI::start() { initData.properties->setProperty(r->first, r->second); } - + // - // Parse <service>.* command line options (the Ice command line options + // Parse <service>.* command line options (the Ice command line options // were parsed by the createProperties above) // - q->args = initData.properties->parseCommandLineOptions(q->name, q->args); + q->args = initData.properties->parseCommandLineOptions(q->name, q->args); } _sharedCommunicator = initialize(initData); } @@ -510,7 +461,7 @@ IceBox::ServiceManagerI::start() // // Add a Properties facet for each service - // + // for(vector<ServiceInfo>::iterator r = _services.begin(); r != _services.end(); ++r) { const ServiceInfo& info = *r; @@ -518,7 +469,7 @@ IceBox::ServiceManagerI::start() _communicator->addAdminFacet(new PropertiesAdminI(communicator->getProperties()), "IceBox.Service." + info.name + ".Properties"); } - + _communicator->getAdmin(); } catch(const ObjectAdapterDeactivatedException&) @@ -659,7 +610,7 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint, communicator = _sharedCommunicator; } else - { + { // // Create the service properties. We use the communicator properties as the default // properties if IceBox.InheritProperties is set. @@ -675,25 +626,25 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint, initData.properties = createProperties(info.args, initData.properties); // - // Next, parse the service "<service>.*" command line options (the Ice command + // Next, parse the service "<service>.*" command line options (the Ice command // line options were parsed by the createProperties above) // info.args = initData.properties->parseCommandLineOptions(service, info.args); } - + // // Clone the logger to assign a new prefix. // initData.logger = _logger->cloneWithPrefix(initData.properties->getProperty("Ice.ProgramName")); - + // - // Remaining command line options are passed to the communicator. This is + // Remaining command line options are passed to the communicator. This is // necessary for Ice plug-in properties (e.g.: IceSSL). // info.communicator = initialize(info.args, initData); communicator = info.communicator; } - + // // Start the service. // @@ -704,8 +655,8 @@ IceBox::ServiceManagerI::start(const string& service, const string& entryPoint, // // There is no need to notify the observers since the 'start all' - // (that indirectly calls this function) occurs before the creation of - // the Server Admin object, and before the activation of the main + // (that indirectly calls this function) occurs before the creation of + // the Server Admin object, and before the activation of the main // object adapter (so before any observer can be registered) // } @@ -798,7 +749,7 @@ IceBox::ServiceManagerI::stopAll() vector<string> stoppedServices; // - // First, for each service, we call stop on the service and flush its database environment to + // First, for each service, we call stop on the service and flush its database environment to // the disk. // for(p = _services.rbegin(); p != _services.rend(); ++p) @@ -830,7 +781,7 @@ IceBox::ServiceManagerI::stopAll() for(p = _services.rbegin(); p != _services.rend(); ++p) { ServiceInfo& info = *p; - + try { _communicator->removeAdminFacet("IceBox.Service." + info.name + ".Properties"); @@ -863,9 +814,9 @@ IceBox::ServiceManagerI::stopAll() } // - // Release the service, the service communicator and then the library. The order is important, + // Release the service, the service communicator and then the library. The order is important, // the service must be released before destroying the communicator so that the communicator - // leak detector doesn't report potential leaks, and the communicator must be destroyed before + // leak detector doesn't report potential leaks, and the communicator must be destroyed before // the library is released since the library will destroy its global state. // try @@ -898,7 +849,7 @@ IceBox::ServiceManagerI::stopAll() out << ex; } } - + try { info.library = 0; @@ -933,6 +884,8 @@ IceBox::ServiceManagerI::stopAll() _services.clear(); servicesStopped(stoppedServices, _observers); + + _observerCompletedCB = 0; // Break cyclic reference count. } void @@ -942,9 +895,7 @@ IceBox::ServiceManagerI::servicesStarted(const vector<string>& services, const s { for(set<ServiceObserverPrx>::const_iterator p = observers.begin(); p != observers.end(); ++p) { - ServiceObserverPrx observer = *p; - observer->servicesStarted_async(new AMICallbackT<AMI_ServiceObserver_servicesStarted>(this, observer), - services); + (*p)->begin_servicesStarted(services, _observerCompletedCB); } } } @@ -956,16 +907,14 @@ IceBox::ServiceManagerI::servicesStopped(const vector<string>& services, const s { for(set<ServiceObserverPrx>::const_iterator p = observers.begin(); p != observers.end(); ++p) { - ServiceObserverPrx observer = *p; - observer->servicesStopped_async(new AMICallbackT<AMI_ServiceObserver_servicesStopped>(this, observer), - services); + (*p)->begin_servicesStopped(services, _observerCompletedCB); } } } void IceBox::ServiceManagerI::observerRemoved(const ServiceObserverPrx& observer, const std::exception& ex) -{ +{ if(_traceServiceObserver >= 1) { // @@ -979,8 +928,8 @@ IceBox::ServiceManagerI::observerRemoved(const ServiceObserverPrx& observer, con out << "Removed service observer " << _communicator->proxyToString(observer) << "\nafter catching " << ex.what(); } - } -} + } +} Ice::PropertiesPtr IceBox::ServiceManagerI::createServiceProperties(const string& service) @@ -996,7 +945,7 @@ IceBox::ServiceManagerI::createServiceProperties(const string& service) { properties = createProperties(); } - + string programName = communicatorProperties->getProperty("Ice.ProgramName"); if(programName.empty()) { @@ -1008,3 +957,29 @@ IceBox::ServiceManagerI::createServiceProperties(const string& service) } return properties; } + +void +ServiceManagerI::observerCompleted(const Ice::AsyncResultPtr& result) +{ + try + { + result->throwLocalException(); + } + catch(const Ice::LocalException& ex) + { + ServiceObserverPrx observer = ServiceObserverPrx::uncheckedCast(result->getProxy()); + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + // + // It's possible to remove several times the same observer, e.g. multiple concurrent + // requests that fail + // + set<ServiceObserverPrx>::iterator p = _observers.find(observer); + if(p != _observers.end()) + { + ServiceObserverPrx observer = *p; + _observers.erase(p); + observerRemoved(observer, ex); + } + } +} |