diff options
Diffstat (limited to 'cpp/src/IcePack/Server.cpp')
-rw-r--r-- | cpp/src/IcePack/Server.cpp | 444 |
1 files changed, 276 insertions, 168 deletions
diff --git a/cpp/src/IcePack/Server.cpp b/cpp/src/IcePack/Server.cpp index 71b47459ccb..37643b62116 100644 --- a/cpp/src/IcePack/Server.cpp +++ b/cpp/src/IcePack/Server.cpp @@ -8,12 +8,14 @@ // // ********************************************************************** -#include <Freeze/Application.h> +#include <Ice/Application.h> +#include <Freeze/Freeze.h> #include <IcePack/LocatorI.h> #include <IcePack/LocatorRegistryI.h> #include <IcePack/ServerManagerI.h> #include <IcePack/AdapterManagerI.h> #include <IcePack/AdminI.h> +#include <IcePack/TraceLevels.h> #ifndef _WIN32 # include <IcePack/ActivatorI.h> # include <signal.h> @@ -30,17 +32,31 @@ using namespace Ice; using namespace Freeze; using namespace IcePack; -class Server : public Freeze::Application +class Server : public Ice::Application { public: - Server(const string& dbEnvName) : - Freeze::Application(dbEnvName) + Server() { } void usage(); - virtual int runFreeze(int argc, char* argv[], const DBEnvironmentPtr&); + virtual int run(int argc, char* argv[]); + +private: + + void initInternal(const CommunicatorPtr&); + void initLocator(const CommunicatorPtr&); + void initLocatorRegistry(const CommunicatorPtr&); + void initAdmin(const CommunicatorPtr&, const CommunicatorPtr&); + + AdapterManagerPrx _adapterManager; + ServerManagerPrx _serverManager; + ActivatorPtr _activator; + AdminPrx _admin; + LocatorPrx _locator; + LocatorRegistryPrx _locatorRegistry; + DBEnvironmentPtr _dbEnv; }; #ifndef _WIN32 @@ -77,60 +93,7 @@ main(int argc, char* argv[]) return EXIT_FAILURE; } - // TODO: ML: Loose this try/catch, it's unnecessary. The - // Application::main() catches already. - PropertiesPtr defaultProperties; - try - { - defaultProperties = getDefaultProperties(argc, argv); - StringSeq args = argsToStringSeq(argc, argv); - args = defaultProperties->parseCommandLineOptions("IcePack", args); - stringSeqToArgs(args, argc, argv); - } - catch(const SystemException& ex) - { - cerr << argv[0] << ": " << ex << endl; - return EXIT_FAILURE; - } - - // - // Check that IcePack.Data property is set and creates - // subdirectories db and servers if they don't already exist. - // - string dataPath = defaultProperties->getProperty("IcePack.Data"); - if(dataPath.empty()) - { - cerr << argv[0] << ": property `IcePack.Data' is not set" << endl; - return EXIT_FAILURE; - } - if(dataPath[dataPath.length() - 1] != '/') - { - dataPath += "/"; - } - - string dbPath = dataPath + "db"; - string serversPath = dataPath + "servers"; - - struct stat filestat; - if(stat(dataPath.c_str(), &filestat) == 0 && S_ISDIR(filestat.st_mode)) - { - if(stat(dbPath.c_str(), &filestat) != 0) - { - mkdir(dbPath.c_str(), 0755); - } - - if(stat(serversPath.c_str(), &filestat) != 0) - { - mkdir(serversPath.c_str(), 0755); - } - } - else - { - cerr << argv[0] << ": `IcePack.Data' doesn't contain a valid directory path." << endl; - return EXIT_FAILURE; - } - - ::Server app(dbPath); + ::Server app; int rc = app.main(argc, argv); XMLPlatformUtils::Terminate(); @@ -154,10 +117,12 @@ void } int -::Server::runFreeze(int argc, char* argv[], const DBEnvironmentPtr& dbEnv) +::Server::run(int argc, char* argv[]) { PropertiesPtr properties = communicator()->getProperties(); + communicator()->setDefaultLocator(0); + StringSeq args = argsToStringSeq(argc, argv); args = properties->parseCommandLineOptions("IcePack", args); args = properties->parseCommandLineOptions("Freeze", args); @@ -206,22 +171,40 @@ int } } - string locatorEndpoints = properties->getProperty("IcePack.Locator.Endpoints"); - if(locatorEndpoints.empty()) + // + // Check that required properties are set and valid. + // + if(properties->getProperty("IcePack.Locator.Endpoints").empty()) { cerr << appName() << ": property `IcePack.Locator.Endpoints' is not set" << endl; return EXIT_FAILURE; } - - string locatorRegistryEndpoints = properties->getProperty("IcePack.LocatorRegistry.Endpoints"); - if(locatorRegistryEndpoints.empty()) + if(properties->getProperty("IcePack.LocatorRegistry.Endpoints").empty()) { cerr << appName() << ": property `IcePack.LocatorRegistry.Endpoints' is not set" << endl; return EXIT_FAILURE; } - - string adminEndpoints = properties->getProperty("IcePack.Admin.Endpoints"); - if(!adminEndpoints.empty()) + if(properties->getProperty("IcePack.Data").empty()) + { + cerr << argv[0] << ": property `IcePack.Data' is not set" << endl; + return EXIT_FAILURE; + } + else + { + struct stat filestat; + if(stat(properties->getProperty("IcePack.Data").c_str(), &filestat) != 0) + { + cerr << argv[0] << ": failed to check if property `IcePack.Data' is set to a directory path: " + << strerror(getSystemErrno()) << endl; + return EXIT_FAILURE; + } + if(!S_ISDIR(filestat.st_mode)) + { + cerr << argv[0] << ": property `IcePack.Data' is not set to a directory path" << endl; + return EXIT_FAILURE; + } + } + if(!properties->getProperty("IcePack.Admin.Endpoints").empty()) { if(!nowarn) { @@ -229,137 +212,262 @@ int } } - string locatorId = properties->getPropertyWithDefault("IcePack.Locator.Identity", "IcePack/locator"); - string locatorRegistryId = properties->getPropertyWithDefault("IcePack.LocatorRegistry.Identity", - "IcePack/locatorregistry"); - string adminId = properties->getPropertyWithDefault("IcePack.Admin.Identity", "IcePack/admin"); - - communicator()->getProperties()->setProperty("Ice.Default.Locator", locatorId + ":" + locatorEndpoints); - // - // An internal object adapter for internal objects which are not - // exposed to the outside world. They might be at one point. + // We need another communicator for two reasons: // - ObjectAdapterPtr internalAdapter = communicator()->createObjectAdapterWithEndpoints("IcePack.Internal", ""); - internalAdapter->setLocator(0); - + // We need a separate thread pool to dispatch the locator registry + // incoming calls to avoid deadlocks (where a client makes a + // request on the locator which in turn causes the activation of a + // server which invoke on the locator registry interface). // - // Creates and register the adapter manager. + // We need to make collocated calls on the internal objects after + // shutdown. // - AdapterManagerPtr adapterManager = new AdapterManagerI(internalAdapter, dbEnv); - AdapterManagerPrx adapterManagerProxy = - AdapterManagerPrx::uncheckedCast(internalAdapter->add(adapterManager, - stringToIdentity("IcePack/adaptermanager"))); + int dummyArgc = 0; + char **dummyArgv = 0; + Ice::CommunicatorPtr backendCommunicator = Ice::initialize(dummyArgc, dummyArgv, communicator()->getProperties()); + + int status = EXIT_SUCCESS; + + try + { + // + // Initialize internal objects and external interfaces. + // + initInternal(backendCommunicator); + initLocatorRegistry(backendCommunicator); + initLocator(communicator()); + initAdmin(communicator(), backendCommunicator); + + + // + // Deploy application descriptor if a descriptor is passed as + // a command line option. + // + if(!descriptor.empty()) + { + try + { + _admin->addApplication(descriptor, targets); + } + catch(const ServerDeploymentException& ex) + { + cerr << appName() << ": warning: failed to deploy application " << descriptor << ":" << endl; + cerr << ex << ": " << ex.server << ": " << ex.reason << endl; + } + catch(const DeploymentException& ex) + { + cerr << appName() << ": warning: failed to deploy application " << descriptor << ":" << endl; + cerr << ex << ": " << ex.component << ": " << ex.reason << endl; + } + } + + string bundleName = properties->getProperty("IcePack.PrintServersReady"); + if(!bundleName.empty()) + { + cout << bundleName << " ready" << endl; + } + + shutdownOnInterrupt(); + communicator()->waitForShutdown(); + ignoreInterrupt(); + } + catch(const DBException& ex) + { + cerr << appName() << ": " << ex << ": " << ex.message << endl; + status = EXIT_FAILURE; + } + catch(const Exception& ex) + { + cerr << appName() << ": " << ex << endl; + status = EXIT_FAILURE; + } + catch(...) + { + cerr << appName() << ": unknown exception" << endl; + status = EXIT_FAILURE; + } + + try + { + // + // Destroy and join with activator, must be done before shutting + // down the backend communicator since invocation on collocated + // objects are done while deactivating the servers. + // + if(_activator) + { + _activator->destroy(); + _activator = 0; + } + + _adapterManager = 0; + _serverManager = 0; + _admin = 0; + _locator = 0; + _locatorRegistry = 0; + + // + // Shutdown the backend communicator. This cause the internal + // adapter to evict all its objects and save their state to + // the database. This needs to be done before destroying the + // database environment. + // + backendCommunicator->shutdown(); + backendCommunicator->waitForShutdown(); + + if(_dbEnv) + { + _dbEnv->close(); + _dbEnv = 0; + } + + backendCommunicator->destroy(); + backendCommunicator = 0; + } + catch(const DBException& ex) + { + cerr << appName() << ": " << ex << ": " << ex.message << endl; + status = EXIT_FAILURE; + } + + return status; +} + +// +// Initialize internal objects: the adapter manager, the server +// manager and the activator. +// +void +::Server::initInternal(const CommunicatorPtr& communicator) +{ + PropertiesPtr properties = communicator->getProperties(); + + TraceLevelsPtr traceLevels = new TraceLevels(properties, communicator->getLogger()); // - // Activator and server manager are not supported on Windows yet. + // Creates subdirectories db and servers if they don't already + // exist. // - ServerManagerPrx serverManagerProxy; + string dataPath = properties->getProperty("IcePack.Data"); + if(dataPath[dataPath.length() - 1] != '/') + { + dataPath += "/"; + } -#ifndef _WIN32 + string dbPath = dataPath + "db"; + string serversPath = dataPath + "servers"; + + struct stat filestat; + if(stat(dbPath.c_str(), &filestat) != 0) + { + mkdir(dbPath.c_str(), 0755); + } + + if(stat(serversPath.c_str(), &filestat) != 0) + { + mkdir(serversPath.c_str(), 0755); + } + + _dbEnv = Freeze::initialize(communicator, dbPath); + + ObjectAdapterPtr adapter = communicator->createObjectAdapterWithEndpoints("IcePackInternalAdapter", ""); + adapter->setLocator(0); - ActivatorIPtr activator = new ActivatorI(communicator()); + Ice::ObjectPrx object; + + ActivatorIPtr activator = new ActivatorI(communicator, traceLevels); activator->start(); - ActivatorPrx activatorProxy = ActivatorPrx::uncheckedCast(internalAdapter->add(activator, - stringToIdentity("IcePack/activator"))); + _activator = activator; - ServerManagerPtr serverManager = new ServerManagerI(internalAdapter, dbEnv, adapterManagerProxy, activatorProxy); - serverManagerProxy = - ServerManagerPrx::uncheckedCast(internalAdapter->add(serverManager, - stringToIdentity("IcePack/servermanager"))); - internalAdapter->activate(); + AdapterManagerPtr adapterManager = new AdapterManagerI(adapter, traceLevels, _dbEnv); + object = adapter->add(adapterManager, stringToIdentity("IcePack/AdapterManager")); + _adapterManager = AdapterManagerPrx::uncheckedCast(object); -#endif + ServerManagerPtr serverManager = new ServerManagerI(adapter, traceLevels, _dbEnv, _adapterManager, _activator); + object = adapter->add(serverManager, stringToIdentity("IcePack/ServerManager")); + _serverManager = ServerManagerPrx::uncheckedCast(object); - // - // Create the "IcePack.Admin" object adapter and register the - // admin object. The admin object is used by icepackadmin to - // administrate IcePack. - // - ObjectAdapterPtr adminAdapter = communicator()->createObjectAdapterWithEndpoints("IcePack.Admin", adminEndpoints); - AdminPtr admin = new AdminI(communicator(), serverManagerProxy, adapterManagerProxy); - adminAdapter->add(admin, stringToIdentity(adminId)); + adapter->activate(); +} - // - // Create the "IcePack.LocatorRegistry" object adapter and - // registry the locator registry object. - // - // The locator registry object provides an implementation of the - // Ice::LocatorRegistry interface. This interface is used by Ice - // servers to register their object adapters. - // - ObjectAdapterPtr locatorRegistryAdapter = - communicator()->createObjectAdapterWithEndpoints("IcePack.LocatorRegistry", locatorRegistryEndpoints); - locatorRegistryAdapter->setLocator(0); - LocatorRegistryPtr locatorRegistry = new LocatorRegistryI(adapterManagerProxy); - LocatorRegistryPrx locatorRegistryProxy = - LocatorRegistryPrx::uncheckedCast(locatorRegistryAdapter->add(locatorRegistry, - stringToIdentity(locatorRegistryId))); +void +::Server::initLocator(const CommunicatorPtr& communicator) +{ + assert(_adapterManager && _locatorRegistry); + + PropertiesPtr properties = communicator->getProperties(); + + string endpoints = properties->getProperty("IcePack.Locator.Endpoints"); + string id = properties->getPropertyWithDefault("IcePack.Locator.Identity", "IcePack/Locator"); // // Create the "IcePack.Locator" object adapter and register the // locator object. // - // The locator locator object provides an implementation of the + // The locator object provides an implementation of the // Ice::Locator interface. This interface is used by Ice clients // to locate object adapters and their associated endpoints. // - LocatorPtr locator = new LocatorI(adapterManagerProxy, locatorRegistryProxy); - ObjectAdapterPtr locatorAdapter = communicator()->createObjectAdapterWithEndpoints("IcePack.Locator", - locatorEndpoints); - locatorAdapter->setLocator(0); - LocatorPrx locatorProxy = LocatorPrx::uncheckedCast(locatorAdapter->add(locator, stringToIdentity(locatorId))); + ObjectAdapterPtr adapter = communicator->createObjectAdapterWithEndpoints("IcePackLocatorAdapter", endpoints); + adapter->setLocator(0); - // - // Set the locator for the admin object adapter. - // - adminAdapter->setLocator(locatorProxy); + LocatorPtr locator = new LocatorI(_adapterManager, _locatorRegistry); + _locator = LocatorPrx::uncheckedCast(adapter->add(locator, stringToIdentity(id))); - // - // Activate adapters. - // - adminAdapter->activate(); - locatorRegistryAdapter->activate(); - locatorAdapter->activate(); + adapter->activate(); +} + +void +::Server::initLocatorRegistry(const CommunicatorPtr& communicator) +{ + assert(_adapterManager); + + PropertiesPtr properties = communicator->getProperties(); + + string endpoints = properties->getProperty("IcePack.LocatorRegistry.Endpoints"); + string id = properties->getPropertyWithDefault("IcePack.LocatorRegistry.Identity", "IcePack/LocatorRegistry"); // - // Deploy application desciptor. + // Create the "IcePack.LocatorRegistry" object adapter and + // register the locator registry object. // - if(!descriptor.empty()) - { - try - { - admin->addApplication(descriptor, targets); - } - catch(const ServerDeploymentException& ex) - { - cerr << appName() << ": warning: failed to deploy application " << descriptor << ":" << endl; - cerr << ex << ": " << ex.server << ": " << ex.reason << endl; - } - catch(const DeploymentException& ex) - { - cerr << appName() << ": warning: failed to deploy application " << descriptor << ":" << endl; - cerr << ex << ": " << ex.component << ": " << ex.reason << endl; - } - } + // The locator registry object provides an implementation of the + // Ice::LocatorRegistry interface. This interface is used by Ice + // servers to register their object adapters. + // + ObjectAdapterPtr adapter = communicator->createObjectAdapterWithEndpoints("IcePackLocatorRegistryAdapter", + endpoints); + adapter->setLocator(0); + LocatorRegistryPtr locatorRegistry = new LocatorRegistryI(_adapterManager); + _locatorRegistry = LocatorRegistryPrx::uncheckedCast(adapter->add(locatorRegistry, stringToIdentity(id))); - string bundleName = properties->getProperty("IcePack.PrintServersReady"); - if(!bundleName.empty()) - { - cout << bundleName << " ready" << endl; - } + adapter->activate(); +} - shutdownOnInterrupt(); - communicator()->waitForShutdown(); - ignoreInterrupt(); +void +::Server::initAdmin(const CommunicatorPtr& communicator, const CommunicatorPtr& backendCommunicator) +{ + assert(_serverManager && _adapterManager && _locator); + + PropertiesPtr properties = communicator->getProperties(); -#ifndef _WIN32 // - // Destroy and join with activator. + // The deployer get the locator proxy from the communicator + // properties. // - activator->destroy(); - activator->getThreadControl().join(); -#endif + properties->setProperty("Ice.Default.Locator", communicator->proxyToString(_locator)); + + backendCommunicator->setDefaultLocator(_locator); + + string endpoints = properties->getProperty("IcePack.Admin.Endpoints"); + string id = properties->getPropertyWithDefault("IcePack.Admin.Identity", "IcePack/Admin"); + + ObjectAdapterPtr adapter = communicator->createObjectAdapterWithEndpoints("IcePackAdminAdapter", endpoints); + AdminPtr admin = new AdminI(communicator, backendCommunicator, _serverManager, _adapterManager); + _admin = AdminPrx::uncheckedCast(adapter->add(admin, stringToIdentity(id))); + + _locatorRegistry->addAdapter("IcePackAdminAdapter", adapter->createProxy(stringToIdentity("dummy"))); - return EXIT_SUCCESS; + adapter->activate(); } |