diff options
author | fields_t <fields_t@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2004-09-24 20:19:09 +0000 |
---|---|---|
committer | fields_t <fields_t@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2004-09-24 20:19:09 +0000 |
commit | 0848317866091b02f40ea62d8db7d580efd1a561 (patch) | |
tree | c4f33b43453b6e5cc15558ab3da655e36fba99e8 /TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp | |
parent | 6a271e6178c4016b0a15578f553833125ef146de (diff) | |
download | ATCD-0848317866091b02f40ea62d8db7d580efd1a561.tar.gz |
ChangeLogTag:Fri Sep 24 13:16:44 MST 2004 Trevor Fields <fields_t@ociweb.com>
Diffstat (limited to 'TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp')
-rw-r--r-- | TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp | 1648 |
1 files changed, 1019 insertions, 629 deletions
diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp index f2971a7fbc5..6602e7a0a88 100644 --- a/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp @@ -1,706 +1,890 @@ // $Id$ #include "ImR_Locator_i.h" +#include "utils.h" +#include "Iterator.h" -#include "Locator_Options.h" -#include "Forwarder.h" -#include "INS_Locator.h" -#include "Adapter_Activator.h" - -#include "orbsvcs/IOR_Multicast.h" +#include "orbsvcs/Time_Utilities.h" #include "tao/IORTable/IORTable.h" #include "tao/PortableServer/POA.h" - #include "tao/ORB_Core.h" #include "tao/default_ports.h" +#include "tao/Messaging/Messaging.h" -#include "ace/Get_Opt.h" -#include "ace/Process_Manager.h" +#include "ace/ARGV.h" #include "ace/OS_NS_sys_time.h" +static const int DEFAULT_START_LIMIT = 1; +static const int IS_ALIVE_RETRY_COUNT = 60; +static const ACE_Time_Value IS_ALIVE_RETRY_INTERVAL(1); + +static const ACE_Time_Value DEFAULT_SERVER_TIMEOUT(0, 100 * 1000); // 100ms + +// If the POA locking problem is ever corrected, this class (along with +// some code in ImR_Locator_i::server_is_running) should be removed. +#if !defined (ACE_HAS_RECURSIVE_MUTEXES) +class Status_Changed_Timer: public ACE_Event_Handler +{ +public: + Status_Changed_Timer(ImR_Locator_i* locator, + const Server_Info_Ptr& info); + + virtual int handle_timeout (const ACE_Time_Value& current_time, + const void* act); +private: + ImR_Locator_i* locator_; + Server_Info_Ptr info_; +}; + +Status_Changed_Timer::Status_Changed_Timer(ImR_Locator_i* locator, + const Server_Info_Ptr& info) + : locator_(locator), + info_(info) +{ +} + +int +Status_Changed_Timer::handle_timeout (const ACE_Time_Value&, + const void*) +{ + locator_->server_status_changed(*info_); + delete this; + return 0; +} +#endif /* ACE_HAS_RECURSIVE_MUTEXES */ + + ImR_Locator_i::ImR_Locator_i () - : - forwarder_impl_ (0), - activator_ (0), - ins_locator_ (0) +: forwarder_(*this) +, ins_locator_(*this) +, debug_(0) +, read_only_(false) { - this->ins_locator_ = new INS_Locator(this); } int -ImR_Locator_i::init (ACE_ENV_SINGLE_ARG_DECL) +ImR_Locator_i::init_with_orb (CORBA::ORB_ptr orb, Options& opts ACE_ENV_ARG_DECL) { - orb_ = OPTIONS::instance()->orb(); + orb_ = CORBA::ORB::_duplicate(orb); + debug_ = opts.debug(); + read_only_ = opts.readonly(); + startup_timeout_ = opts.startup_timeout(); + ping_interval_ = opts.ping_interval(); CORBA::Object_var obj = - orb_->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); + this->orb_->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - - PortableServer::POA_var root_poa = - PortableServer::POA::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + this->root_poa_ = PortableServer::POA::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (-1); + ACE_ASSERT(! CORBA::is_nil(this->root_poa_.in())); - if (CORBA::is_nil (root_poa.in ())) - ACE_ERROR_RETURN ((LM_ERROR, - "Unable to obtain RootPOA reference.\n"), - -1); + this->forwarder_.init(orb ACE_ENV_ARG_PARAMETER); + this->adapter_.init(& this->forwarder_); - PortableServer::POAManager_var poa_manager = - root_poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + // Register the Adapter_Activator reference to be the RootPOA's + // Adapter Activator. + root_poa_->the_activator (&this->adapter_ ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - // We are going to set the policies to be used with the child - // POA. - CORBA::PolicyList policies (2); - policies.length (2); - - policies[0] = - root_poa->create_id_assignment_policy (PortableServer::USER_ID - ACE_ENV_ARG_PARAMETER); + CORBA::PolicyList policies; + imr_poa_ = root_poa_->create_POA ("ImplRepoService", + PortableServer::POAManager::_nil(), policies ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - policies[1] = - root_poa->create_lifespan_policy (PortableServer::PERSISTENT - ACE_ENV_ARG_PARAMETER); + PortableServer::ObjectId_var id = this->imr_poa_->activate_object(this ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - PortableServer::POA_var locator_poa = - root_poa->create_POA ("ImplRepoService", - poa_manager.in (), - policies - ACE_ENV_ARG_PARAMETER); + obj = this->imr_poa_->id_to_reference (id.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + CORBA::String_var ior = this->orb_->object_to_string(obj.in() ACE_ENV_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - // Creation of the new POAs is over, so destroy the Policy_ptr's as - // we dont need them anymore. - for (CORBA::ULong i = 0; i < policies.length (); ++i) - { - CORBA::Policy_ptr policy = policies[i]; - policy->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); - ACE_CHECK_RETURN (-1); - } + // Register the ImR for use with INS + obj = orb->resolve_initial_references ("IORTable" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + IORTable::Table_var ior_table = IORTable::Table::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + ACE_ASSERT(! CORBA::is_nil(ior_table.in())); + ior_table->bind ("ImplRepoService", ior.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + ior_table->set_locator (&this->ins_locator_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); - // Register 'this' with the ImR_Forwarder - ACE_NEW_RETURN (this->forwarder_impl_, - ImR_Forwarder (this, orb_.in ()), - -1); + // Set up multicast support (if enabled) + if (opts.multicast()) + { + ACE_Reactor* reactor = orb->orb_core()->reactor(); + if (this->setup_multicast (reactor, ior.in()) != 0) + return -1; + } - // Get the ObjectID for the string child POA name. - PortableServer::ObjectId_var locator_id = - PortableServer::string_to_ObjectId ("ImplRepoService"); + // Initialize the persistent storage. This will load any values that + // may have been persisted before. + // The init can return 1 if there is no persistent file yet. In + // that case, we need not do anything for now. + int init_result = + this->repository_.init (opts.repository_mode(), opts.persist_file_name()); + if (init_result == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, "Repository failed to initialize\n"), -1); + } - // Activate the object with the given id. - locator_poa->activate_object_with_id (locator_id.in (), - this - ACE_ENV_ARG_PARAMETER); + // Activate the two poa managers + PortableServer::POAManager_var poaman = + this->root_poa_->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - - // Get the locator object reference - CORBA::Object_var locator_obj = - locator_poa->id_to_reference (locator_id.in () ACE_ENV_ARG_PARAMETER); + poaman->activate (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - - // Get the reference to IORTable. - obj = orb_->resolve_initial_references ("IORTable" ACE_ENV_ARG_PARAMETER); + poaman = this->imr_poa_->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - - // Narrow it down to the correct type - IORTable::Table_var adapter = - IORTable::Table::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + poaman->activate (ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - CORBA::String_var ior; - - if (CORBA::is_nil (adapter.in ())) - { - ACE_ERROR ((LM_ERROR, "Nil IORTable\n")); - } - else + // We write the ior file last so that the tests can know we are ready. + if (opts.ior_filename().length() > 0) + { + FILE* fp = ACE_OS::fopen(opts.ior_filename().c_str(), "w"); + if (fp == 0) { - // Set the locator - adapter->set_locator (this->ins_locator_.in () ACE_ENV_ARG_PARAMETER); - ACE_CHECK_RETURN (-1); - - // Get the stringified format of the locator's object - // reference. - ior = orb_->object_to_string (locator_obj.in () ACE_ENV_ARG_PARAMETER); - ACE_CHECK_RETURN (-1); - - // Finally, bind this ior to the child POA's name in the - // IORTable. - adapter->bind ("ImplRepoService", ior.in () ACE_ENV_ARG_PARAMETER); - ACE_CHECK_RETURN (-1); + ACE_ERROR_RETURN ((LM_ERROR, + "ImR Locator: Could not open file: %s\n", opts.ior_filename().c_str()), -1); } + ACE_OS::fprintf(fp, "%s", ior.in()); + ACE_OS::fclose(fp); + } - ACE_CString output_filename = OPTIONS::instance()->output_filename(); - - if (output_filename.length() > 0) - { - FILE* fp = ACE_OS::fopen(output_filename.c_str(), "w"); - ACE_ASSERT(fp != 0); - ACE_OS::fprintf(fp, "%s", ior.in()); - ACE_OS::fclose(fp); - } + return 0; +} - ACE_NEW_RETURN (this->activator_, - ImR_Adapter_Activator (this->forwarder_impl_), - -1); +int +ImR_Locator_i::init(Options& opts ACE_ENV_ARG_DECL) +{ + ACE_ARGV av(opts.cmdline().c_str()); + int argc = av.argc(); + char** argv = av.argv(); + + CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "TAO_ImR_Locator" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(-1); + int err = this->init_with_orb(orb.in(), opts ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(-1); + return err; +} - // Register the Adapter_Activator reference to be the RootPOA's - // Adapter Activator. - root_poa->the_activator (this->activator_ ACE_ENV_ARG_PARAMETER); +int +ImR_Locator_i::run(ACE_ENV_SINGLE_ARG_DECL) +{ + if (debug_ > 0) + { + ACE_DEBUG((LM_DEBUG, "ImR Locator: Running\n" + "\tPing Interval : %ds\n" + "\tStartup Timeout : %ds\n" + "\tPersistence : %s\n" + "\tLocked : %s\n\n", + ping_interval_.sec(), + startup_timeout_.sec(), + repository_.repo_mode(), + read_only_ ? "true" : "false")); + } + this->auto_start_servers(ACE_ENV_SINGLE_ARG_PARAMETER); ACE_CHECK_RETURN (-1); - if (OPTIONS::instance()->multicast()) - { - ACE_Reactor *reactor = orb_->orb_core ()->reactor (); + this->orb_->run(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + return 0; +} - ACE_Process_Manager process_manager; - process_manager.open (ACE_Process_Manager::DEFAULT_SIZE, reactor); +int +ImR_Locator_i::fini (ACE_ENV_SINGLE_ARG_DECL) +{ + ACE_TRY + { + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Shutting down...\n")); - if (this->setup_multicast (reactor, ior.in ()) != 0) - return -1; - } - else - { - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Multicast Handler disabled.\n")); - } - } + this->root_poa_->destroy (1, 1 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; - poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER); - ACE_CHECK_RETURN (-1); + this->orb_->destroy(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; - orb_->run (ACE_ENV_SINGLE_ARG_PARAMETER); + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Shut down successfully.\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::fini"); + ACE_RE_THROW; + } + ACE_ENDTRY; ACE_CHECK_RETURN (-1); - return 0; } -/** - * First, figure out if we should set up a multicast handler (based on command - * line settings) and which port to set it up (based on the environment, - * command line, or the default IMPLREPOSERVICE port). Then register the - * handler with the @param reactor. - * - * @retval 0 ok - * @retval -1 failed - */ int -ImR_Locator_i::setup_multicast (ACE_Reactor *reactor, - const char *ior) +ImR_Locator_i::setup_multicast (ACE_Reactor* reactor, const char* ior) { ACE_ASSERT (reactor != 0); + ACE_ASSERT (ior != 0); #if defined (ACE_HAS_IP_MULTICAST) + TAO_ORB_Core* core = TAO_ORB_Core_instance(); // See if the -ORBMulticastDiscoveryEndpoint option was specified. - ACE_CString mde (TAO_ORB_Core_instance ()->orb_params ()->mcast_discovery_endpoint ()); - - // First, see if the user has given us a multicast port number - // on the command-line; - u_short port = - TAO_ORB_Core_instance ()->orb_params ()->service_port (IMPLREPOSERVICE); + ACE_CString mde (core->orb_params()->mcast_discovery_endpoint()); - if (port == 0) + if (mde.length () != 0) + { + if (this->ior_multicast_.init(ior, + mde.c_str(), TAO_SERVICEID_IMPLREPOSERVICE) == -1) + { + return -1; + } + } + else + { + // Port can be specified as param, env var, or default + CORBA::UShort port = core->orb_params()->service_port(IMPLREPOSERVICE); + if (port == 0) { // Check environment var. for multicast port. - const char *port_number = ACE_OS::getenv ("ImplRepoServicePort"); + const char* port_number = ACE_OS::getenv ("ImplRepoServicePort"); if (port_number != 0) port = ACE_OS::atoi (port_number); } + if (port == 0) + port = TAO_DEFAULT_IMPLREPO_SERVER_REQUEST_PORT; - // Port wasn't specified on the command-line or in environment - - // use the default. - if (port == 0) - port = TAO_DEFAULT_IMPLREPO_SERVER_REQUEST_PORT; - - // Instantiate a handler which will handle client requests for - // the ImplRepoService ior, received on the multicast port. - TAO_IOR_Multicast *ior_multicast; - - ACE_NEW_RETURN (ior_multicast, - TAO_IOR_Multicast (), - -1); - - if (mde.length () != 0) - { - // initializes - if (ior_multicast->init (ior, - mde.c_str (), - TAO_SERVICEID_IMPLREPOSERVICE) == -1) - return -1; - } - else + if (this->ior_multicast_.init(ior, port, + ACE_DEFAULT_MULTICAST_ADDR, TAO_SERVICEID_IMPLREPOSERVICE) == -1) { - if (ior_multicast->init (ior, - port, - ACE_DEFAULT_MULTICAST_ADDR, - TAO_SERVICEID_IMPLREPOSERVICE) == -1) - return -1; + return -1; } + } // Register event handler for the ior multicast. - if (reactor->register_handler (ior_multicast, - ACE_Event_Handler::READ_MASK) == -1) - { - if (OPTIONS::instance()->debug() >= 1) - ACE_DEBUG ((LM_DEBUG, - "ImR Locator: " - "cannot register Event handler\n")); - return -1; - } + if (reactor->register_handler (&this->ior_multicast_, + ACE_Event_Handler::READ_MASK) == -1) + { + if (debug_ >= 1) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: cannot register Event handler\n")); + return -1; + } - if (OPTIONS::instance()->debug() >= 1) - ACE_DEBUG ((LM_DEBUG, - "ImR Locator: Multicast Handler enabled.\n")); + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Multicast Handler enabled.\n")); return 0; -#else /* ACE_HAS_IP_MULTICAST */ - +#else /* ACE_HAS_IP_MULTICAST*/ ACE_UNUSED_ARG (reactor); ACE_UNUSED_ARG (ior); - ACE_DEBUG ((LM_WARNING, - "ImR Locator: " - "ACE_HAS_IP_MULTICAST is not defined. " - "Multicast support disabled.\n")); - return 0; -#endif /* ACE_HAS_IP_MULTICAST */ +#endif /* ACE_HAS_IP_MULTICAST*/ } CORBA::Long -ImR_Locator_i::register_activator (const char* activator, - ImplementationRepository::Administration_ptr admin, - const ImplementationRepository::Locator::ServerNameList & servers - ACE_ENV_ARG_DECL_NOT_USED) - ACE_THROW_SPEC ((CORBA::SystemException)) +ImR_Locator_i::register_activator (const char* aname, + ImplementationRepository::Activator_ptr activator + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) { - for (CORBA::ULong idx = 0; idx < servers.length(); ++idx) { - const char* server = servers[idx]; - int err = this->server_map_.bind(server, activator); - ACE_ASSERT(err == 0 || err == 1); - ACE_UNUSED_ARG (err); - } + ACE_ASSERT(aname != 0); + ACE_ASSERT(! CORBA::is_nil(activator)); - ActivatorInfo info; - // We save the unique hash value of the passed in admin object, so that - // we can prevent accidental unregister by a different activator. - info.token = ACE_OS::gettimeofday().msec(); - info.admin = ImplementationRepository::Administration::_duplicate(admin); + // Before we can register the activator, we need to ensure that any existing + // registration is purged. + this->unregister_activator_i(aname); + ACE_CHECK_RETURN(0); - int bind_return = this->activator_map_.bind (activator, info); + CORBA::String_var ior = + this->orb_->object_to_string (activator ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); - if (bind_return == 1) // Success, but was already bound. + CORBA::Long token = ACE_OS::gettimeofday().msec(); + + int err = this->repository_.add_activator (aname, token, ior.in(), activator); + ACE_ASSERT(err == 0); + ACE_UNUSED_ARG(err); + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Activator registered for %s.\n", aname)); + + return token; +} + +void +ImR_Locator_i::unregister_activator (const char* aname, + CORBA::Long token + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_ASSERT(aname != 0); + Activator_Info_Ptr info = + this->get_activator (aname); + ACE_CHECK; + + if (! info.null()) { - if (OPTIONS::instance()->debug() >= 1) + if (info->token != token && this->debug_ > 0) { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: New activator registered for %s.\n", activator)); + ACE_DEBUG((LM_DEBUG, "ImR Locator: Ignoring unregister activator:%s. Wrong token.\n", aname)); + return; } - return info.token; + + this->unregister_activator_i(aname); + ACE_CHECK; + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Activator %s unregistered.\n", aname)); } - else if (bind_return != 0) + else { - ACE_ASSERT(bind_return != 0); + if (this->debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Ignoring unregister activator:%s. Unknown activator.\n", aname)); } +} + +void +ImR_Locator_i::unregister_activator_i(const char* aname) +{ + ACE_ASSERT(aname != 0); + int err = this->repository_.remove_activator (aname); + ACE_UNUSED_ARG(err); +} + +void +ImR_Locator_i::activate_server (const char* server ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + // This is the version called by tao_imr to activate the server, manually + // starting it if necessary. + activate_server_by_name(server, true ACE_ENV_ARG_PARAMETER); +} - if (OPTIONS::instance()->debug() >= 1) +char* +ImR_Locator_i::activate_server_by_name (const char* name, bool manual_start ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + // Activate the server, starting it if necessary. Don't start MANUAL + // servers unless manual_start=true + ACE_ASSERT(name != 0); + + Server_Info_Ptr info = this->repository_.get_server(name); + if (info.null()) { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Activator registered for %s.\n", activator)); + ACE_ERROR ((LM_ERROR, "ImR Locator: Cannot find info for server <%s>\n", name)); + ACE_THROW_RETURN(ImplementationRepository::NotFound (), 0); } - return info.token; + + return activate_server_i(*info, manual_start ACE_ENV_ARG_PARAMETER); } -// Remove a activator when it no longer wants to receive requests. -// object_ref is set to the removed activator. -void -ImR_Locator_i::unregister_activator (const char * activator, - CORBA::Long token - ACE_ENV_ARG_DECL_NOT_USED) - ACE_THROW_SPEC ((CORBA::SystemException)) +char* +ImR_Locator_i::activate_server_i (Server_Info& info, bool manual_start ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) { - ActivatorInfo info; - if (this->activator_map_.find (activator, info) == 0) + if (info.activation_mode == ImplementationRepository::PER_CLIENT && ! manual_start) + { + info.reset(); + } + + while(true) { - if (info.token != token && OPTIONS::instance()->debug() >= 1) + if (is_alive(info)) { - ACE_DEBUG((LM_DEBUG, "ImR Locator: Ignoring unregister activator:%s. Wrong token.\n", activator)); - return; + if (debug_ > 0) + { + ACE_DEBUG((LM_DEBUG, "ImR Locator: Successfully activated <%s> at \n\t%s\n", + info.name.c_str(), info.partial_ior.c_str())); + } + info.start_count = 0; + return CORBA::string_dup(info.partial_ior.c_str()); } - - int bind_return = this->activator_map_.unbind (activator, info); - ACE_UNUSED_ARG (bind_return); - ACE_ASSERT(bind_return == 0); - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Activator %s unregistered.\n", activator)); - } - } - else - { - if (OPTIONS::instance()->debug() >= 1) + if (info.start_count >= info.start_limit) { - ACE_DEBUG((LM_DEBUG, "ImR Locator: Ignoring unregister activator:%s. Unknown activator.\n", activator)); + break; } + + ++info.start_count; + + // Note : If the activator is already in the process of starting a server, then + // this will simply block with the others currently waiting. + start_server(info, manual_start ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(0); } + + if (this->debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Cannot Activate <%s>. Too many retries.\n", info.name.c_str())); + + ACE_THROW_RETURN (ImplementationRepository::CannotActivate + (CORBA::string_dup ("Too many retries.")), 0); +} + +char* +ImR_Locator_i::activate_server_by_object (const char* object_name ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + ACE_ASSERT(object_name != 0); + + // We assume that the first part of the object name is the server name. + // So a name of foo/bar means that the server name is foo. + ACE_CString server_name(object_name); + ssize_t pos = server_name.find ('/'); + if (pos != ACE_CString::npos) + server_name = server_name.substr(pos + 1); + + return activate_server_by_name(server_name.c_str(), false ACE_ENV_ARG_PARAMETER); } -// Starts up the server <server> at all the activators where it is -// registered, if not already running. void -ImR_Locator_i::activate_server (const char *server ACE_ENV_ARG_DECL) - ACE_THROW_SPEC (( - CORBA::SystemException, - ImplementationRepository::NotFound, - ImplementationRepository::CannotActivate)) +ImR_Locator_i::start_server(Server_Info& info, bool manual_start ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) { - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Activating server %s.\n", server)); - } + if (info.activation_mode == ImplementationRepository::MANUAL && ! manual_start) + { + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Cannot Activate MANUAL server <%s>.\n", info.name.c_str())); + ACE_THROW(ImplementationRepository::CannotActivate + (CORBA::string_dup ("MANUAL server."))); + } + if (info.cmdline.length() == 0) + { + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Cannot Activate server <%s>." + " No command line.\n", info.name.c_str())); + ACE_THROW(ImplementationRepository::CannotActivate + (CORBA::string_dup ("No command line registered for server."))); + } + + Activator_Info_Ptr ainfo = get_activator(info.activator); - ACE_CString activator; - if (this->server_map_.find(server, activator) == 0) + if (ainfo.null() || CORBA::is_nil(ainfo->activator.in())) { - this->activate_server_in_activator(server, activator.c_str()); - } - else + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Cannot Activate server <%s>. " + "Activator <%s> not found.\n", info.name.c_str(), info.activator.c_str())); + ACE_THROW(ImplementationRepository::CannotActivate + (CORBA::string_dup ("No activator registered for server."))); + } + + if (this->debug_ > 0) { - ACE_ERROR ((LM_ERROR, "ImR Locator: Couldn't find an activator for server:%s\n", server)); - ACE_THROW(ImplementationRepository::NotFound()); + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Starting server <%s>. Attempt %d/%d.\n", + info.name.c_str(), info.start_count, info.start_limit)); } -} -// Starts up the server <server> at one or more activators -// and returns the IOR of the activated server. -char * -ImR_Locator_i::activate_server_with_startup (const char *server, - int check_startup - ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, - ImplementationRepository::NotFound, - ImplementationRepository::CannotActivate)) -{ - if (OPTIONS::instance()->debug() >= 1) + ACE_TRY + { + ++ ainfo->waiting_clients; + ainfo->activator->start_server( + info.name.c_str(), + info.cmdline.c_str(), + info.dir.c_str(), + info.env_vars + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + -- ainfo->waiting_clients; + } + ACE_CATCH(CORBA::TIMEOUT, ex) + { + -- ainfo->waiting_clients; + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator : Timeout or error waiting for startup.\n")); + info.reset(); + } + ACE_CATCHANY { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Activating server %s." - " Check startup=%d.\n", server, check_startup)); + -- ainfo->waiting_clients; + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "Exception during activator communication. Activator connection broken.\n")); + if (debug_ > 1) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::start_server()"); + ainfo->reset(); + info.reset(); } + ACE_ENDTRY; +} + +void +ImR_Locator_i::server_status_changed(Server_Info& info) +{ + Activator_Info_Ptr ainfo = get_activator(info.activator); - ACE_CString activator; - if (this->server_map_.find(server, activator) == 0) + if (! ainfo.null() + && ! CORBA::is_nil(ainfo->activator.in()) + && ainfo->waiting_clients > 0 + ) { - ImplementationRepository::Administration_var admin = - this->choose_activator (activator.c_str() ACE_ENV_ARG_PARAMETER); - ACE_CHECK_RETURN (0); - char* partial_ior = admin->activate_server_with_startup (server, - check_startup ACE_ENV_ARG_PARAMETER); - ACE_CHECK_RETURN (0); - if (partial_ior != 0) { - return partial_ior; + ACE_TRY_NEW_ENV + { + ainfo->activator->server_status_changed(info.name.c_str() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; } - } - ACE_ERROR ((LM_ERROR, "ImR Locator: Couldn't find an activator for server:%s\n", server)); - ACE_THROW_RETURN (ImplementationRepository::NotFound(), 0); - return 0; + ACE_CATCHANY + { + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "Exception during activator communication. Activator connection broken.\n")); + if (debug_ > 1) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::server_status_changed()"); + ainfo->reset(); + } + ACE_ENDTRY; + } } - -// Starts up the server <server> if not already running in the -// specified activator. void -ImR_Locator_i::activate_server_in_activator (const char *server, - const char * activator - ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, - ImplementationRepository::NotFound, - ImplementationRepository::CannotActivate)) +ImR_Locator_i::set_timeout_policy(CORBA::Object_ptr obj, const ACE_Time_Value& to) { - if (OPTIONS::instance()->debug() >= 1) + ACE_TRY_NEW_ENV + { + TimeBase::TimeT timeout; + ORBSVCS_Time::Time_Value_to_TimeT (timeout, to); + CORBA::Any tmp; + tmp <<= timeout; + + CORBA::PolicyList policies(1); + policies.length(1); + policies[0] = orb_->create_policy(Messaging::RELATIVE_RT_TIMEOUT_POLICY_TYPE, tmp ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + obj->_set_policy_overrides (policies, CORBA::ADD_OVERRIDE ACE_ENV_ARG_PARAMETER); + } + ACE_CATCHANY { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Activating server" - " %s in activator %s.\n", server, activator)); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::set_timeout_policy()"); } - ImplementationRepository::Administration_var admin = - this->choose_activator (activator ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - admin->activate_server (server ACE_ENV_ARG_PARAMETER); - ACE_CHECK; + ACE_ENDTRY; } -// Adds the server to the repository and registers the startup information -// about the server <server>. void -ImR_Locator_i::register_server (const char *server, +ImR_Locator_i::register_server (const char* server, const ImplementationRepository::StartupOptions &options ACE_ENV_ARG_DECL) ACE_THROW_SPEC ((CORBA::SystemException, - -ImplementationRepository::AlreadyRegistered, + ImplementationRepository::AlreadyRegistered, ImplementationRepository::NotFound)) { - ACE_CString activator; - if (this->server_map_.find(server, activator) == 0) + register_server_i(server, options, false ACE_ENV_ARG_PARAMETER); +} + +void +ImR_Locator_i::reregister_server (const char* server, + const ImplementationRepository::StartupOptions &options + ACE_ENV_ARG_DECL ) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::AlreadyRegistered, + ImplementationRepository::NotFound)) +{ + register_server_i(server, options, true ACE_ENV_ARG_PARAMETER); +} +void +ImR_Locator_i::register_server_i (const char* server, + const ImplementationRepository::StartupOptions &options, + bool allow_updates + ACE_ENV_ARG_DECL ) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::AlreadyRegistered, + ImplementationRepository::NotFound)) +{ + ACE_ASSERT(server != 0); + + if (this->read_only_) { - ACE_THROW(ImplementationRepository::AlreadyRegistered()); - return; + ACE_DEBUG((LM_DEBUG, "ImR Locator: Cannot register server <%s> due to locked database.\n", server)); + ACE_THROW (CORBA::NO_PERMISSION ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); } - ImplementationRepository::Administration_var admin = - this->choose_activator (options.activator.in() ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - - admin->register_server (server, options ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - if (OPTIONS::instance()->debug() >= 1) + Server_Info_Ptr info = this->repository_.get_server(server); + if (info.null()) + { + if (this->debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Adding server <%s>.\n", server)); + + this->repository_.add_server (server, + options.activator.in(), + options.command_line.in (), + options.environment, + options.working_directory.in (), + options.activation, + options.start_limit < 1 ? 1 : options.start_limit); + } + else if (! allow_updates) + { + ACE_ERROR ((LM_ERROR, + "ImR Locator: Server <%s> Already Registered!\n", server)); + ACE_THROW (ImplementationRepository::AlreadyRegistered()); + } + else + { + if (info->activator.length() > 0 && info->activator != options.activator.in()) { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Registered server %s " - "in activator %s.\n", server, options.activator.in())); + ACE_ERROR ((LM_ERROR, + "ImR Locator: Server <%s> Already Registered with Activator <%s>\n", + server, info->activator.c_str())); + ACE_THROW (ImplementationRepository::AlreadyRegistered()); } - int bind_return = this->server_map_.bind (server, options.activator.in()); - ACE_UNUSED_ARG (bind_return); - ACE_ASSERT(bind_return == 0); + + if (this->debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Updating server <%s>.\n", server)); + + info->activator = options.activator.in(); + info->cmdline = options.command_line.in(); + info->env_vars = options.environment; + info->dir = options.working_directory.in(); + info->activation_mode = options.activation; + info->start_limit = options.start_limit < 1 ? 1 : options.start_limit; + info->start_count = 0; + int err = this->repository_.update_server(*info); + ACE_ASSERT(err == 0); + ACE_UNUSED_ARG(err); + } + + if (this->debug_ > 1) + { + // Note : The info var may be null + ACE_DEBUG ((LM_DEBUG, "ImR_Locator_i::register_server_i:\nServer: %s\n" + "Activator: %s\n" + "Command Line: %s\n" + "Working Directory: %s\n" + "Activation: %s\n" + "Start Limit: %d\n" + "\n", + server, + options.activator.in(), + options.command_line.in (), + options.working_directory.in (), + ImR_Utils::activationModeToString(options.activation).c_str(), + options.start_limit + )); + + for (CORBA::ULong i = 0; i < options.environment.length(); ++i) + ACE_DEBUG ((LM_DEBUG, "Environment variable %s=%s\n", + options.environment[i].name.in(), + options.environment[i].value.in())); + } } -// Updates the startup information about the server <server>. -// Can not currently be used to move a server from one activator to another, -// this simply updates the registered info. void -ImR_Locator_i::reregister_server ( - const char *server, - const ImplementationRepository::StartupOptions &options - ACE_ENV_ARG_DECL ) - ACE_THROW_SPEC ((CORBA::SystemException,ImplementationRepository::NotFound)) +ImR_Locator_i::remove_server (const char* name ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) { - ACE_CString activator; - if (this->server_map_.find(server, activator) != 0) + ACE_ASSERT(name != 0); + if (this->read_only_) { - ACE_THROW(ImplementationRepository::NotFound()); - } - if (activator.compare(options.activator.in()) != 0) - { - ACE_THROW(ImplementationRepository::NotFound()); + ACE_ERROR ((LM_ERROR, + "ImR Locator: Can't remove server <%s> due to locked database.\n", name)); + ACE_THROW (CORBA::NO_PERMISSION ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); } - ImplementationRepository::Administration_var admin = - this->choose_activator (activator.c_str() ACE_ENV_ARG_PARAMETER); - ACE_CHECK; + // Note : This will be safe, because any Server_Info_Ptr objects will still + // be valid, and the actual Server_Info will be destroyed when the last + // one goes out of scope. - if (OPTIONS::instance()->debug() >= 1) + Server_Info_Ptr info = this->repository_.get_server(name); + if (! info.null()) { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Reregister server %s " - "in activator %s.\n", server, activator.c_str())); + server_status_changed(*info); + + if (this->repository_.remove_server (name) == 0) + { + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Removed Server <%s>.\n", name)); + } + } + else + { + ACE_ERROR ((LM_ERROR, + "ImR Locator: Can't remove unknown server <%s>.\n", name)); + ACE_THROW (ImplementationRepository::NotFound ()); } - admin->reregister_server (server, options ACE_ENV_ARG_PARAMETER); - ACE_CHECK; } -// Removes the server <server> from the repository. void -ImR_Locator_i::remove_server (const char *server ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +ImR_Locator_i::shutdown_server (const char* server ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) { - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Remove server %s.\n", server)); - } - ACE_CString activator; - if (this->server_map_.find(server, activator) == 0) + ACE_ASSERT(server != 0); + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Shutting down server <%s>.\n", server)); + + Server_Info_Ptr info = this->repository_.get_server(server); + if (info.null()) { - this->remove_server_in_activator(server, activator.c_str()); - } - else + ACE_ERROR ((LM_ERROR, + "ImR Locator: shutdown_server() Cannot find info for server <%s>\n", server)); + ACE_THROW(ImplementationRepository::NotFound()); + } + + connect_server(*info); + + if (CORBA::is_nil(info->server.in())) { - ACE_ERROR ((LM_ERROR, "ImR Locator: Couldn't find an activator for server:%s\n", server)); + ACE_ERROR ((LM_ERROR, + "ImR Locator: shutdown_server() Cannot connect to server <%s>\n", server)); ACE_THROW(ImplementationRepository::NotFound()); } -} -// Removes the server <server> from the repository. -void -ImR_Locator_i::remove_server_in_activator (const char *server, - const char *activator - ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, - ImplementationRepository::NotFound - )) -{ - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Remove server %s " - "from activator %s.\n", server, activator)); - } - ACE_CString registered_activator; - if (this->server_map_.find(server, registered_activator) != 0) + ACE_TRY_NEW_ENV { - ACE_THROW(ImplementationRepository::NotFound()); // todo : Add to signature in pidl and others + ImplementationRepository::ServerObject_var server = info->server; + server->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; } - if (registered_activator.compare(activator) != 0) + ACE_CATCHANY { - ACE_ASSERT(false); + if (this->debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Exception ignored while shutting down <%s>\n", server)); } + ACE_ENDTRY; - ImplementationRepository::Administration_var admin = - this->choose_activator (activator ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - admin->remove_server (server ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - int err = this->server_map_.unbind(server); - ACE_UNUSED_ARG (err); + info->reset(); + + int err = this->repository_.update_server(*info); ACE_ASSERT(err == 0); + ACE_UNUSED_ARG(err); + + server_status_changed(*info); } -// Attempts to gracefully shut down the server, at all activators that -// it is running. void -ImR_Locator_i::shutdown_server (const char *server ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +ImR_Locator_i::server_is_running (const char* name, + const char* partial_ior, + ImplementationRepository::ServerObject_ptr server + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound)) { - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Shutdown server %s.\n", server)); - } - ACE_CString activator; - if (this->server_map_.find(server, activator) == 0) + ACE_ASSERT(name != 0); + ACE_ASSERT(partial_ior != 0); + ACE_ASSERT(! CORBA::is_nil(server)); + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Server %s is running at %s.\n", name, partial_ior)); + + set_timeout_policy(server, DEFAULT_SERVER_TIMEOUT); + + CORBA::String_var ior = orb_->object_to_string (server ACE_ENV_ARG_PARAMETER); + + Server_Info_Ptr info = this->repository_.get_server(name); + if (info.null()) { - this->shutdown_server_in_activator(server, activator.c_str()); - } - else + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Auto adding NORMAL server:<%s>\n", name)); + + ImplementationRepository::EnvironmentList env(0); + this->repository_.add_server (name, + "", // no activator + "", // no cmdline + ImplementationRepository::EnvironmentList(), + "", // no working dir + ImplementationRepository::NORMAL, + DEFAULT_START_LIMIT, + partial_ior, + ior.in(), + server + ); + } + else { - ACE_ERROR ((LM_ERROR, "ImR Locator: Couldn't find an activator for server:%s\n", server)); - ACE_THROW(ImplementationRepository::NotFound()); + info->ior = ior.in(); + info->partial_ior = partial_ior; + info->server = ImplementationRepository::ServerObject::_duplicate(server); + + int err = this->repository_.update_server(*info); + ACE_ASSERT(err == 0); + ACE_UNUSED_ARG(err); + + // Temporarily disable this optimization since it only works on Windows, due to root poa lock + // being held in the server, preventing us from calling back to the server from within this call. + //is_alive(*info); // We don't really care if it is or not, we just want to cache the result. + +#if !defined (ACE_HAS_RECURSIVE_MUTEXES) + // Schedule a timer to call server_status_changed() on this + // ImR_Locator_i. Due to locking problems within the POA, we need to + // do this after we return from this method. Status_Changed_Timer is + // allocated on the heap here, but is deleted within the + // handle_timeout() call. + Status_Changed_Timer* sct; + ACE_NEW_THROW_EX (sct, + Status_Changed_Timer (this, info), + CORBA::NO_MEMORY ()); + + ACE_Time_Value delay(0, 10000); + this->orb_->orb_core()->reactor()->schedule_timer (sct, 0, delay); +#else + server_status_changed(*info); +#endif /* ACE_HAS_RECURSIVE_MUTEXES */ } } -// Attempts to gracefully shut down the server, void -ImR_Locator_i::shutdown_server_in_activator ( - const char *server, - const char *activator - ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) -{ - ImplementationRepository::Administration_var admin = - this->choose_activator (activator ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - if (OPTIONS::instance()->debug() >= 1) +ImR_Locator_i::server_is_shutting_down (const char* server ACE_ENV_ARG_DECL_NOT_USED) +ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +{ + ACE_ASSERT(server != 0); + Server_Info_Ptr info = this->repository_.get_server(server); + if (info.null()) + { + if (this->debug_ > 1) { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Shutdown server %s " - "in activator %s.\n", server, activator)); + ACE_DEBUG((LM_DEBUG, + "ImR_Locator_i::server_is_shutting_down: Unknown server:%s\n", server)); } - admin->shutdown_server (server ACE_ENV_ARG_PARAMETER); - ACE_CHECK; -} + return; + } -void -ImR_Locator_i::server_is_running (const char *, - const char *, - ImplementationRepository::ServerObject_ptr - ACE_ENV_ARG_DECL_NOT_USED) - ACE_THROW_SPEC ((CORBA::SystemException, - ImplementationRepository::NotFound)) -{ - ACE_ERROR((LM_ERROR, "ImR_Locator_i::server_is_running() " - "This operation is only for the ImR_Activator.\n")); - ACE_ASSERT(false); -} + if (this->debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: server <%s> is shutting down.\n", server)); -void -ImR_Locator_i::server_is_running_in_activator (const char* server, - const char* activator, - const char* partial_ior, - ImplementationRepository::ServerObject_ptr server_object - ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) -{ - // todo : At this point we could automatically register the server, so that - // manually started servers don't require tao_imr add first. - ImplementationRepository::Administration_var admin = - this->choose_activator (activator ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Server %s " - "running in activator %s.\n", server, activator)); - } - admin->server_is_running (server, partial_ior, server_object ACE_ENV_ARG_PARAMETER); - ACE_CHECK; -} + info->reset(); -void -ImR_Locator_i::server_is_shutting_down (const char* ACE_ENV_ARG_DECL_NOT_USED) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) -{ - ACE_ERROR((LM_ERROR, "ImR_Locator_i::server_is_shutting_down()" - " This operation is only for the ImR_Activator.\n")); - ACE_ASSERT(false); -} + int err = this->repository_.update_server(*info); + ACE_ASSERT(err == 0); + ACE_UNUSED_ARG(err); -// What the server should call before it shuts down. -void -ImR_Locator_i::server_is_shutting_down_in_activator ( - const char *server, - const char *activator - ACE_ENV_ARG_DECL - ) ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) -{ - ImplementationRepository::Administration_var admin = - this->choose_activator (activator ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Server %s " - "shutting down in activator %s.\n", server, activator)); - } - admin->server_is_shutting_down (server ACE_ENV_ARG_PARAMETER); - ACE_CHECK; + server_status_changed(*info); } -// Find void -ImR_Locator_i::find ( - const char * server, - ImplementationRepository::ServerInformation_out info - ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +ImR_Locator_i::find (const char* server, + ImplementationRepository::ServerInformation_out imr_info + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) { - ACE_CString activator; - if (this->server_map_.find(server, activator) == 0) - { - this->find_in_activator(server, activator.c_str(), info); - } - else + ACE_ASSERT(server != 0); + ACE_NEW_THROW_EX (imr_info, ImplementationRepository::ServerInformation, CORBA::NO_MEMORY ()); + + Server_Info_Ptr info = this->repository_.get_server(server); + if (info.null()) { - ACE_ERROR ((LM_ERROR, "ImR Locator: Couldn't find an activator for server:%s\n", server)); + ACE_ERROR ((LM_ERROR, + "ImR Locator: Cannot find info for server <%s>\n", + server)); ACE_THROW(ImplementationRepository::NotFound()); } -} -void -ImR_Locator_i::find_in_activator ( - const char* server, - const char* activator, - ImplementationRepository::ServerInformation_out info - ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) -{ - ImplementationRepository::Administration_var admin = - this->choose_activator (activator ACE_ENV_ARG_PARAMETER); - ACE_CHECK; - if (OPTIONS::instance()->debug() >= 1) - { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Find server %s " - "in activator %s.\n", server, activator)); - } - admin->find(server, info ACE_ENV_ARG_PARAMETER); - ACE_CHECK; + imr_info = info->createImRServerInfo(ACE_ENV_SINGLE_ARG_PARAMETER); + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Locator: Found server %s.\n", server)); } -// Used to access the list of servers registered. May also return an -// iterator which can be used to access more than <how_many> of them. void ImR_Locator_i::list (CORBA::ULong how_many, ImplementationRepository::ServerInformationList_out server_list, @@ -708,158 +892,364 @@ ImR_Locator_i::list (CORBA::ULong how_many, ACE_ENV_ARG_DECL ) ACE_THROW_SPEC ((CORBA::SystemException)) { - if (OPTIONS::instance()->debug() >= 1) - { + if (this->debug_ > 0) ACE_DEBUG ((LM_DEBUG, "ImR Locator: List servers.\n")); + + // Initialize the out variables, so if we return early, they will + // not be dangling. + server_iterator = ImplementationRepository::ServerInformationIterator::_nil(); + ACE_NEW_THROW_EX (server_list, + ImplementationRepository::ServerInformationList(0), CORBA::NO_MEMORY()); + + Locator_Repository::SIMap::ENTRY* entry = 0; + Locator_Repository::SIMap::ITERATOR it(this->repository_.servers()); + + // Number of servers that will go into the server_list. + CORBA::ULong n = this->repository_.servers().current_size(); + if (how_many > 0 && n > how_many) + { + n = how_many; } - ActivatorMap::ENTRY *next_entry = 0; - int cnt = 0; - for (ActivatorMap::ITERATOR iterator (this->activator_map_); - iterator.next (next_entry) != 0; - iterator.advance ()) + server_list->length(n); + + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR_Locator_i::list: Filling ServerList with %d servers\n", n)); + + for (CORBA::ULong i = 0; i < n; i++) { - ImplementationRepository::Administration_ptr admin = next_entry->int_id_.admin.in(); - ++cnt; - // todo : Check to make sure activator implementation supports repeat calls correctly. - admin->list (how_many, - server_list, - server_iterator - ACE_ENV_ARG_PARAMETER); - ACE_CHECK; + it.next(entry); + it.advance(); + ACE_ASSERT(entry != 0); + + Server_Info_Ptr info = entry->int_id_; + + ImplementationRepository::ServerInformation_var imr_info = info->createImRServerInfo(ACE_ENV_SINGLE_ARG_PARAMETER); + server_list[i] = *imr_info; } - if (cnt <= 0) + if (this->repository_.servers().current_size() > n) { - // Temporary fix for the seg fault that occurs when the skel tries to - // handle the unitialised sequence when this method is called and - // no activator has been registered yet. - // @todo A full rework of this method is needed - see bug #1543. - server_iterator = - ImplementationRepository::ServerInformationIterator::_nil (); - ACE_NEW_THROW_EX (server_list, - ImplementationRepository::ServerInformationList (0), + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR_Locator_i::list: Creating ServerInformation Iterator\n")); + + ImR_Iterator* imr_iter; + + ACE_NEW_THROW_EX (imr_iter, + ImR_Iterator (n, this->repository_, this->imr_poa_.in()), CORBA::NO_MEMORY ()); + + PortableServer::ServantBase_var tmp(imr_iter); + + ACE_TRY + { + PortableServer::ObjectId_var id = + this->imr_poa_->activate_object (imr_iter ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + CORBA::Object_var obj = this->imr_poa_->id_to_reference(id.in() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + server_iterator = ImplementationRepository:: + ServerInformationIterator::_narrow(obj.in() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK; } } -ImplementationRepository::Administration_ptr -ImR_Locator_i::choose_activator (const char *activator ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((ImplementationRepository::NotFound, CORBA::SystemException)) +Activator_Info_Ptr +ImR_Locator_i::get_activator (const ACE_CString& aname) { - ActivatorInfo info; - if (this->activator_map_.find (activator, info) != 0) + Activator_Info_Ptr info = this->repository_.get_activator (aname); + if (! info.null()) + { + this->connect_activator (*info); + } + return info; +} + +void +ImR_Locator_i::connect_activator (Activator_Info& info) +{ + if (! CORBA::is_nil(info.activator.in()) || info.ior.length() == 0) + return; + + ACE_TRY_NEW_ENV + { + CORBA::Object_var obj = + this->orb_->string_to_object (info.ior.c_str() + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil(obj.in())) { - ACE_THROW_RETURN (ImplementationRepository::NotFound (), 0); + info.reset(); + return; } - return info.admin._retn(); + + info.activator = + ImplementationRepository::Activator::_narrow (obj.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil(info.activator.in())) + { + info.reset(); + return; + } + + set_timeout_policy(info.activator.in(), startup_timeout_); + + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Locator: reconnected to activator <%s>\n", info.name.c_str())); + } + ACE_CATCHANY + { + info.reset(); + } + ACE_ENDTRY; } -char * -ImR_Locator_i::find_ior (const char *object_name ACE_ENV_ARG_DECL) - ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +void +ImR_Locator_i::auto_start_servers(ACE_ENV_SINGLE_ARG_DECL) { - if (OPTIONS::instance()->debug() >= 1) + if (this->repository_.servers().current_size() == 0) + return; + + Locator_Repository::SIMap::ENTRY* server_entry; + Locator_Repository::SIMap::ITERATOR server_iter(this->repository_.servers()); + + // For each of the entries in the Locator_Repository, get the startup + // information and activate the servers, if they are not already + // running. + for (;server_iter.next(server_entry) != 0; server_iter.advance()) + { + Server_Info_Ptr info = server_entry->int_id_; + ACE_ASSERT(! info.null()); + + ACE_TRY + { + if (info->activation_mode == ImplementationRepository::AUTO_START + && info->cmdline.length() > 0) + { + this->activate_server_i (*info, true ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Find ior %s.\n", object_name)); + if (this->debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR_Locator_i::run: AUTO_START Could not activate <%s>\n", + server_entry->ext_id_.c_str ())); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "AUTO_START"); + } + // Ignore exceptions } + ACE_ENDTRY; + ACE_CHECK; + } +} + +void +ImR_Locator_i::connect_server(Server_Info& info) +{ + if (! CORBA::is_nil(info.server.in()) || info.ior.length() == 0) + return; + + ACE_TRY_NEW_ENV + { + CORBA::Object_var obj = orb_->string_to_object (info.ior.c_str() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; - ActivatorMap::ENTRY *next_entry = 0; - - for (ActivatorMap::ITERATOR iterator (this->activator_map_); - iterator.next (next_entry) != 0; - iterator.advance ()) + if (CORBA::is_nil(obj.in())) { - ImplementationRepository::Administration_ptr admin = next_entry->int_id_.admin.in(); - ACE_TRY - { - char* ior = admin->find_ior (object_name ACE_ENV_ARG_PARAMETER); - ACE_TRY_CHECK; + info.reset(); + return; + } - return ior; - } - ACE_CATCH (ImplementationRepository::NotFound, ex) - { - ACE_UNUSED_ARG(ex); - } - ACE_ENDTRY; + info.server = + ImplementationRepository::ServerObject::_narrow (obj.in() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil(info.server.in())) + { + info.reset(); + return; } - - ACE_ERROR ((LM_ERROR, "ImR Locator: Couldn't find an activator for object:%s\n", object_name)); - ACE_THROW_RETURN (ImplementationRepository::NotFound (), 0); - return 0; + + set_timeout_policy(info.server.in(), DEFAULT_SERVER_TIMEOUT); + + if (debug_) + ACE_DEBUG((LM_DEBUG, "ImR Locator: Reconnected server <%s>\n", info.name.c_str())); + } + ACE_CATCHANY + { + info.reset(); + } + ACE_ENDTRY; +} + +bool +ImR_Locator_i::is_alive(Server_Info& info) +{ + for (int i = 0; i < IS_ALIVE_RETRY_COUNT; ++i) + { + int status = this->is_alive_i(info); + if (status == 0) + return false; + if (status == 1) + return true; + + // This is evil, but there's not much else we can do for now. We should never + // reach this code once the ImR Servers are fixed so that they don't lie about + // server_is_running. Currently, they send this notification during poa creation. + // We have to run the orb, because the very thing that may be slowing the + // aliveness of the servers is the fact that they're trying to register more + // objects with us. + ACE_Time_Value tv = IS_ALIVE_RETRY_INTERVAL; + this->orb_->run(tv); + } + if (debug_ > 0) + { + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> is_alive() retry count exceeded. alive=false.\n", info.name.c_str())); + } + // We return true here, because the server *might* be alive, it's just not starting in a timely + // manner. We can't return false, because then we'll just try to start another instance, and the + // same thing will likely happen. + info.last_ping = ACE_OS::gettimeofday(); + return true; } -void ImR_Locator_i::shutdown_repo (ACE_ENV_SINGLE_ARG_DECL) - ACE_THROW_SPEC ( (CORBA::SystemException) ) +int +ImR_Locator_i::is_alive_i(Server_Info& info) { - if (OPTIONS::instance()->debug() >= 1) + // This is used by the ACE_TRY below when exceptions are turned off. + ACE_DECLARE_NEW_CORBA_ENV; + + if (info.ior.length() == 0 || info.partial_ior.length() == 0) + { + if (debug_ > 1) + { + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> not running. alive=false.\n", info.name.c_str())); + } + info.last_ping = ACE_Time_Value::zero; + return 0; + } + + if (ping_interval_ == ACE_Time_Value::zero) + { + if (debug_ > 1) + { + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> Ping verification disabled. alive=true.\n", info.name.c_str())); + } + return 1; + } + + if (ACE_OS::gettimeofday() - info.last_ping < ping_interval_) + { + if (debug_ > 1) { - ACE_DEBUG ((LM_DEBUG, "ImR Locator: Shutting down repository\n")); + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> within ping interval. alive=true.\n", info.name.c_str())); } + return 1; + } + + connect_server(info); - ActivatorMap::ENTRY *next_entry = 0; - - for (ActivatorMap::ITERATOR iterator (this->activator_map_); - iterator.next (next_entry) != 0; - iterator.advance ()) + if (CORBA::is_nil (info.server.in())) + { + if (debug_ > 1) { - ImplementationRepository::Administration_ptr admin_ref = next_entry->int_id_.admin.in();; + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> Could not connect. alive=false.\n", info.name.c_str())); + } + return 0; + } + + ACE_TRY + { + // Make a copy, in case the info is updated during the ping. + ImplementationRepository::ServerObject_var server = info.server; + + // This will timeout if it takes too long + server->ping (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; - ACE_TRY + if (debug_ > 1) + { + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> Ping successfull. alive=true\n", info.name.c_str())); + } + info.last_ping = ACE_OS::gettimeofday(); + } + ACE_CATCH(CORBA::TRANSIENT, ex) + { + const CORBA::ULong BITS_5_THRU_12_MASK = 0x00000f80; + switch (ex.minor() & BITS_5_THRU_12_MASK) + { + case TAO_INVOCATION_SEND_REQUEST_MINOR_CODE: + { + if (debug_ > 1) { - admin_ref->shutdown_repo (ACE_ENV_SINGLE_ARG_PARAMETER); - ACE_TRY_CHECK; + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> Local TRANSIENT. alive=false.\n", info.name.c_str())); } - ACE_CATCH (ImplementationRepository::NotFound, ex) + } + info.last_ping = ACE_Time_Value::zero; + return 0; + case TAO_POA_DISCARDING: + case TAO_POA_HOLDING: + { + if (debug_ > 1) { - ACE_UNUSED_ARG(ex); + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> Remote TRANSIENT. alive=maybe.\n", info.name.c_str())); } - ACE_ENDTRY; + } + return -1; // We keep trying to ping, because returning 1 now, would just lead + // to clients getting the same exception. If we can't ping after several + // attempts, then we'll give up and return 1, letting the client worry about it. + default: + ACE_ERROR ((LM_ERROR, + "ImR_Activator_i::is_alive(): <%s> unexpected TRANSIENT minor code (%d). alive=false\n", + info.name.c_str(), ex.minor())); + info.last_ping = ACE_Time_Value::zero; + return 0; + } + } + ACE_CATCH(CORBA::TIMEOUT, ex) + { + if (debug_ > 1) + { + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> Ping timed out. alive=true.\n", info.name.c_str())); + } + return -1; // See above. + } + ACE_CATCHANY + { + if (debug_ > 1) + { + ACE_DEBUG((LM_DEBUG, + "ImR Locator: <%s> Ping exception. alive=false.\n")); } - - // Finally shutdown the ORB. - // - orb_->shutdown (0) ; + info.last_ping = ACE_Time_Value::zero; + return false; + } + ACE_ENDTRY; + return 1; } #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) -template class ACE_Hash_Map_Manager<ACE_CString, ActivatorInfo, ACE_Null_Mutex>; -template class ACE_Hash_Map_Manager_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator<ACE_CString, ActivatorInfo, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Entry<ACE_CString, ActivatorInfo>; -template class ACE_Hash_Map_Reverse_Iterator<ACE_CString, ActivatorInfo, ACE_Null_Mutex>; -template class ACE_Hash_Map_Reverse_Iterator_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator_Base_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; - -template class ACE_Hash_Map_Manager<ACE_CString, ACE_CString, ACE_Null_Mutex>; -template class ACE_Hash_Map_Manager_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator<ACE_CString, ACE_CString, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Entry<ACE_CString, ACE_CString>; -template class ACE_Hash_Map_Reverse_Iterator<ACE_CString, ACE_CString, ACE_Null_Mutex>; -template class ACE_Hash_Map_Reverse_Iterator_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; -template class ACE_Hash_Map_Iterator_Base_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex>; - #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) - -#pragma instantiate ACE_Hash_Map_Manager<ACE_CString,ActivatorInfo,ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Manager_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator<ACE_CString,ActivatorInfo,ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Entry<ACE_CString, ActivatorInfo> -#pragma instantiate ACE_Hash_Map_Reverse_Iterator<ACE_CString, ActivatorInfo, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<ACE_CString, ActivatorInfo, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> - -#pragma instantiate ACE_Hash_Map_Manager<ACE_CString,ACE_CString,ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Manager_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator<ACE_CString,ACE_CString,ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Entry<ACE_CString, ACE_CString> -#pragma instantiate ACE_Hash_Map_Reverse_Iterator<ACE_CString, ACE_CString, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> -#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<ACE_CString, ACE_CString, ACE_Hash<ACE_CString>, ACE_Equal_To<ACE_CString>, ACE_Null_Mutex> - -#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION*/ |