ImR_Activator_i.cpp

Go to the documentation of this file.
00001 // $Id: ImR_Activator_i.cpp 78858 2007-07-12 23:24:55Z sowayaa $
00002 
00003 #include "ImR_Activator_i.h"
00004 
00005 #include "Activator_Options.h"
00006 
00007 #include "tao/ORB_Core.h"
00008 
00009 #include "ace/Reactor.h"
00010 #include "ace/ARGV.h"
00011 #include "ace/OS_NS_unistd.h"
00012 #include "ace/OS_NS_stdio.h"
00013 #include "ace/os_include/os_netdb.h"
00014 
00015 static ACE_CString getHostName ()
00016 {
00017   char host_name[MAXHOSTNAMELEN];
00018   ACE_OS::hostname (host_name, MAXHOSTNAMELEN);
00019   return ACE_CString (host_name);
00020 }
00021 
00022 ImR_Activator_i::ImR_Activator_i (void)
00023 : registration_token_(0)
00024 , debug_(0)
00025 , notify_imr_ (false)
00026 , name_ (getHostName ())
00027 , env_buf_len_ (Activator_Options::ENVIRONMENT_BUFFER)
00028 {
00029 }
00030 
00031 static PortableServer::POA_ptr
00032 createPersistentPOA (PortableServer::POA_ptr root_poa, const char* poa_name)
00033 {
00034   PortableServer::LifespanPolicy_var life =
00035     root_poa->create_lifespan_policy (PortableServer::PERSISTENT);
00036 
00037   PortableServer::IdAssignmentPolicy_var assign =
00038     root_poa->create_id_assignment_policy (PortableServer::USER_ID);
00039 
00040   CORBA::PolicyList pols;
00041   pols.length (2);
00042   pols[0] = PortableServer::LifespanPolicy::_duplicate (life.in ());
00043   pols[1] = PortableServer::IdAssignmentPolicy::_duplicate (assign.in ());
00044 
00045   PortableServer::POAManager_var mgr = root_poa->the_POAManager ();
00046   PortableServer::POA_var poa =
00047     root_poa->create_POA(poa_name, mgr.in (), pols);
00048 
00049   life->destroy ();
00050   assign->destroy ();
00051 
00052   return poa._retn ();
00053 }
00054 
00055 // It's ok if we can't register with the ImR. It just
00056 // means we won't be able to notify it of any events
00057 // (Currently, just that we're shutting down and to
00058 // notify of the ImR when a child process exits.)
00059 void
00060 ImR_Activator_i::register_with_imr (ImplementationRepository::Activator_ptr activator)
00061 {
00062   try
00063     {
00064       if (this->debug_ > 1)
00065         ACE_DEBUG( (LM_DEBUG, "ImR Activator: Contacting ImplRepoService...\n"));
00066 
00067       // First, resolve the ImR, without this we can go no further
00068       CORBA::Object_var obj =
00069         orb_->resolve_initial_references ("ImplRepoService");
00070 
00071       this->process_mgr_.open (ACE_Process_Manager::DEFAULT_SIZE,
00072         this->orb_->orb_core ()->reactor ());
00073 
00074       locator_ = ImplementationRepository::Locator::_narrow (obj.in ());
00075 
00076       if (!CORBA::is_nil (locator_.in ()))
00077         {
00078           this->registration_token_ =
00079             locator_->register_activator (name_.c_str (), activator);
00080 
00081           if (debug_ > 0)
00082             ACE_DEBUG((LM_DEBUG, "ImR Activator: Registered with ImR.\n"));
00083 
00084           return;
00085         }
00086     }
00087   catch (const CORBA::Exception& ex)
00088     {
00089       if (debug_ > 1)
00090         ex._tao_print_exception (
00091           "ImR Activator: Can't register with ImR.");
00092     }
00093 
00094   if (debug_ > 0)
00095     ACE_DEBUG ((LM_DEBUG, "ImR Activator: Not registered with ImR.\n"));
00096 }
00097 
00098 int
00099 ImR_Activator_i::init_with_orb (CORBA::ORB_ptr orb, const Activator_Options& opts)
00100 {
00101   ACE_ASSERT(! CORBA::is_nil (orb));
00102   orb_ = CORBA::ORB::_duplicate (orb);
00103   debug_ = opts.debug ();
00104   notify_imr_ = opts.notify_imr ();
00105   env_buf_len_ = opts.env_buf_len ();
00106   if (opts.name ().length () > 0)
00107     {
00108       name_ = opts.name();
00109     }
00110 
00111   try
00112     {
00113       CORBA::Object_var obj = orb->resolve_initial_references ("RootPOA");
00114       ACE_ASSERT (! CORBA::is_nil (obj.in ()));
00115       this->root_poa_ = PortableServer::POA::_narrow (obj.in ());
00116       ACE_ASSERT (! CORBA::is_nil(this->root_poa_.in ()));
00117 
00118       // The activator must use a persistent POA so that it can be started before the
00119       // locator in some scenarios, such as when the locator persists its database, and
00120       // wants to reconnect to running activators to auto_start some servers.
00121       this->imr_poa_ = createPersistentPOA (this->root_poa_.in (),
00122         "ImR_Activator");
00123       ACE_ASSERT (! CORBA::is_nil(this->imr_poa_.in ()));
00124 
00125       // Activate ourself
00126       PortableServer::ObjectId_var id = PortableServer::string_to_ObjectId ("ImR_Activator");
00127       this->imr_poa_->activate_object_with_id (id.in (), this);
00128       obj = this->imr_poa_->id_to_reference (id.in ());
00129       ImplementationRepository::Activator_var activator =
00130         ImplementationRepository::Activator::_narrow (obj.in ());
00131       ACE_ASSERT(! CORBA::is_nil (activator.in ()));
00132 
00133       CORBA::String_var ior = this->orb_->object_to_string (activator.in ());
00134 
00135       if (this->debug_ > 0)
00136         ACE_DEBUG((LM_DEBUG, "ImR Activator: Starting %s\n", name_.c_str ()));
00137 
00138       // initialize our process manager.
00139       // This requires a reactor that has signal handling.
00140       ACE_Reactor *reactor = ACE_Reactor::instance ();
00141       if (reactor != 0)
00142         {
00143           if (this->process_mgr_.open (ACE_Process_Manager::DEFAULT_SIZE, reactor) == -1)
00144             {
00145               ACE_ERROR_RETURN ((LM_ERROR,
00146                 "The ACE_Process_Manager didnt get initialized\n"), -1);
00147             }
00148         }
00149 
00150       this->register_with_imr (activator.in ()); // no throw
00151 
00152       PortableServer::POAManager_var poaman =
00153         this->root_poa_->the_POAManager ();
00154       poaman->activate ();
00155 
00156       if (this->debug_ > 1)
00157         {
00158           ACE_DEBUG ((LM_DEBUG,
00159             "ImR Activator: The Activator IOR is: <%s>\n", ior.in ()));
00160         }
00161 
00162       // The last thing we do is write out the ior so that a test program can assume
00163       // that the activator is ready to go as soon as the ior is written.
00164       if (opts.ior_filename ().length () > 0)
00165         {
00166           FILE* fp = ACE_OS::fopen (opts.ior_filename ().c_str (), "w");
00167           if (fp == 0)
00168             {
00169               ACE_ERROR_RETURN ((LM_ERROR,
00170                 "ImR Activator: Could not open file: %s\n", opts.ior_filename ().c_str ()), -1);
00171             }
00172           ACE_OS::fprintf (fp, "%s", ior.in ());
00173           ACE_OS::fclose (fp);
00174         }
00175     }
00176   catch (const CORBA::Exception& ex)
00177     {
00178       ex._tao_print_exception (
00179         "ImR_Activator_i::init_with_orb");
00180       throw;
00181     }
00182   return 0;
00183 }
00184 
00185 int
00186 ImR_Activator_i::init (Activator_Options& opts)
00187 {
00188   ACE_CString cmdline = opts.cmdline();
00189   // Must use IOR style objrefs, because URLs sometimes get mangled when passed
00190   // to ACE_Process::spawn().
00191   cmdline += "-ORBUseImR 0 -ORBObjRefStyle IOR ";
00192   ACE_ARGV av (cmdline.c_str ());
00193   int argc = av.argc ();
00194 
00195   CORBA::ORB_var orb =
00196     CORBA::ORB_init (argc, av.argv (), "TAO_ImR_Activator");
00197 
00198   int ret = this->init_with_orb(orb.in (), opts);
00199 
00200   return ret;
00201 }
00202 
00203 int
00204 ImR_Activator_i::fini (void)
00205 {
00206   try
00207     {
00208       if (debug_ > 1)
00209         ACE_DEBUG ((LM_DEBUG, "ImR Activator: Shutting down...\n"));
00210 
00211       this->process_mgr_.close ();
00212 
00213       this->root_poa_->destroy (1, 1);
00214 
00215       if (! CORBA::is_nil (this->locator_.in ()) && this->registration_token_ != 0)
00216         {
00217           this->locator_->unregister_activator (name_.c_str(),
00218             this->registration_token_);
00219         }
00220     }
00221   catch (const CORBA::COMM_FAILURE&)
00222     {
00223       if (debug_ > 1)
00224         ACE_DEBUG ((LM_DEBUG, "ImR Activator: Unable to unregister from ImR.\n"));
00225     }
00226   catch (const CORBA::TRANSIENT&)
00227     {
00228       if (debug_ > 1)
00229         ACE_DEBUG ((LM_DEBUG, "ImR Activator: Unable to unregister from ImR.\n"));
00230     }
00231   catch (const CORBA::Exception& ex)
00232   {
00233     ex._tao_print_exception ("ImR Activator: fini");
00234     throw;
00235   }
00236 
00237   try
00238     {
00239       this->orb_->destroy ();
00240 
00241       if (debug_ > 0)
00242         ACE_DEBUG ((LM_DEBUG, "ImR Activator: Shut down successfully.\n"));
00243     }
00244   catch (const CORBA::Exception& ex)
00245     {
00246       ex._tao_print_exception ("ImR Activator: fini 2");
00247       throw;
00248     }
00249   return 0;
00250 }
00251 
00252 int
00253 ImR_Activator_i::run (void)
00254 {
00255   this->orb_->run ();
00256   return 0;
00257 }
00258 
00259 void
00260 ImR_Activator_i::shutdown (void)
00261 {
00262   this->shutdown (false);
00263 }
00264 
00265 void
00266 ImR_Activator_i::shutdown (bool wait_for_completion)
00267 {
00268   this->orb_->shutdown (wait_for_completion);
00269 }
00270 
00271 void
00272 ImR_Activator_i::start_server(const char* name,
00273                               const char* cmdline,
00274                               const char* dir,
00275                               const ImplementationRepository::EnvironmentList & env)
00276 {
00277   if (debug_ > 1)
00278     ACE_DEBUG((LM_DEBUG, "ImR Activator: Starting server <%s>...\n", name));
00279   if (debug_ > 1)
00280     ACE_DEBUG((LM_DEBUG, "\tcommand line : <%s>\n\tdirectory : <%s>\n", cmdline, dir));
00281 
00282   ACE_Process_Options proc_opts (
00283                         1,
00284                         ACE_Process_Options::DEFAULT_COMMAND_LINE_BUF_LEN,
00285                         this->env_buf_len_);
00286   proc_opts.command_line (cmdline);
00287   proc_opts.working_directory (dir);
00288   // Win32 does not support the CLOSE_ON_EXEC semantics for sockets
00289   // the way unix does, so in order to avoid having the child process
00290   // hold the listen socket open, we force the child to inherit no
00291   // handles. This includes stdin, stdout, logs, etc.
00292   proc_opts.handle_inheritence (0);
00293 
00294   proc_opts.setenv ("TAO_USE_IMR", "1");
00295   if (!CORBA::is_nil (this->locator_.in ()))
00296     {
00297       CORBA::String_var ior = orb_->object_to_string (locator_.in ());
00298       proc_opts.setenv ("ImplRepoServiceIOR", ior.in());
00299     }
00300 
00301   for (CORBA::ULong i = 0; i < env.length (); ++i)
00302     {
00303       proc_opts.setenv (env[i].name.in (), env[i].value.in ());
00304     }
00305 
00306   int pid = this->process_mgr_.spawn (proc_opts);
00307   if (pid == ACE_INVALID_PID)
00308     {
00309       ACE_ERROR ((LM_ERROR,
00310         "ImR Activator: Cannot start server <%s> using <%s>\n", name, cmdline));
00311 
00312       throw ImplementationRepository::CannotActivate(
00313         CORBA::string_dup (
00314           "Process Creation Failed"));
00315       return;
00316     }
00317   else
00318     {
00319       if (debug_ > 1)
00320         {
00321           ACE_DEBUG((LM_DEBUG,
00322             "ImR Activator: register death handler for process %d\n", pid));
00323         }
00324       this->process_mgr_.register_handler (this, pid);
00325 
00326       // We only bind to the process_map_ if we want to notify
00327       // the locator of a process' death.
00328       if (notify_imr_)
00329         {
00330           this->process_map_.rebind (pid, name);
00331         }
00332     }
00333 
00334   if (debug_ > 0)
00335     {
00336       ACE_DEBUG ((LM_DEBUG, "ImR Activator: Successfully started <%s>. \n", name));
00337     }
00338 }
00339 
00340 int
00341 ImR_Activator_i::handle_exit (ACE_Process * process)
00342 {
00343   // We use the process_manager so that we're notified when
00344   // any of our launched processes die. We notify the locator
00345   // when this happens.
00346 
00347   if (debug_ > 0)
00348     {
00349       ACE_DEBUG
00350         ((LM_DEBUG,
00351         ACE_TEXT ("Process %d exited with exit code %d\n"),
00352         process->getpid (), process->return_value ()));
00353     }
00354 
00355   ACE_CString name;
00356   if (this->process_map_.find (process->getpid (), name) == 0)
00357     {
00358       this->process_map_.unbind (process->getpid ());
00359 
00360       if (!CORBA::is_nil (this->locator_.in ()))
00361         {
00362           if (debug_ > 1)
00363             {
00364               ACE_DEBUG ((LM_DEBUG,
00365                 ACE_TEXT ("ImR Activator: Notifying ImR that %s has exited.\n"),
00366                 name.c_str()));
00367             }
00368           this->locator_->notify_child_death (name.c_str());
00369         }
00370     }
00371 
00372   return 0;
00373 }

Generated on Sun Jan 27 15:54:50 2008 for TAO_Implementation_Repository by doxygen 1.3.6