ImR_Locator_i.cpp

Go to the documentation of this file.
00001 // ImR_Locator_i.cpp,v 1.33 2006/03/16 15:53:35 sjiang Exp
00002 
00003 #include "ImR_Locator_i.h"
00004 #include "utils.h"
00005 #include "Iterator.h"
00006 #include "INS_Locator.h"
00007 
00008 #include "orbsvcs/Time_Utilities.h"
00009 
00010 #include "tao/IORTable/IORTable.h"
00011 #include "tao/PortableServer/PortableServer.h"
00012 #include "tao/ORB_Core.h"
00013 #include "tao/default_ports.h"
00014 #include "tao/Messaging/Messaging.h"
00015 #include "tao/AnyTypeCode/Any.h"
00016 
00017 #include "ace/ARGV.h"
00018 #include "ace/OS_NS_sys_time.h"
00019 #include "ace/Vector_T.h"
00020 
00021 static const int DEFAULT_START_LIMIT = 1;
00022 
00023 static const int PING_RETRY_SCHEDULE[] = {0, 10, 100, 500, 1000, 1000, 1000, 1000, 5000, 5000};
00024 
00025 static const ACE_Time_Value DEFAULT_SERVER_TIMEOUT (0, 10 * 1000); // 10ms
00026 // We want to give shutdown a little more time to work, so that we
00027 // can guarantee to the tao_imr utility that it has shutdown. The tao_imr
00028 // utility prints a different message depending on whether shutdown succeeds
00029 // or times out.
00030 static const ACE_Time_Value DEFAULT_SHUTDOWN_TIMEOUT (0, 5000 * 1000);
00031 
00032 static PortableServer::POA_ptr
00033 createPersistentPOA (PortableServer::POA_ptr root_poa, const char* poa_name ACE_ENV_ARG_DECL) {
00034 
00035   PortableServer::LifespanPolicy_var life =
00036     root_poa->create_lifespan_policy (PortableServer::PERSISTENT ACE_ENV_ARG_PARAMETER);
00037   ACE_CHECK_RETURN (PortableServer::POA::_nil ());
00038 
00039   PortableServer::IdAssignmentPolicy_var assign =
00040     root_poa->create_id_assignment_policy (PortableServer::USER_ID ACE_ENV_ARG_PARAMETER);
00041   ACE_CHECK_RETURN (PortableServer::POA::_nil ());
00042 
00043   CORBA::PolicyList pols;
00044   pols.length (2);
00045   pols[0] = PortableServer::LifespanPolicy::_duplicate (life.in ());
00046   pols[1] = PortableServer::IdAssignmentPolicy::_duplicate (assign.in ());
00047 
00048   PortableServer::POAManager_var mgr = root_poa->the_POAManager ();
00049   PortableServer::POA_var poa =
00050     root_poa->create_POA (poa_name, mgr.in (), pols ACE_ENV_ARG_PARAMETER);
00051   ACE_CHECK_RETURN (PortableServer::POA::_nil ());
00052 
00053   life->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
00054   ACE_CHECK_RETURN (PortableServer::POA::_nil ());
00055   assign->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
00056   ACE_CHECK_RETURN (PortableServer::POA::_nil ());
00057 
00058   return poa._retn ();
00059 }
00060 
00061 ImR_Locator_i::ImR_Locator_i (void)
00062   : forwarder_ (*this)
00063   , ins_locator_ (0)
00064   , debug_ (0)
00065   , read_only_ (false)
00066 {
00067   // Visual C++ 6.0 is not smart enough to do a direct assignment
00068   // while allocating the INS_Locator.  So, we have to do it in
00069   // two steps.
00070   INS_Locator* locator;
00071   ACE_NEW (locator,
00072           INS_Locator (*this));
00073   ins_locator_ = locator;
00074 }
00075 
00076 ImR_Locator_i::~ImR_Locator_i (void)
00077 {
00078   // For some reason g++ 4.0 needs this out-of-line destructor instead
00079   // of the default one generated by the compiler.  Without this
00080   // destructor, we get a number of "undefined reference" link errors
00081   // related to the virtual tables of the INS_Locator, ImR_Adapter and
00082   // ImR_Forwarder members in this class.
00083 }
00084 
00085 int
00086 ImR_Locator_i::init_with_orb (CORBA::ORB_ptr orb, Options& opts ACE_ENV_ARG_DECL)
00087 {
00088   orb_ = CORBA::ORB::_duplicate (orb);
00089   debug_ = opts.debug ();
00090   read_only_ = opts.readonly ();
00091   startup_timeout_ = opts.startup_timeout ();
00092   ping_interval_ = opts.ping_interval ();
00093 
00094   CORBA::Object_var obj =
00095     this->orb_->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER);
00096   ACE_CHECK_RETURN (-1);
00097   this->root_poa_ = PortableServer::POA::_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
00098   ACE_CHECK_RETURN (-1);
00099   ACE_ASSERT (! CORBA::is_nil (this->root_poa_.in ()));
00100 
00101   this->forwarder_.init (orb ACE_ENV_ARG_PARAMETER);
00102   this->adapter_.init (& this->forwarder_);
00103 
00104   // Register the Adapter_Activator reference to be the RootPOA's
00105   // Adapter Activator.
00106   root_poa_->the_activator (&this->adapter_ ACE_ENV_ARG_PARAMETER);
00107   ACE_CHECK_RETURN (-1);
00108 
00109   // Use a persistent POA so that any IOR
00110   this->imr_poa_ = createPersistentPOA (this->root_poa_.in (),
00111                                         "ImplRepo_Service" ACE_ENV_ARG_PARAMETER);
00112   ACE_CHECK_RETURN (-1);
00113   ACE_ASSERT (! CORBA::is_nil (this->imr_poa_.in ()));
00114 
00115   waiter_svt_.debug (debug_ > 1);
00116   PortableServer::ObjectId_var id = PortableServer::string_to_ObjectId ("ImR_AsyncStartupWaiter");
00117   this->imr_poa_->activate_object_with_id (id.in (), &waiter_svt_ ACE_ENV_ARG_PARAMETER);
00118   ACE_CHECK_RETURN (-1);
00119   obj = this->imr_poa_->id_to_reference (id.in () ACE_ENV_ARG_PARAMETER);
00120   ACE_CHECK_RETURN (-1);
00121   if (startup_timeout_ > ACE_Time_Value::zero)
00122     {
00123       obj = set_timeout_policy (obj.in (), startup_timeout_);
00124     }
00125   waiter_ = ImplementationRepository::AsyncStartupWaiter::_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
00126   ACE_CHECK_RETURN (-1);
00127 
00128   id = PortableServer::string_to_ObjectId ("ImplRepo_Service");
00129   this->imr_poa_->activate_object_with_id (id.in (), this ACE_ENV_ARG_PARAMETER);
00130   ACE_CHECK_RETURN (-1);
00131 
00132   obj = this->imr_poa_->id_to_reference (id.in () ACE_ENV_ARG_PARAMETER);
00133   ACE_CHECK_RETURN (-1);
00134   CORBA::String_var ior = this->orb_->object_to_string (obj.in () ACE_ENV_ARG_PARAMETER);
00135   ACE_CHECK_RETURN (-1);
00136 
00137   // Register the ImR for use with INS
00138   obj = orb->resolve_initial_references ("IORTable" ACE_ENV_ARG_PARAMETER);
00139   ACE_CHECK_RETURN (-1);
00140   IORTable::Table_var ior_table = IORTable::Table::_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
00141   ACE_CHECK_RETURN (-1);
00142   ACE_ASSERT (! CORBA::is_nil (ior_table.in ()));
00143   ior_table->bind ("ImplRepoService", ior.in () ACE_ENV_ARG_PARAMETER);
00144   ACE_CHECK_RETURN (-1);
00145   ior_table->bind ("ImR", ior.in () ACE_ENV_ARG_PARAMETER);
00146   ACE_CHECK_RETURN (-1);
00147   ior_table->set_locator (this->ins_locator_.in () ACE_ENV_ARG_PARAMETER);
00148   ACE_CHECK_RETURN (-1);
00149 
00150   // Set up multicast support (if enabled)
00151   if (opts.multicast ())
00152     {
00153       ACE_Reactor* reactor = orb->orb_core ()->reactor ();
00154       if (this->setup_multicast (reactor, ior.in ()) != 0)
00155         return -1;
00156     }
00157 
00158   // Initialize the persistent storage. This will load any values that
00159   // may have been persisted before.
00160   // The init can return 1 if there is no persistent file yet. In
00161   // that case, we need not do anything for now.
00162   int init_result =
00163     this->repository_.init (opts);
00164   if (init_result == -1)
00165     {
00166       ACE_ERROR_RETURN ((LM_ERROR, "Repository failed to initialize\n"), -1);
00167     }
00168 
00169   // Activate the two poa managers
00170   PortableServer::POAManager_var poaman =
00171     this->root_poa_->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
00172   ACE_CHECK_RETURN (-1);
00173   poaman->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
00174   ACE_CHECK_RETURN (-1);
00175   poaman = this->imr_poa_->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER);
00176   ACE_CHECK_RETURN (-1);
00177   poaman->activate (ACE_ENV_SINGLE_ARG_PARAMETER);
00178   ACE_CHECK_RETURN (-1);
00179 
00180   // We write the ior file last so that the tests can know we are ready.
00181   if (opts.ior_filename ().length () > 0)
00182     {
00183       FILE* fp = ACE_OS::fopen (opts.ior_filename ().c_str (), "w");
00184       if (fp == 0)
00185         {
00186           ACE_ERROR_RETURN ((LM_ERROR,
00187                              "ImR: Could not open file: %s\n", opts.ior_filename ().c_str ()), -1);
00188         }
00189       ACE_OS::fprintf (fp, "%s", ior.in ());
00190       ACE_OS::fclose (fp);
00191     }
00192 
00193   return 0;
00194 }
00195 
00196 int
00197 ImR_Locator_i::init (Options& opts ACE_ENV_ARG_DECL)
00198 {
00199   ACE_CString cmdline = opts.cmdline ();
00200   cmdline += " -orbcollocation no -orbuseimr 0";
00201   ACE_ARGV av (cmdline.c_str ());
00202   int argc = av.argc ();
00203   char** argv = av.argv ();
00204 
00205   CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "TAO_ImR_Locator" ACE_ENV_ARG_PARAMETER);
00206   ACE_CHECK_RETURN (-1);
00207   int err = this->init_with_orb (orb.in (), opts ACE_ENV_ARG_PARAMETER);
00208   ACE_CHECK_RETURN (-1);
00209   return err;
00210 }
00211 
00212 int
00213 ImR_Locator_i::run (ACE_ENV_SINGLE_ARG_DECL)
00214 {
00215   if (debug_ > 0)
00216     {
00217       ACE_DEBUG ((LM_DEBUG, "Implementation Repository: Running\n"
00218                   "\tPing Interval : %dms\n"
00219                   "\tStartup Timeout : %ds\n"
00220                   "\tPersistence : %s\n"
00221                   "\tMulticast : %s\n"
00222                   "\tDebug : %d\n"
00223                   "\tLocked : %s\n\n",
00224                   ping_interval_.msec (),
00225                   startup_timeout_.sec (),
00226                   repository_.repo_mode (),
00227                   ior_multicast_.reactor () != 0 ? "Enabled" : "Disabled",
00228                   debug (),
00229                   read_only_ ? "True" : "False"));
00230     }
00231   this->auto_start_servers (ACE_ENV_SINGLE_ARG_PARAMETER);
00232   ACE_CHECK_RETURN (-1);
00233 
00234   this->orb_->run (ACE_ENV_SINGLE_ARG_PARAMETER);
00235   ACE_CHECK_RETURN (-1);
00236   return 0;
00237 }
00238 
00239 void
00240 ImR_Locator_i::shutdown (CORBA::Boolean activators, CORBA::Boolean servers ACE_ENV_ARG_DECL)
00241                         ACE_THROW_SPEC ((CORBA::SystemException))
00242 {
00243   if (servers != 0 && this->repository_.servers ().current_size () > 0)
00244     {
00245       // Note : shutdown is oneway, so we can't throw
00246       ACE_ERROR ((LM_ERROR, "ImR: Shutdown of all servers not implemented.\n"));
00247     }
00248   if (activators != 0 && this->repository_.activators ().current_size () > 0)
00249     {
00250       ACE_Vector<ImplementationRepository::Activator_var> acts;
00251       Locator_Repository::AIMap::ENTRY* entry = 0;
00252       Locator_Repository::AIMap::ITERATOR it (this->repository_.activators ());
00253       for (;it.next (entry) != 0; it.advance ())
00254         {
00255           Activator_Info_Ptr info = entry->int_id_;
00256           ACE_ASSERT (! info.null ());
00257           connect_activator (*info);
00258           if (! CORBA::is_nil (info->activator.in ()))
00259             acts.push_back (info->activator);
00260         }
00261 
00262       int shutdown_errs = 0;
00263 
00264       for (size_t i = 0; i < acts.size (); ++i)
00265         {
00266           ACE_TRY
00267             {
00268               acts[i]->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER);
00269               ACE_TRY_CHECK;
00270               acts[i] = ImplementationRepository::Activator::_nil ();
00271             }
00272           ACE_CATCHANY
00273             {
00274               ++shutdown_errs;
00275               if (debug_ > 1)
00276                 {
00277                   ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR: shutdown activator");
00278                 }
00279             }
00280           ACE_ENDTRY;
00281           ACE_CHECK;
00282         }
00283       if (debug_ > 0 && shutdown_errs > 0)
00284         {
00285           ACE_DEBUG ((LM_DEBUG, "ImR: Some activators could not be shut down.\n"));
00286         }
00287     }
00288   // Technically, we should wait for all the activators to unregister, but
00289   // ,for now at least, it doesn't seem worth it.
00290   shutdown (false ACE_ENV_ARG_PARAMETER);
00291 }
00292 
00293 void
00294 ImR_Locator_i::shutdown (bool wait_for_completion ACE_ENV_ARG_DECL)
00295 {
00296   this->orb_->shutdown (wait_for_completion ACE_ENV_ARG_PARAMETER);
00297 }
00298 
00299 int
00300 ImR_Locator_i::fini (ACE_ENV_SINGLE_ARG_DECL)
00301 {
00302   ACE_TRY
00303     {
00304       if (debug_ > 1)
00305         ACE_DEBUG ((LM_DEBUG, "ImR: Shutting down...\n"));
00306 
00307       teardown_multicast ();
00308 
00309       this->root_poa_->destroy (1, 1 ACE_ENV_ARG_PARAMETER);
00310       ACE_TRY_CHECK;
00311 
00312       this->orb_->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
00313       ACE_TRY_CHECK;
00314 
00315       if (debug_ > 0)
00316         ACE_DEBUG ((LM_DEBUG, "ImR: Shut down successfully.\n"));
00317     }
00318   ACE_CATCHANY
00319     {
00320       ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::fini");
00321       ACE_RE_THROW;
00322     }
00323   ACE_ENDTRY;
00324   ACE_CHECK_RETURN (-1);
00325   return 0;
00326 }
00327 
00328 void
00329 ImR_Locator_i::teardown_multicast ()
00330 {
00331   ACE_Reactor* r = ior_multicast_.reactor ();
00332   if (r != 0) {
00333     r->remove_handler (&ior_multicast_, ACE_Event_Handler::READ_MASK);
00334     ior_multicast_.reactor (0);
00335   }
00336 }
00337 
00338 int
00339 ImR_Locator_i::setup_multicast (ACE_Reactor* reactor, const char* ior)
00340 {
00341   ACE_ASSERT (reactor != 0);
00342   ACE_ASSERT (ior != 0);
00343 #if defined (ACE_HAS_IP_MULTICAST)
00344 
00345   TAO_ORB_Core* core = TAO_ORB_Core_instance ();
00346   // See if the -ORBMulticastDiscoveryEndpoint option was specified.
00347   ACE_CString mde (core->orb_params ()->mcast_discovery_endpoint ());
00348 
00349   if (mde.length () != 0)
00350     {
00351       if (this->ior_multicast_.init (ior,
00352                                      mde.c_str (), TAO_SERVICEID_IMPLREPOSERVICE) == -1)
00353         {
00354           return -1;
00355         }
00356     }
00357   else
00358     {
00359       // Port can be specified as param, env var, or default
00360       CORBA::UShort port =
00361         core->orb_params ()->service_port (TAO::MCAST_IMPLREPOSERVICE);
00362       if (port == 0)
00363         {
00364           // Check environment var. for multicast port.
00365           const char* port_number = ACE_OS::getenv ("ImplRepoServicePort");
00366 
00367           if (port_number != 0)
00368             port = static_cast<CORBA::UShort> (ACE_OS::atoi (port_number));
00369         }
00370       if (port == 0)
00371         port = TAO_DEFAULT_IMPLREPO_SERVER_REQUEST_PORT;
00372 
00373       if (this->ior_multicast_.init (ior, port,
00374                                      ACE_DEFAULT_MULTICAST_ADDR, TAO_SERVICEID_IMPLREPOSERVICE) == -1)
00375         {
00376           return -1;
00377         }
00378     }
00379 
00380   // Register event handler for the ior multicast.
00381   if (reactor->register_handler (&this->ior_multicast_,
00382                                  ACE_Event_Handler::READ_MASK) == -1)
00383     {
00384       if (debug_ >= 1)
00385         ACE_DEBUG ((LM_DEBUG, "ImR: cannot register Event handler\n"));
00386       return -1;
00387     }
00388 #else /* ACE_HAS_IP_MULTICAST*/
00389   ACE_UNUSED_ARG (reactor);
00390   ACE_UNUSED_ARG (ior);
00391 #endif /* ACE_HAS_IP_MULTICAST*/
00392   return 0;
00393 }
00394 
00395 CORBA::Long
00396 ImR_Locator_i::register_activator (const char* aname,
00397                                    ImplementationRepository::Activator_ptr activator
00398                                    ACE_ENV_ARG_DECL)
00399                                    ACE_THROW_SPEC ((CORBA::SystemException))
00400 {
00401   ACE_ASSERT (aname != 0);
00402   ACE_ASSERT (! CORBA::is_nil (activator));
00403 
00404   // Before we can register the activator, we need to ensure that any existing
00405   // registration is purged.
00406   this->unregister_activator_i (aname);
00407   ACE_CHECK_RETURN (0);
00408 
00409   CORBA::String_var ior =
00410     this->orb_->object_to_string (activator ACE_ENV_ARG_PARAMETER);
00411   ACE_CHECK_RETURN (-1);
00412 
00413   CORBA::Long token = ACE_OS::gettimeofday ().msec ();
00414 
00415   int err = this->repository_.add_activator (aname, token, ior.in (), activator);
00416   ACE_ASSERT (err == 0);
00417   ACE_UNUSED_ARG (err);
00418 
00419   if (this->debug_ > 0)
00420     ACE_DEBUG ((LM_DEBUG, "ImR: Activator registered for %s.\n", aname));
00421 
00422   return token;
00423 }
00424 
00425 void
00426 ImR_Locator_i::unregister_activator (const char* aname,
00427                                      CORBA::Long token
00428                                      ACE_ENV_ARG_DECL)
00429                                      ACE_THROW_SPEC ((CORBA::SystemException))
00430 {
00431   ACE_ASSERT (aname != 0);
00432   Activator_Info_Ptr info = this->get_activator (aname);
00433 
00434   if (! info.null ())
00435     {
00436       if (info->token != token && this->debug_ > 0)
00437         {
00438           ACE_DEBUG ((LM_DEBUG, "ImR: Ignoring unregister activator:%s. Wrong token.\n", aname));
00439           return;
00440         }
00441 
00442       this->unregister_activator_i (aname);
00443       ACE_CHECK;
00444 
00445       if (this->debug_ > 0)
00446         ACE_DEBUG ((LM_DEBUG, "ImR: Activator %s unregistered.\n", aname));
00447     }
00448   else
00449     {
00450       if (this->debug_ > 0)
00451         ACE_DEBUG ((LM_DEBUG, "ImR: Ignoring unregister activator:%s. Unknown activator.\n", aname));
00452     }
00453 }
00454 
00455 void
00456 ImR_Locator_i::unregister_activator_i (const char* aname)
00457 {
00458   ACE_ASSERT (aname != 0);
00459   int err = this->repository_.remove_activator (aname);
00460   ACE_UNUSED_ARG (err);
00461 }
00462 
00463 void
00464 ImR_Locator_i::notify_child_death (const char* name ACE_ENV_ARG_DECL_NOT_USED)
00465 ACE_THROW_SPEC ((CORBA::SystemException))
00466 {
00467   ACE_ASSERT (name != 0);
00468 
00469   if (this->debug_ > 1)
00470     ACE_DEBUG ((LM_DEBUG, "ImR: Server has died <%s>.\n", name));
00471 
00472   Server_Info_Ptr info = this->repository_.get_server (name);
00473   if (! info.null ())
00474     {
00475       info->ior = "";
00476       info->partial_ior = "";
00477 
00478       int err = this->repository_.update_server (*info);
00479       ACE_ASSERT (err == 0);
00480       ACE_UNUSED_ARG (err);
00481     }
00482   else
00483     {
00484       if (this->debug_ > 1)
00485         ACE_DEBUG ((LM_DEBUG,
00486                     "ImR: Failed to find server in repository.\n"));
00487     }
00488 }
00489 
00490 void
00491 ImR_Locator_i::activate_server (const char* server ACE_ENV_ARG_DECL)
00492 ACE_THROW_SPEC ((CORBA::SystemException,
00493                 ImplementationRepository::NotFound,
00494                 ImplementationRepository::CannotActivate))
00495 {
00496   if (debug_ > 1)
00497     ACE_DEBUG ((LM_DEBUG, "ImR: Manually activating server <%s>\n", server));
00498 
00499   // This is the version called by tao_imr to activate the server, manually
00500   // starting it if necessary.
00501   activate_server_by_name (server, true ACE_ENV_ARG_PARAMETER);
00502 }
00503 
00504 char*
00505 ImR_Locator_i::activate_server_by_name (const char* name, bool manual_start ACE_ENV_ARG_DECL)
00506 ACE_THROW_SPEC ((CORBA::SystemException,
00507                 ImplementationRepository::NotFound,
00508                 ImplementationRepository::CannotActivate))
00509 {
00510   // Activate the server, starting it if necessary. Don't start MANUAL
00511   // servers unless manual_start=true
00512   ACE_ASSERT (name != 0);
00513 
00514   Server_Info_Ptr info = this->repository_.get_server (name);
00515   if (info.null ())
00516     {
00517       ACE_ERROR ((LM_ERROR, "ImR: Cannot find info for server <%s>\n", name));
00518       ACE_THROW_RETURN (ImplementationRepository::NotFound (), 0);
00519     }
00520 
00521   return activate_server_i (*info, manual_start ACE_ENV_ARG_PARAMETER);
00522 }
00523 
00524 char*
00525 ImR_Locator_i::activate_server_by_object (const char* object_name ACE_ENV_ARG_DECL)
00526 ACE_THROW_SPEC ((CORBA::SystemException,
00527                 ImplementationRepository::NotFound,
00528                 ImplementationRepository::CannotActivate))
00529 {
00530   ACE_ASSERT (object_name != 0);
00531 
00532   // We assume that the first part of the object name is the server name.
00533   // So a name of foo/bar means that the server name is foo.
00534   ACE_CString server_name (object_name);
00535   ssize_t pos = server_name.find ('/');
00536   if (pos != ACE_CString::npos)
00537     server_name = server_name.substr (pos + 1);
00538 
00539   return activate_server_by_name (server_name.c_str (), false ACE_ENV_ARG_PARAMETER);
00540 }
00541 
00542 char*
00543 ImR_Locator_i::activate_server_i (Server_Info& info, bool manual_start ACE_ENV_ARG_DECL)
00544 ACE_THROW_SPEC ((CORBA::SystemException,
00545                 ImplementationRepository::NotFound,
00546                 ImplementationRepository::CannotActivate))
00547 {
00548   if (info.activation_mode == ImplementationRepository::PER_CLIENT)
00549     {
00550       return activate_perclient_server_i (info, manual_start ACE_ENV_ARG_PARAMETER);
00551     }
00552 
00553   while (true)
00554     {
00555       if (is_alive (info))
00556         {
00557           if (debug_ > 1)
00558             {
00559               ACE_DEBUG ((LM_DEBUG, "ImR: Successfully activated <%s> at \n\t%s\n",
00560                           info.name.c_str (), info.partial_ior.c_str ()));
00561             }
00562           info.start_count = 0;
00563 
00564           waiter_svt_.unblock_all (info.name.c_str ());
00565 
00566           return CORBA::string_dup (info.partial_ior.c_str ());
00567         }
00568 
00569       info.reset ();
00570 
00571       if (! info.starting && info.start_count >= info.start_limit)
00572         {
00573           if (this->debug_ > 0)
00574             {
00575               ACE_DEBUG ((LM_DEBUG,
00576                           "ImR: Cannot Activate <%s>.\n", info.name.c_str ()));
00577             }
00578 
00579           waiter_svt_.unblock_all (info.name.c_str ());
00580 
00581           ACE_THROW_RETURN (ImplementationRepository::CannotActivate
00582                             (CORBA::string_dup ("Cannot start server.")), 0);
00583         }
00584 
00585       // Note : We already updated info with StartupInfo in server_is_running ()
00586       ImplementationRepository::StartupInfo_var si =
00587         start_server (info, manual_start ACE_ENV_ARG_PARAMETER);
00588       ACE_CHECK_RETURN (0);
00589     }
00590 }
00591 
00592 char*
00593 ImR_Locator_i::activate_perclient_server_i (Server_Info info, bool manual_start ACE_ENV_ARG_DECL)
00594 ACE_THROW_SPEC ((CORBA::SystemException,
00595                 ImplementationRepository::NotFound,
00596                 ImplementationRepository::CannotActivate))
00597 {
00598   do
00599     {
00600       ImplementationRepository::StartupInfo* psi =
00601         start_server (info, manual_start ACE_ENV_ARG_PARAMETER);
00602       ACE_CHECK_RETURN (0);
00603 
00604       if (psi != 0)
00605         {
00606           ImplementationRepository::StartupInfo_var si = psi;
00607           ACE_ASSERT (info.name == si->name.in ());
00608           info.partial_ior = si->partial_ior.in ();
00609           info.ior = si->ior.in ();
00610 
00611           if (is_alive (info))
00612             {
00613               if (debug_ > 1)
00614                 {
00615                   ACE_DEBUG ((LM_DEBUG, "ImR: Successfully activated <%s> at \n\t%s\n",
00616                               info.name.c_str (), info.partial_ior.c_str ()));
00617                 }
00618               return CORBA::string_dup (info.partial_ior.c_str ());
00619             }
00620           info.reset ();
00621         }
00622     } while (info.start_count < info.start_limit);
00623 
00624   if (this->debug_ > 0)
00625     {
00626       ACE_DEBUG ((LM_DEBUG,
00627                   "ImR: Cannot Activate <%s>.\n", info.name.c_str ()));
00628     }
00629   ACE_THROW_RETURN (ImplementationRepository::CannotActivate
00630                     (CORBA::string_dup ("Cannot start server.")), 0);
00631 }
00632 
00633 ImplementationRepository::StartupInfo*
00634 ImR_Locator_i::start_server (Server_Info& info, bool manual_start ACE_ENV_ARG_DECL)
00635 ACE_THROW_SPEC ((CORBA::SystemException,
00636                 ImplementationRepository::NotFound,
00637                 ImplementationRepository::CannotActivate))
00638 {
00639   if (info.activation_mode == ImplementationRepository::MANUAL && ! manual_start)
00640     {
00641       if (debug_ > 0)
00642         ACE_DEBUG ((LM_DEBUG, "ImR: Cannot start server <%s>. ActivationMode=MANUAL\n", info.name.c_str ()));
00643       ACE_THROW_RETURN (ImplementationRepository::CannotActivate
00644                         (CORBA::string_dup ("Cannot implicitly activate MANUAL server.")), 0);
00645     }
00646   if (info.cmdline.length () == 0)
00647     {
00648       if (debug_ > 0)
00649         ACE_DEBUG ((LM_DEBUG, "ImR: Cannot start server <%s>."
00650                     " No command line.\n", info.name.c_str ()));
00651       ACE_THROW_RETURN (ImplementationRepository::CannotActivate
00652                         (CORBA::string_dup ("No command line registered for server.")), 0);
00653     }
00654 
00655   Activator_Info_Ptr ainfo = get_activator (info.activator);
00656 
00657   if (ainfo.null () || CORBA::is_nil (ainfo->activator.in ()))
00658     {
00659       if (debug_ > 0)
00660         ACE_DEBUG ((LM_DEBUG, "ImR: Cannot start server <%s>. "
00661                     "Activator <%s> not found.\n", info.name.c_str (), info.activator.c_str ()));
00662       ACE_THROW_RETURN (ImplementationRepository::CannotActivate
00663                         (CORBA::string_dup ("No activator registered for server.")), 0);
00664     }
00665 
00666   ACE_TRY
00667     {
00668       ++ info.waiting_clients;
00669 
00670       if (info.waiting_clients <= 1 || info.activation_mode == ImplementationRepository::PER_CLIENT)
00671         {
00672           info.starting = true;
00673           ++info.start_count;
00674           ACE_ASSERT (info.start_count <= info.start_limit);
00675           if (this->debug_ > 0)
00676             {
00677               ACE_DEBUG ((LM_DEBUG, "ImR: Starting server <%s>. Attempt %d/%d.\n",
00678                           info.name.c_str (), info.start_count, info.start_limit));
00679             }
00680           ainfo->activator->start_server (
00681                                           info.name.c_str (),
00682                                           info.cmdline.c_str (),
00683                                           info.dir.c_str (),
00684                                           info.env_vars
00685                                           ACE_ENV_ARG_PARAMETER);
00686           ACE_TRY_CHECK;
00687         }
00688 
00689       if (info.partial_ior.length () == 0)
00690         {
00691           if (this->debug_ > 0)
00692             {
00693               ACE_DEBUG ((LM_DEBUG, "ImR: Waiting for <%s> to start...\n", info.name.c_str ()));
00694             }
00695 
00696           ImplementationRepository::StartupInfo_var si =
00697             waiter_->wait_for_startup (info.name.c_str () ACE_ENV_ARG_PARAMETER);
00698           ACE_TRY_CHECK;
00699 
00700           -- info.waiting_clients;
00701           info.starting = false;
00702 
00703           return si._retn ();
00704         }
00705       else // The server_is_running () came in before the wait_for_startup ()
00706         {
00707           if (this->debug_ > 0)
00708             {
00709               ACE_DEBUG ((LM_DEBUG, "ImR: <%s> Skipping wait. Already started.\n", info.name.c_str ()));
00710             }
00711           -- info.waiting_clients;
00712           info.starting = false;
00713         }
00714     }
00715   ACE_CATCH (CORBA::TIMEOUT, ex)
00716     {
00717       -- info.waiting_clients;
00718       info.starting = false;
00719       // We may have connected successfully, because the timeout could occur before
00720       // the AsyncStartupWaiter manages to return. In fact, when the ImR is very busy
00721       // this is the most likely code path.
00722       if (info.partial_ior.length () == 0)
00723         {
00724           if (debug_ > 0)
00725             ACE_DEBUG ((LM_DEBUG, "ImR : Timeout waiting for <%s> to start.\n", info.name.c_str ()));
00726           info.reset ();
00727         }
00728     }
00729   ACE_CATCH (ImplementationRepository::CannotActivate, ex)
00730     {
00731       -- info.waiting_clients;
00732       info.starting = false;
00733       info.reset ();
00734       if (debug_ > 0)
00735         ACE_DEBUG ((LM_DEBUG, "ImR: Activator cannot start <%s>.\n", info.name.c_str ()));
00736     }
00737   ACE_CATCHANY
00738     {
00739       -- info.waiting_clients;
00740       info.starting = false;
00741       if (debug_ > 0)
00742         ACE_DEBUG ((LM_DEBUG, "ImR: Unexpected exception while starting <%s>.\n", info.name.c_str ()));
00743       if (debug_ > 1)
00744         ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "");
00745       ainfo->reset ();
00746       info.reset ();
00747     }
00748   ACE_ENDTRY;
00749   return 0; // This is not a corba call, so a zero should be ok
00750 }
00751 
00752 CORBA::Object_ptr
00753 ImR_Locator_i::set_timeout_policy (CORBA::Object_ptr obj, const ACE_Time_Value& to)
00754 {
00755   CORBA::Object_var ret (CORBA::Object::_duplicate (obj));
00756 
00757   ACE_TRY_NEW_ENV
00758     {
00759       TimeBase::TimeT timeout;
00760       ORBSVCS_Time::Time_Value_to_TimeT (timeout, to);
00761       CORBA::Any tmp;
00762       tmp <<= timeout;
00763 
00764       CORBA::PolicyList policies (1);
00765       policies.length (1);
00766       policies[0] = orb_->create_policy (Messaging::RELATIVE_RT_TIMEOUT_POLICY_TYPE, tmp ACE_ENV_ARG_PARAMETER);
00767       ACE_TRY_CHECK;
00768 
00769       ret = obj->_set_policy_overrides (policies, CORBA::ADD_OVERRIDE ACE_ENV_ARG_PARAMETER);
00770       ACE_TRY_CHECK;
00771 
00772       policies[0]->destroy (ACE_ENV_SINGLE_ARG_PARAMETER);
00773       ACE_TRY_CHECK;
00774 
00775       if (CORBA::is_nil (ret.in ()))
00776         {
00777           if (this->debug_ > 0)
00778             {
00779               ACE_DEBUG ((LM_DEBUG, "ImR: Unable to set timeout policy.\n"));
00780             }
00781           ret = CORBA::Object::_duplicate (obj);
00782         }
00783     }
00784   ACE_CATCHANY
00785     {
00786       ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::set_timeout_policy ()");
00787     }
00788   ACE_ENDTRY;
00789 
00790   return ret._retn ();
00791 }
00792 
00793 void
00794 ImR_Locator_i::add_or_update_server (const char* server,
00795                                 const ImplementationRepository::StartupOptions &options
00796                                 ACE_ENV_ARG_DECL)
00797                                 ACE_THROW_SPEC ((CORBA::SystemException,
00798                                   ImplementationRepository::NotFound))
00799 {
00800   ACE_ASSERT (server != 0);
00801 
00802   if (this->read_only_)
00803     {
00804       ACE_DEBUG ((LM_DEBUG, "ImR: Cannot add/update server <%s> due to locked database.\n", server));
00805       ACE_THROW (CORBA::NO_PERMISSION (
00806                                        CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0),
00807                                        CORBA::COMPLETED_NO));
00808     }
00809 
00810   if (debug_ > 0)
00811     ACE_DEBUG ((LM_DEBUG, "ImR: Add/Update server <%s>.\n", server));
00812 
00813   int limit = options.start_limit;
00814   if (limit < 0)
00815     {
00816       limit = -limit;
00817     }
00818   else if (limit == 0)
00819     {
00820       limit = 1;
00821     }
00822 
00823   Server_Info_Ptr info = this->repository_.get_server (server);
00824   if (info.null ())
00825     {
00826       if (this->debug_ > 1)
00827         ACE_DEBUG ((LM_DEBUG, "ImR: Adding server <%s>.\n", server));
00828 
00829       this->repository_.add_server (server,
00830                                     options.activator.in (),
00831                                     options.command_line.in (),
00832                                     options.environment,
00833                                     options.working_directory.in (),
00834                                     options.activation,
00835                                     limit);
00836     }
00837   else
00838     {
00839       if (this->debug_ > 1)
00840         ACE_DEBUG ((LM_DEBUG, "ImR: Updating server <%s>.\n", server));
00841 
00842       info->activator = options.activator.in ();
00843       info->cmdline = options.command_line.in ();
00844       info->env_vars = options.environment;
00845       info->dir = options.working_directory.in ();
00846       info->activation_mode = options.activation;
00847       info->start_limit = limit;
00848       info->start_count = 0;
00849       int err = this->repository_.update_server (*info);
00850       ACE_ASSERT (err == 0);
00851       ACE_UNUSED_ARG (err);
00852     }
00853 
00854   if (this->debug_ > 1)
00855     {
00856       // Note : The info var may be null, so we use options.
00857       ACE_DEBUG ((LM_DEBUG, "ImR: Server: %s\n"
00858                   "\tActivator: %s\n"
00859                   "\tCommand Line: %s\n"
00860                   "\tWorking Directory: %s\n"
00861                   "\tActivation: %s\n"
00862                   "\tStart Limit: %d\n"
00863                   "\n",
00864                   server,
00865                   options.activator.in (),
00866                   options.command_line.in (),
00867                   options.working_directory.in (),
00868                   ImR_Utils::activationModeToString (options.activation).c_str (),
00869                   limit
00870                   ));
00871 
00872       for (CORBA::ULong i = 0; i < options.environment.length (); ++i)
00873         ACE_DEBUG ((LM_DEBUG, "Environment variable %s=%s\n",
00874                     options.environment[i].name.in (),
00875                     options.environment[i].value.in ()));
00876     }
00877 }
00878 
00879 void
00880 ImR_Locator_i::remove_server (const char* name ACE_ENV_ARG_DECL)
00881 ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound))
00882 {
00883   ACE_ASSERT (name != 0);
00884   if (this->read_only_)
00885     {
00886       ACE_ERROR ((LM_ERROR,
00887                   "ImR: Can't remove server <%s> due to locked database.\n", name));
00888       ACE_THROW (CORBA::NO_PERMISSION (
00889                                        CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0),
00890                                        CORBA::COMPLETED_NO));
00891     }
00892 
00893   // Note : This will be safe, because any Server_Info_Ptr objects will still
00894   // be valid, and the actual Server_Info will be destroyed when the last
00895   // one goes out of scope.
00896 
00897   Server_Info_Ptr info = this->repository_.get_server (name);
00898   if (! info.null ())
00899     {
00900       if (this->repository_.remove_server (name) == 0)
00901         {
00902           if (this->debug_ > 1)
00903             ACE_DEBUG ((LM_DEBUG, "ImR: Removing Server <%s>...\n", name));
00904 
00905           PortableServer::POA_var poa = findPOA (name);
00906           ACE_CHECK;
00907           if (! CORBA::is_nil (poa.in ()))
00908             {
00909               bool etherealize = true;
00910               bool wait = false;
00911               poa->destroy (etherealize, wait ACE_ENV_ARG_PARAMETER);
00912               ACE_CHECK;
00913             }
00914           if (this->debug_ > 0)
00915             ACE_DEBUG ((LM_DEBUG, "ImR: Removed Server <%s>.\n", name));
00916         }
00917     }
00918   else
00919     {
00920       ACE_ERROR ((LM_ERROR,
00921                   "ImR: Can't remove unknown server <%s>.\n", name));
00922       ACE_THROW (ImplementationRepository::NotFound ());
00923     }
00924 }
00925 
00926 PortableServer::POA_ptr
00927 ImR_Locator_i::findPOA (const char* name)
00928 {
00929   ACE_TRY_NEW_ENV
00930     {
00931       bool activate_it = false;
00932       return root_poa_->find_POA (name, activate_it ACE_ENV_ARG_PARAMETER);
00933       ACE_TRY_CHECK;
00934     }
00935   ACE_CATCHANY
00936     {// Ignore
00937     }
00938   ACE_ENDTRY;
00939   return PortableServer::POA::_nil ();
00940 }
00941 
00942 void
00943 ImR_Locator_i::shutdown_server (const char* server ACE_ENV_ARG_DECL)
00944 ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound))
00945 {
00946   ACE_ASSERT (server != 0);
00947 
00948   if (this->debug_ > 0)
00949     ACE_DEBUG ((LM_DEBUG, "ImR: Shutting down server <%s>.\n", server));
00950 
00951   Server_Info_Ptr info = this->repository_.get_server (server);
00952   if (info.null ())
00953     {
00954       ACE_ERROR ((LM_ERROR,
00955                   "ImR: shutdown_server () Cannot find info for server <%s>\n", server));
00956       ACE_THROW (ImplementationRepository::NotFound ());
00957     }
00958 
00959   connect_server (*info);
00960 
00961   if (CORBA::is_nil (info->server.in ()))
00962     {
00963       ACE_ERROR ((LM_ERROR,
00964                   "ImR: shutdown_server () Cannot connect to server <%s>\n", server));
00965       ACE_THROW (ImplementationRepository::NotFound ());
00966     }
00967 
00968   ACE_TRY_NEW_ENV
00969     {
00970       CORBA::Object_var obj = set_timeout_policy (info->server.in (), DEFAULT_SHUTDOWN_TIMEOUT);
00971       ImplementationRepository::ServerObject_var server =
00972         ImplementationRepository::ServerObject::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
00973       ACE_TRY_CHECK;
00974       server->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER);
00975       ACE_TRY_CHECK;
00976     }
00977   ACE_CATCH (CORBA::TIMEOUT, ex)
00978     {
00979       info->reset ();
00980       int err = this->repository_.update_server (*info);
00981       ACE_ASSERT (err == 0);
00982       ACE_UNUSED_ARG (err);
00983       // Note : This is a good thing. It means we didn't waste our time waiting for
00984       // the server to finish shutting down.
00985       if (this->debug_ > 1)
00986         {
00987           ACE_DEBUG ((LM_DEBUG, "ImR: Timeout while waiting for <%s> shutdown.\n", server));
00988         }
00989       ACE_RE_THROW;
00990     }
00991   ACE_CATCHANY
00992     {
00993       if (this->debug_ > 1)
00994         {
00995           ACE_DEBUG ((LM_DEBUG, "ImR: Exception ignored while shutting down <%s>\n", server));
00996         }
00997     }
00998   ACE_ENDTRY;
00999 
01000   // Note : In most cases this has already been done in the server_is_shutting_down ()
01001   // operation, but it doesn't hurt to update it again.
01002   info->reset ();
01003 
01004   int err = this->repository_.update_server (*info);
01005   ACE_ASSERT (err == 0);
01006   ACE_UNUSED_ARG (err);
01007 }
01008 
01009 void
01010 ImR_Locator_i::server_is_running (const char* name,
01011                                   const char* partial_ior,
01012                                   ImplementationRepository::ServerObject_ptr server
01013                                   ACE_ENV_ARG_DECL)
01014                                   ACE_THROW_SPEC ((CORBA::SystemException,
01015                                   ImplementationRepository::NotFound))
01016 {
01017   ACE_ASSERT (name != 0);
01018   ACE_ASSERT (partial_ior != 0);
01019   ACE_ASSERT (! CORBA::is_nil (server));
01020 
01021   if (this->debug_ > 0)
01022     ACE_DEBUG ((LM_DEBUG, "ImR: Server %s is running at %s.\n", name, partial_ior));
01023 
01024   CORBA::String_var ior = orb_->object_to_string (server ACE_ENV_ARG_PARAMETER);
01025   ACE_CHECK;
01026 
01027   if (this->debug_ > 1)
01028     ACE_DEBUG ((LM_DEBUG, "ImR: Server %s callback at %s.\n", name, ior.in ()));
01029 
01030   Server_Info_Ptr info = this->repository_.get_server (name);
01031   if (info.null ())
01032     {
01033       if (this->debug_ > 0)
01034         ACE_DEBUG ((LM_DEBUG, "ImR: Auto adding NORMAL server <%s>.\n", name));
01035 
01036       ImplementationRepository::EnvironmentList env (0);
01037       this->repository_.add_server (name,
01038                                     "", // no activator
01039                                     "", // no cmdline
01040                                     ImplementationRepository::EnvironmentList (),
01041                                     "", // no working dir
01042                                     ImplementationRepository::NORMAL,
01043                                     DEFAULT_START_LIMIT,
01044                                     partial_ior,
01045                                     ior.in (),
01046                                     ImplementationRepository::ServerObject::_nil () // Will connect at first access
01047                                     );
01048     }
01049   else
01050     {
01051       if (info->activation_mode != ImplementationRepository::PER_CLIENT) {
01052         info->ior = ior.in ();
01053         info->partial_ior = partial_ior;
01054         info->server = ImplementationRepository::ServerObject::_nil (); // Will connect at first access
01055 
01056         int err = this->repository_.update_server (*info);
01057         ACE_ASSERT (err == 0);
01058         ACE_UNUSED_ARG (err);
01059 
01060         waiter_svt_.unblock_one (name, partial_ior, ior.in (), false);
01061       } else {
01062         // Note : There's no need to unblock all the waiting request until
01063         // we know the final status of the server.
01064         waiter_svt_.unblock_one (name, partial_ior, ior.in (), true);
01065       }
01066     }
01067 }
01068 
01069 void
01070 ImR_Locator_i::server_is_shutting_down (const char* server ACE_ENV_ARG_DECL_NOT_USED)
01071 ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound))
01072 {
01073   ACE_ASSERT (server != 0);
01074   Server_Info_Ptr info = this->repository_.get_server (server);
01075   if (info.null ())
01076     {
01077       if (this->debug_ > 1)
01078         {
01079           ACE_DEBUG ((LM_DEBUG,
01080                       "ImR_Locator_i::server_is_shutting_down: Unknown server:%s\n", server));
01081         }
01082       return;
01083     }
01084 
01085   if (this->debug_ > 0)
01086     ACE_DEBUG ((LM_DEBUG, "ImR: Server <%s> is shutting down.\n", server));
01087 
01088   info->reset ();
01089 
01090   int err = this->repository_.update_server (*info);
01091   ACE_ASSERT (err == 0);
01092   ACE_UNUSED_ARG (err);
01093 }
01094 
01095 void
01096 ImR_Locator_i::find (const char* server,
01097                      ImplementationRepository::ServerInformation_out imr_info
01098                      ACE_ENV_ARG_DECL)
01099                      ACE_THROW_SPEC ((CORBA::SystemException))
01100 {
01101   ACE_ASSERT (server != 0);
01102   ACE_NEW_THROW_EX (imr_info, ImplementationRepository::ServerInformation, CORBA::NO_MEMORY ());
01103 
01104   Server_Info_Ptr info = this->repository_.get_server (server);
01105   if (! info.null ())
01106     {
01107       imr_info = info->createImRServerInfo (ACE_ENV_SINGLE_ARG_PARAMETER);
01108 
01109       if (this->debug_ > 1)
01110         ACE_DEBUG ((LM_DEBUG, "ImR: Found server %s.\n", server));
01111     }
01112   else
01113     {
01114       if (debug_ > 1)
01115         ACE_DEBUG ((LM_DEBUG, "ImR: Cannot find server <%s>\n", server));
01116     }
01117 }
01118 
01119 void
01120 ImR_Locator_i::list (CORBA::ULong how_many,
01121                      ImplementationRepository::ServerInformationList_out server_list,
01122                      ImplementationRepository::ServerInformationIterator_out server_iterator
01123                      ACE_ENV_ARG_DECL
01124                      ) ACE_THROW_SPEC ((CORBA::SystemException))
01125 {
01126   if (this->debug_ > 1)
01127     ACE_DEBUG ((LM_DEBUG, "ImR: List servers.\n"));
01128 
01129   // Initialize the out variables, so if we return early, they will
01130   // not be dangling.
01131   server_iterator = ImplementationRepository::ServerInformationIterator::_nil ();
01132   ACE_NEW_THROW_EX (server_list,
01133                     ImplementationRepository::ServerInformationList (0), CORBA::NO_MEMORY ());
01134 
01135   Locator_Repository::SIMap::ENTRY* entry = 0;
01136   Locator_Repository::SIMap::ITERATOR it (this->repository_.servers ());
01137 
01138   // Number of servers that will go into the server_list.
01139   CORBA::ULong n = this->repository_.servers ().current_size ();
01140   if (how_many > 0 && n > how_many)
01141     {
01142       n = how_many;
01143     }
01144 
01145   server_list->length (n);
01146 
01147   if (this->debug_ > 1)
01148     ACE_DEBUG ((LM_DEBUG, "ImR_Locator_i::list: Filling ServerList with %d servers\n", n));
01149 
01150   for (CORBA::ULong i = 0; i < n; i++)
01151     {
01152       it.next (entry);
01153       it.advance ();
01154       ACE_ASSERT (entry != 0);
01155 
01156       Server_Info_Ptr info = entry->int_id_;
01157 
01158       ImplementationRepository::ServerInformation_var imr_info = info->createImRServerInfo (ACE_ENV_SINGLE_ARG_PARAMETER);
01159       server_list[i] = *imr_info;
01160     }
01161 
01162   if (this->repository_.servers ().current_size () > n)
01163     {
01164       if (this->debug_ > 1)
01165         ACE_DEBUG ((LM_DEBUG, "ImR_Locator_i::list: Creating ServerInformation Iterator\n"));
01166 
01167       ImR_Iterator* imr_iter;
01168 
01169       ACE_NEW_THROW_EX (imr_iter,
01170                         ImR_Iterator (n, this->repository_, this->imr_poa_.in ()),
01171                         CORBA::NO_MEMORY ());
01172 
01173       PortableServer::ServantBase_var tmp (imr_iter);
01174 
01175       ACE_TRY
01176         {
01177           PortableServer::ObjectId_var id =
01178             this->imr_poa_->activate_object (imr_iter ACE_ENV_ARG_PARAMETER);
01179           ACE_TRY_CHECK;
01180           CORBA::Object_var obj = this->imr_poa_->id_to_reference (id.in () ACE_ENV_ARG_PARAMETER);
01181           ACE_TRY_CHECK;
01182           server_iterator = ImplementationRepository::
01183             ServerInformationIterator::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
01184           ACE_TRY_CHECK;
01185         }
01186       ACE_CATCHANY
01187         {
01188           ACE_RE_THROW;
01189         }
01190       ACE_ENDTRY;
01191       ACE_CHECK;
01192     }
01193 }
01194 
01195 Activator_Info_Ptr
01196 ImR_Locator_i::get_activator (const ACE_CString& aname)
01197 {
01198   Activator_Info_Ptr info = this->repository_.get_activator (aname);
01199   if (! info.null ())
01200     {
01201       this->connect_activator (*info);
01202     }
01203   return info;
01204 }
01205 
01206 void
01207 ImR_Locator_i::connect_activator (Activator_Info& info)
01208 {
01209   if (! CORBA::is_nil (info.activator.in ()) || info.ior.length () == 0)
01210     return;
01211 
01212   ACE_TRY_NEW_ENV
01213     {
01214       CORBA::Object_var obj =
01215         this->orb_->string_to_object (info.ior.c_str ()
01216                                       ACE_ENV_ARG_PARAMETER);
01217       ACE_TRY_CHECK;
01218 
01219       if (CORBA::is_nil (obj.in ()))
01220         {
01221           info.reset ();
01222           return;
01223         }
01224 
01225       if (startup_timeout_ > ACE_Time_Value::zero)
01226         {
01227           obj = set_timeout_policy (obj.in (), startup_timeout_);
01228         }
01229 
01230       info.activator =
01231         ImplementationRepository::Activator::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
01232       ACE_TRY_CHECK;
01233 
01234       if (CORBA::is_nil (info.activator.in ()))
01235         {
01236           info.reset ();
01237           return;
01238         }
01239 
01240       if (debug_ > 1)
01241         ACE_DEBUG ((LM_DEBUG, "ImR: Connected to activator <%s>\n", info.name.c_str ()));
01242     }
01243   ACE_CATCHANY
01244     {
01245       info.reset ();
01246     }
01247   ACE_ENDTRY;
01248 }
01249 
01250 void
01251 ImR_Locator_i::auto_start_servers (ACE_ENV_SINGLE_ARG_DECL)
01252 {
01253   if (this->repository_.servers ().current_size () == 0)
01254     return;
01255 
01256   Locator_Repository::SIMap::ENTRY* server_entry;
01257   Locator_Repository::SIMap::ITERATOR server_iter (this->repository_.servers ());
01258 
01259   // For each of the entries in the Locator_Repository, get the startup
01260   // information and activate the servers, if they are not already
01261   // running.
01262   for (;server_iter.next (server_entry) != 0; server_iter.advance ())
01263     {
01264       Server_Info_Ptr info = server_entry->int_id_;
01265       ACE_ASSERT (! info.null ());
01266 
01267       ACE_TRY
01268         {
01269           if (info->activation_mode == ImplementationRepository::AUTO_START
01270               && info->cmdline.length () > 0)
01271             {
01272               this->activate_server_i (*info, true ACE_ENV_ARG_PARAMETER);
01273               ACE_TRY_CHECK;
01274             }
01275         }
01276       ACE_CATCHANY
01277         {
01278           if (this->debug_ > 1)
01279             {
01280               ACE_DEBUG ((LM_DEBUG,
01281                           "ImR: AUTO_START Could not activate <%s>\n",
01282                           server_entry->ext_id_.c_str ()));
01283               ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "AUTO_START");
01284             }
01285           // Ignore exceptions
01286         }
01287       ACE_ENDTRY;
01288       ACE_CHECK;
01289     }
01290 }
01291 
01292 void
01293 ImR_Locator_i::connect_server (Server_Info& info)
01294 {
01295   if (! CORBA::is_nil (info.server.in ()))
01296     {
01297       return; // already connected
01298     }
01299 
01300   if (info.ior.length () == 0)
01301     {
01302       info.reset ();
01303       return; // can't connect
01304     }
01305 
01306   ACE_TRY_NEW_ENV
01307     {
01308       CORBA::Object_var obj = orb_->string_to_object (info.ior.c_str () ACE_ENV_ARG_PARAMETER);
01309       ACE_TRY_CHECK;
01310 
01311       if (CORBA::is_nil (obj.in ()))
01312         {
01313           info.reset ();
01314           return;
01315         }
01316 
01317       obj = set_timeout_policy (obj.in (), DEFAULT_SERVER_TIMEOUT);
01318 
01319       info.server =
01320         ImplementationRepository::ServerObject::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER);
01321       ACE_TRY_CHECK;
01322 
01323       if (CORBA::is_nil (info.server.in ()))
01324         {
01325           info.reset ();
01326           return;
01327         }
01328 
01329       if (debug_ > 1)
01330         ACE_DEBUG ((LM_DEBUG, "ImR: Connected to server <%s>\n", info.name.c_str ()));
01331     }
01332   ACE_CATCHANY
01333     {
01334       info.reset ();
01335     }
01336   ACE_ENDTRY;
01337 }
01338 
01339 bool
01340 ImR_Locator_i::is_alive (Server_Info& info)
01341 {
01342   const size_t table_size = sizeof (PING_RETRY_SCHEDULE) /
01343                             sizeof (*PING_RETRY_SCHEDULE);
01344 
01345   for (size_t i = 0; i < table_size; ++i)
01346     {
01347       int status = this->is_alive_i (info);
01348       if (status == 0)
01349         return false;
01350       if (status == 1)
01351         return true;
01352 
01353       // This is evil, but there's not much else we can do for now. We
01354       // should never reach this code once the ImR Servers are fixed
01355       // so that they don't lie about server_is_running. Currently,
01356       // they send this notification during poa creation.  We have to
01357       // run the orb, because the very thing that may be slowing the
01358       // aliveness of the servers is the fact that they're trying to
01359       // register more objects with us.  In practical testing, we
01360       // never retried the ping more than once, because the second
01361       // ping always timed out, even if the servers poa manager had
01362       // not been activated. The only way we saw multiple retries was
01363       // if we ran the orb on the server before the poa manager was
01364       // activated.  For this reason, the first retry is immediate,
01365       // and the orb->run () call is not required. The call will
01366       // likely timeout, and is_alive will return true.
01367       if (PING_RETRY_SCHEDULE[i] > 0)
01368         {
01369           ACE_Time_Value tv (0, PING_RETRY_SCHEDULE[i] * 1000);
01370           this->orb_->run (tv);
01371         }
01372     }
01373   if (debug_ > 0)
01374     {
01375       ACE_DEBUG ((LM_DEBUG,
01376                   "ImR: <%s> Ping retry count exceeded. alive=maybe.\n", info.name.c_str ()));
01377     }
01378   // We return true here, because the server *might* be alive, it's just not starting in a timely
01379   // manner. We can't return false, because then we'll just try to start another instance, and the
01380   // same thing will likely happen.
01381   info.last_ping = ACE_OS::gettimeofday ();
01382   return true;
01383 }
01384 
01385 int
01386 ImR_Locator_i::is_alive_i (Server_Info& info)
01387 {
01388   // This is used by the ACE_TRY below when exceptions are turned off.
01389   ACE_DECLARE_NEW_CORBA_ENV;
01390 
01391   if (info.ior.length () == 0 || info.partial_ior.length () == 0)
01392     {
01393       if (debug_ > 1)
01394         {
01395           ACE_DEBUG ((LM_DEBUG,
01396                       "ImR: <%s> not running. alive=false.\n", info.name.c_str ()));
01397         }
01398       info.last_ping = ACE_Time_Value::zero;
01399       return 0;
01400     }
01401 
01402   if (ping_interval_ == ACE_Time_Value::zero)
01403     {
01404       if (debug_ > 1)
01405         {
01406           ACE_DEBUG ((LM_DEBUG,
01407                       "ImR: <%s> Ping verification disabled. alive=true.\n", info.name.c_str ()));
01408         }
01409       return 1;
01410     }
01411 
01412   if ((ACE_OS::gettimeofday () - info.last_ping) < ping_interval_)
01413     {
01414       if (debug_ > 1)
01415         {
01416           ACE_DEBUG ((LM_DEBUG,
01417                       "ImR: <%s> within ping interval. alive=true.\n", info.name.c_str ()));
01418         }
01419       return 1;
01420     }
01421 
01422   // If we don't have enough information to start the server if it isn't already
01423   // then we might as well assume it is running. That way the client can get the
01424   // status directly from the server.
01425   if (info.cmdline.length () == 0 || ! repository_.has_activator (info.activator))
01426     {
01427       if (debug_ > 1)
01428         {
01429           ACE_DEBUG ((LM_DEBUG,
01430                       "ImR: Ping verification skipped. <%s> not startable.\n", info.name.c_str ()));
01431         }
01432       return 1;
01433     }
01434 
01435   connect_server (info);
01436 
01437   if (CORBA::is_nil (info.server.in ()))
01438     {
01439       if (debug_ > 1)
01440         {
01441           ACE_DEBUG ((LM_DEBUG,
01442                       "ImR: <%s> Could not connect. alive=false.\n", info.name.c_str ()));
01443         }
01444       return 0;
01445     }
01446 
01447   ACE_TRY
01448     {
01449       // Make a copy, in case the info is updated during the ping.
01450       ImplementationRepository::ServerObject_var server = info.server;
01451 
01452       // This will timeout if it takes too long
01453       server->ping (ACE_ENV_SINGLE_ARG_PARAMETER);
01454       ACE_TRY_CHECK;
01455 
01456       if (debug_ > 1)
01457         {
01458           ACE_DEBUG ((LM_DEBUG,
01459                       "ImR: <%s> Ping successful. alive=true\n", info.name.c_str ()));
01460         }
01461       info.last_ping = ACE_OS::gettimeofday ();
01462     }
01463   ACE_CATCH (CORBA::TRANSIENT, ex)
01464     {
01465       const CORBA::ULong BITS_5_THRU_12_MASK = 0x00000f80;
01466       switch (ex.minor () & BITS_5_THRU_12_MASK)
01467         {
01468         case TAO_INVOCATION_SEND_REQUEST_MINOR_CODE:
01469           {
01470             if (debug_ > 1)
01471               {
01472                 ACE_DEBUG ((LM_DEBUG,
01473                             "ImR: <%s> Local TRANSIENT. alive=false.\n", info.name.c_str ()));
01474               }
01475           }
01476         info.last_ping = ACE_Time_Value::zero;
01477         return 0;
01478         case TAO_POA_DISCARDING:
01479         case TAO_POA_HOLDING:
01480           {
01481             if (debug_ > 1)
01482               {
01483                 ACE_DEBUG ((LM_DEBUG,
01484                             "ImR: <%s> Remote TRANSIENT. alive=maybe.\n", info.name.c_str ()));
01485               }
01486           }
01487         return -1; // We keep trying to ping, because returning 1 now, would just lead
01488         // to clients getting the same exception. If we can't ping after several
01489         // attempts, then we'll give up and return 1, letting the client worry about it.
01490         default:
01491           {
01492             if (debug_ > 1)
01493               {
01494                 ACE_DEBUG ((LM_DEBUG,
01495                             "ImR: <%s> TRANSIENT exception. alive=false.\n", info.name.c_str ()));
01496               }
01497             info.last_ping = ACE_Time_Value::zero;
01498           }
01499         return 0;
01500         }
01501     }
01502   ACE_CATCH (CORBA::TIMEOUT, ex)
01503     {
01504       if (debug_ > 1)
01505         {
01506           ACE_DEBUG ((LM_DEBUG,
01507                       "ImR: <%s> Ping timed out. alive=true.\n", info.name.c_str ()));
01508         }
01509       return 1; // This is "alive" as far as we're concerned. Presumably the client
01510       // will have a less stringent timeout policy, or will want to know
01511       // about the timeout. In any case, we're only guaranteeing that the
01512       // server is alive, not that it's responsive.
01513     }
01514   ACE_CATCHANY
01515     {
01516       if (debug_ > 1)
01517         {
01518           ACE_DEBUG ((LM_DEBUG, "ImR: <%s> Unexpected Ping exception. alive=false\n", info.name.c_str ()));
01519           ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "\n");
01520         }
01521       info.last_ping = ACE_Time_Value::zero;
01522       return false;
01523     }
01524   ACE_ENDTRY;
01525   return 1;
01526 }
01527 
01528 int
01529 ImR_Locator_i::debug () const
01530 {
01531   return debug_;
01532 }

Generated on Thu Nov 9 13:36:19 2006 for TAO_Implementation_Repository by doxygen 1.3.6