summaryrefslogtreecommitdiff
path: root/orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp
diff options
context:
space:
mode:
authorparsons <parsons@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2010-08-13 15:47:20 +0000
committerparsons <parsons@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2010-08-13 15:47:20 +0000
commitd86939f8e188671a6226b24e0957d984050c0ed6 (patch)
treee58de7d2e0d317204ee79bd0578e51c93bf58ea8 /orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp
parente55d9214407ea472e418f9852cb58dddab0c83f5 (diff)
downloadATCD-d86939f8e188671a6226b24e0957d984050c0ed6.tar.gz
Diffstat (limited to 'orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp')
-rw-r--r--orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp381
1 files changed, 381 insertions, 0 deletions
diff --git a/orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp b/orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp
new file mode 100644
index 00000000000..15d28889e53
--- /dev/null
+++ b/orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp
@@ -0,0 +1,381 @@
+// $Id$
+
+#include "ImR_Activator_i.h"
+
+#include "Activator_Options.h"
+
+#include "tao/ORB_Core.h"
+
+#include "ace/Reactor.h"
+#include "ace/ARGV.h"
+#include "ace/OS_NS_unistd.h"
+#include "ace/OS_NS_stdio.h"
+#include "ace/os_include/os_netdb.h"
+
+static ACE_CString getHostName ()
+{
+ char host_name[MAXHOSTNAMELEN];
+ ACE_OS::hostname (host_name, MAXHOSTNAMELEN);
+ return ACE_CString (host_name);
+}
+
+ImR_Activator_i::ImR_Activator_i (void)
+: registration_token_(0)
+, debug_(0)
+, notify_imr_ (false)
+, name_ (getHostName ())
+, env_buf_len_ (Activator_Options::ENVIRONMENT_BUFFER)
+, max_env_vars_ (Activator_Options::ENVIRONMENT_MAX_VARS)
+{
+}
+
+static PortableServer::POA_ptr
+createPersistentPOA (PortableServer::POA_ptr root_poa, const char* poa_name)
+{
+ PortableServer::LifespanPolicy_var life =
+ root_poa->create_lifespan_policy (PortableServer::PERSISTENT);
+
+ PortableServer::IdAssignmentPolicy_var assign =
+ root_poa->create_id_assignment_policy (PortableServer::USER_ID);
+
+ CORBA::PolicyList pols;
+ pols.length (2);
+ pols[0] = PortableServer::LifespanPolicy::_duplicate (life.in ());
+ pols[1] = PortableServer::IdAssignmentPolicy::_duplicate (assign.in ());
+
+ PortableServer::POAManager_var mgr = root_poa->the_POAManager ();
+ PortableServer::POA_var poa =
+ root_poa->create_POA(poa_name, mgr.in (), pols);
+
+ life->destroy ();
+ assign->destroy ();
+
+ return poa._retn ();
+}
+
+// It's ok if we can't register with the ImR. It just
+// means we won't be able to notify it of any events
+// (Currently, just that we're shutting down and to
+// notify of the ImR when a child process exits.)
+void
+ImR_Activator_i::register_with_imr (ImplementationRepository::Activator_ptr activator)
+{
+ try
+ {
+ if (this->debug_ > 1)
+ ACE_DEBUG( (LM_DEBUG, "ImR Activator: Contacting ImplRepoService...\n"));
+
+ // First, resolve the ImR, without this we can go no further
+ CORBA::Object_var obj =
+ orb_->resolve_initial_references ("ImplRepoService");
+
+ this->process_mgr_.open (ACE_Process_Manager::DEFAULT_SIZE,
+ this->orb_->orb_core ()->reactor ());
+
+ locator_ = ImplementationRepository::Locator::_narrow (obj.in ());
+
+ if (!CORBA::is_nil (locator_.in ()))
+ {
+ this->registration_token_ =
+ locator_->register_activator (name_.c_str (), activator);
+
+ if (debug_ > 0)
+ ACE_DEBUG((LM_DEBUG, "ImR Activator: Registered with ImR.\n"));
+
+ return;
+ }
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ if (debug_ > 1)
+ ex._tao_print_exception (
+ "ImR Activator: Can't register with ImR.");
+ }
+
+ if (debug_ > 0)
+ ACE_DEBUG ((LM_DEBUG, "ImR Activator: Not registered with ImR.\n"));
+}
+
+int
+ImR_Activator_i::init_with_orb (CORBA::ORB_ptr orb, const Activator_Options& opts)
+{
+ ACE_ASSERT(! CORBA::is_nil (orb));
+ orb_ = CORBA::ORB::_duplicate (orb);
+ debug_ = opts.debug ();
+ notify_imr_ = opts.notify_imr ();
+ env_buf_len_ = opts.env_buf_len ();
+ max_env_vars_ = opts.max_env_vars ();
+ if (opts.name ().length () > 0)
+ {
+ name_ = opts.name();
+ }
+
+ try
+ {
+ CORBA::Object_var obj = orb->resolve_initial_references ("RootPOA");
+ ACE_ASSERT (! CORBA::is_nil (obj.in ()));
+ this->root_poa_ = PortableServer::POA::_narrow (obj.in ());
+ ACE_ASSERT (! CORBA::is_nil(this->root_poa_.in ()));
+
+ // The activator must use a persistent POA so that it can be started before the
+ // locator in some scenarios, such as when the locator persists its database, and
+ // wants to reconnect to running activators to auto_start some servers.
+ this->imr_poa_ = createPersistentPOA (this->root_poa_.in (),
+ "ImR_Activator");
+ ACE_ASSERT (! CORBA::is_nil(this->imr_poa_.in ()));
+
+ // Activate ourself
+ PortableServer::ObjectId_var id = PortableServer::string_to_ObjectId ("ImR_Activator");
+ this->imr_poa_->activate_object_with_id (id.in (), this);
+ obj = this->imr_poa_->id_to_reference (id.in ());
+ ImplementationRepository::Activator_var activator =
+ ImplementationRepository::Activator::_narrow (obj.in ());
+ ACE_ASSERT(! CORBA::is_nil (activator.in ()));
+
+ CORBA::String_var ior = this->orb_->object_to_string (activator.in ());
+
+ if (this->debug_ > 0)
+ ACE_DEBUG((LM_DEBUG, "ImR Activator: Starting %s\n", name_.c_str ()));
+
+ // initialize our process manager.
+ // This requires a reactor that has signal handling.
+ ACE_Reactor *reactor = ACE_Reactor::instance ();
+ if (reactor != 0)
+ {
+ if (this->process_mgr_.open (ACE_Process_Manager::DEFAULT_SIZE, reactor) == -1)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "The ACE_Process_Manager didnt get initialized\n"), -1);
+ }
+ }
+
+ this->register_with_imr (activator.in ()); // no throw
+
+ PortableServer::POAManager_var poaman =
+ this->root_poa_->the_POAManager ();
+ poaman->activate ();
+
+ if (this->debug_ > 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ "ImR Activator: The Activator IOR is: <%s>\n", ior.in ()));
+ }
+
+ // The last thing we do is write out the ior so that a test program can assume
+ // that the activator is ready to go as soon as the ior is written.
+ if (opts.ior_filename ().length () > 0)
+ {
+ FILE* fp = ACE_OS::fopen (opts.ior_filename ().c_str (), "w");
+ if (fp == 0)
+ {
+ ACE_ERROR_RETURN ((LM_ERROR,
+ "ImR Activator: Could not open file: %s\n", opts.ior_filename ().c_str ()), -1);
+ }
+ ACE_OS::fprintf (fp, "%s", ior.in ());
+ ACE_OS::fclose (fp);
+ }
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception (
+ "ImR_Activator_i::init_with_orb");
+ throw;
+ }
+ return 0;
+}
+
+int
+ImR_Activator_i::init (Activator_Options& opts)
+{
+ ACE_CString cmdline = opts.cmdline();
+ // Must use IOR style objrefs, because URLs sometimes get mangled when passed
+ // to ACE_Process::spawn().
+ cmdline += "-ORBUseImR 0 -ORBObjRefStyle IOR ";
+ ACE_ARGV av (cmdline.c_str ());
+ int argc = av.argc ();
+
+ CORBA::ORB_var orb =
+ CORBA::ORB_init (argc, av.argv (), "TAO_ImR_Activator");
+
+ int ret = this->init_with_orb(orb.in (), opts);
+
+ return ret;
+}
+
+int
+ImR_Activator_i::fini (void)
+{
+ try
+ {
+ if (debug_ > 1)
+ ACE_DEBUG ((LM_DEBUG, "ImR Activator: Shutting down...\n"));
+
+ this->process_mgr_.close ();
+
+ this->root_poa_->destroy (1, 1);
+
+ if (! CORBA::is_nil (this->locator_.in ()) && this->registration_token_ != 0)
+ {
+ this->locator_->unregister_activator (name_.c_str(),
+ this->registration_token_);
+ }
+ }
+ catch (const CORBA::COMM_FAILURE&)
+ {
+ if (debug_ > 1)
+ ACE_DEBUG ((LM_DEBUG, "ImR Activator: Unable to unregister from ImR.\n"));
+ }
+ catch (const CORBA::TRANSIENT&)
+ {
+ if (debug_ > 1)
+ ACE_DEBUG ((LM_DEBUG, "ImR Activator: Unable to unregister from ImR.\n"));
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception ("ImR Activator: fini");
+ throw;
+ }
+
+ try
+ {
+ this->orb_->destroy ();
+
+ if (debug_ > 0)
+ ACE_DEBUG ((LM_DEBUG, "ImR Activator: Shut down successfully.\n"));
+ }
+ catch (const CORBA::Exception& ex)
+ {
+ ex._tao_print_exception ("ImR Activator: fini 2");
+ throw;
+ }
+ return 0;
+}
+
+int
+ImR_Activator_i::run (void)
+{
+ this->orb_->run ();
+ return 0;
+}
+
+void
+ImR_Activator_i::shutdown (void)
+{
+ this->shutdown (false);
+}
+
+void
+ImR_Activator_i::shutdown (bool wait_for_completion)
+{
+ this->orb_->shutdown (wait_for_completion);
+}
+
+void
+ImR_Activator_i::start_server(const char* name,
+ const char* cmdline,
+ const char* dir,
+ const ImplementationRepository::EnvironmentList & env)
+{
+ if (debug_ > 1)
+ ACE_DEBUG((LM_DEBUG, "ImR Activator: Starting server <%s>...\n", name));
+ if (debug_ > 1)
+ ACE_DEBUG((LM_DEBUG, "\tcommand line : <%s>\n\tdirectory : <%s>\n", cmdline, dir));
+
+ ACE_Process_Options proc_opts (
+ 1,
+ ACE_Process_Options::DEFAULT_COMMAND_LINE_BUF_LEN,
+ this->env_buf_len_, this->max_env_vars_);
+ proc_opts.command_line (ACE_TEXT_CHAR_TO_TCHAR(cmdline));
+ proc_opts.working_directory (dir);
+ // Win32 does not support the CLOSE_ON_EXEC semantics for sockets
+ // the way unix does, so in order to avoid having the child process
+ // hold the listen socket open, we force the child to inherit no
+ // handles. This includes stdin, stdout, logs, etc.
+ proc_opts.handle_inheritance (0);
+
+ // We always enable the unicode environmet buffer on Windows. This works
+ // around a 32kb environment buffer limitation. This must come before any of
+ // the setenv() calls, since the first of those will copy the current
+ // process's environment.
+ proc_opts.enable_unicode_environment ();
+
+ proc_opts.setenv (ACE_TEXT("TAO_USE_IMR"), "1");
+ if (!CORBA::is_nil (this->locator_.in ()))
+ {
+ CORBA::String_var ior = orb_->object_to_string (locator_.in ());
+ proc_opts.setenv (ACE_TEXT("ImplRepoServiceIOR"), ior.in());
+ }
+
+ for (CORBA::ULong i = 0; i < env.length (); ++i)
+ {
+ proc_opts.setenv (ACE_TEXT_CHAR_TO_TCHAR(env[i].name.in ()), env[i].value.in ());
+ }
+
+ int pid = this->process_mgr_.spawn (proc_opts);
+ if (pid == ACE_INVALID_PID)
+ {
+ ACE_ERROR ((LM_ERROR,
+ "ImR Activator: Cannot start server <%s> using <%s>\n", name, cmdline));
+
+ throw ImplementationRepository::CannotActivate(
+ CORBA::string_dup (
+ "Process Creation Failed"));
+ return;
+ }
+ else
+ {
+ if (debug_ > 1)
+ {
+ ACE_DEBUG((LM_DEBUG,
+ "ImR Activator: register death handler for process %d\n", pid));
+ }
+ this->process_mgr_.register_handler (this, pid);
+
+ // We only bind to the process_map_ if we want to notify
+ // the locator of a process' death.
+ if (notify_imr_)
+ {
+ this->process_map_.rebind (pid, name);
+ }
+ }
+
+ if (debug_ > 0)
+ {
+ ACE_DEBUG ((LM_DEBUG, "ImR Activator: Successfully started <%s>, pid=%d\n", name, pid));
+ }
+}
+
+int
+ImR_Activator_i::handle_exit (ACE_Process * process)
+{
+ // We use the process_manager so that we're notified when
+ // any of our launched processes die. We notify the locator
+ // when this happens.
+
+ if (debug_ > 0)
+ {
+ ACE_DEBUG
+ ((LM_DEBUG,
+ ACE_TEXT ("Process %d exited with exit code %d\n"),
+ process->getpid (), process->return_value ()));
+ }
+
+ ACE_CString name;
+ if (this->process_map_.find (process->getpid (), name) == 0)
+ {
+ this->process_map_.unbind (process->getpid ());
+
+ if (!CORBA::is_nil (this->locator_.in ()))
+ {
+ if (debug_ > 1)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("ImR Activator: Notifying ImR that %s has exited.\n"),
+ name.c_str()));
+ }
+ this->locator_->notify_child_death (name.c_str());
+ }
+ }
+
+ return 0;
+}