diff options
Diffstat (limited to 'modules/CIAO/ciao/ComponentServer/CIAO_ServerActivator_Impl.cpp')
-rw-r--r-- | modules/CIAO/ciao/ComponentServer/CIAO_ServerActivator_Impl.cpp | 510 |
1 files changed, 510 insertions, 0 deletions
diff --git a/modules/CIAO/ciao/ComponentServer/CIAO_ServerActivator_Impl.cpp b/modules/CIAO/ciao/ComponentServer/CIAO_ServerActivator_Impl.cpp new file mode 100644 index 00000000000..770ae3b7d22 --- /dev/null +++ b/modules/CIAO/ciao/ComponentServer/CIAO_ServerActivator_Impl.cpp @@ -0,0 +1,510 @@ +// $Id$ + +#include "CIAO_ServerActivator_Impl.h" +#include "ace/Log_Msg.h" +#include "ace/UUID.h" +#include "ciao/Logger/Log_Macros.h" + +#include "CIAO_FailureReasonsC.h" +#include "CIAO_ComponentServerC.h" +#include "CIAO_PropertiesC.h" + +namespace CIAO +{ + namespace Deployment + { + CIAO_ServerActivator_i::CIAO_ServerActivator_i (CORBA::ULong def_spawn_delay, + const char * default_cs_path, + const char * cs_args, + bool multithreaded, + Components::Deployment::ComponentInstallation_ptr ci, + CORBA::ORB_ptr orb, + PortableServer::POA_ptr poa) + : spawn_delay_ (def_spawn_delay), + multithreaded_ (multithreaded), + orb_ (CORBA::ORB::_duplicate (orb)), + poa_ (PortableServer::POA::_duplicate (poa)), + cs_path_ (default_cs_path), + cs_args_ (cs_args), + mutex_ (), + condition_ (mutex_), + ci_ (Components::Deployment::ComponentInstallation::_duplicate (ci)) + + { + CIAO_TRACE ("CIAO_ServerActivator_i::CIAO_ServerActivator_i"); + ACE_Utils::UUID_GENERATOR::instance ()->init (); + } + + CIAO_ServerActivator_i::~CIAO_ServerActivator_i(void) + { + } + + void + CIAO_ServerActivator_i::component_server_callback ( + ::Components::Deployment::ComponentServer_ptr serverref, + const char * server_UUID, + ::Components::ConfigValues_out config) + { + CIAO_TRACE("CIAO_ServerActivator_i::component_server_callback"); + + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::component_server_callback - " + "Received callback from ComponentServer %C\n", + server_UUID)); + + Server_Info *info = 0; + + for (SERVER_INFOS::iterator i (this->server_infos_.begin ()); + !i.done (); ++i) + { + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::component_server_callback - " + "Comparing %C with %C\n", (*i)->uuid_.c_str (), server_UUID)); + if ((*i)->uuid_ == server_UUID) + { + info = (*i).get (); + } + } + + if (!info) + { + CIAO_ERROR (1, (LM_WARNING, CLINFO + "CIAO_ServerActivator_i::component_server_callback - " + "Received callback from ComponentServer %C, which doesn't belong to me.\n", + server_UUID)); + throw CORBA::BAD_PARAM (); + } + + if (info->activated_) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::component_server_callback - " + "Received callback from ComponentServer %C, which has already been configured.\n", + server_UUID)); + throw CORBA::BAD_INV_ORDER (); + } + + if (!CORBA::is_nil (info->ref_)) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::component_server_callback - " + "Received callback from ComponentServer %C, which has already called back.\n", + server_UUID)); + throw CORBA::BAD_INV_ORDER (); + } + + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::component_server_callback - " + "Received callback from ComponentServer %C\n", + server_UUID)); + + info->ref_ = ::Components::Deployment::ComponentServer::_duplicate (serverref); + + this->create_component_server_config_values (*info, config); + + // @@TODO: May want to print out configvalues here. + CIAO_DEBUG (6, (LM_DEBUG, CLINFO + "CIAO_ServerActivator_i::component_server_callback - " + "Generated %u ConfigValues for ComponentServer %C\n", + config->length (), server_UUID)); + } + + void + CIAO_ServerActivator_i::configuration_complete (const char *server_UUID) + { + CIAO_TRACE ("CIAO_ServerActivator_i::configuration_complete"); + + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::configuration_complete - " + "Received configuration_complete from ComponentServer %C\n", + server_UUID)); + + try + { + Server_Info *info = 0; + + for (SERVER_INFOS::ITERATOR j (this->server_infos_); + !j.done (); ++j) + { + if ((*j)->uuid_ == server_UUID) + { + info = (*j).get (); + } + } + + if (!info) + { + CIAO_ERROR (1, (LM_WARNING, CLINFO + "CIAO_ServerActivator_i::configuration_complete - " + "Received configuration_complete from ComponentServer %C, which doesn't belong to me.\n", + server_UUID)); + throw CORBA::BAD_PARAM (); + } + + if (info->activated_) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::configuration_complete - " + "Received configuration_complete from ComponentServer %C, which has already been completed.\n", + server_UUID)); + throw CORBA::BAD_INV_ORDER (); + } + + if (CORBA::is_nil (info->ref_.in ())) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::configuration_complete - " + "Received configuration_complete from ComponentServer %C, which has not called back.\n", + server_UUID)); + throw CORBA::BAD_INV_ORDER (); + } + + info->activated_ = true; + } + catch (...) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::configuration_complete - " + "Caught unknown exception while processing configuration_complete\n")); + throw; + } + } + + ::Components::Deployment::ComponentServer_ptr + CIAO_ServerActivator_i::create_component_server (const ::Components::ConfigValues & config) + { + CIAO_TRACE("CIAO_ServerActivator_i::create_component_server"); + + Safe_Server_Info server (new Server_Info (config.length () + 1)); + + CIAO::Utility::build_config_values_map (*server->cmap_, config); + + ACE_CString cmd_options = this->construct_command_line (*server); + + CIAO_DEBUG (6, (LM_DEBUG, CLINFO + "CIAO_ServerActivator_i::create_component_server - ComponentServer arguments: %C\n", + cmd_options.c_str ())); + + server_infos_.insert_tail (server); + + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::create_component_server - " + "Attempting to spawn ComponentServer with UUID %C\n", + server->uuid_.c_str ())); + + // Now we need to get a copy of the one that was inserted... + pid_t const pid = this->spawn_component_server (*server, cmd_options); + ACE_UNUSED_ARG (pid); + + ACE_Time_Value timeout (this->spawn_delay_); + + CORBA::Any val; + + if (server->cmap_->find (SERVER_TIMEOUT, val) == 0) + { + CORBA::ULong t; + if (val >>= t) + { + CIAO_DEBUG (6, (LM_DEBUG, CLINFO "CIAO_ServerActivator_i::create_component_server - " + "Using provided non-default server timeout of %u\n", t)); + timeout = ACE_Time_Value (t); + } + else + { + CIAO_ERROR (1, (LM_WARNING, CLINFO "CIAO_ServerActivator_i::create_component_server - " + "Failed to extract provided non-default server timeout from property '%C', " + "falling back to default timeout of %u\n", + this->spawn_delay_)); + } + } + + if (this->multithreaded_) + this->multi_threaded_wait_for_callback (*server, timeout/*, pid*/); + else + this->single_threaded_wait_for_callback (*server, timeout/*, pid*/); + + CIAO_DEBUG (6, (LM_DEBUG, CLINFO + "CIAO_ServerActivator_i::create_component_server - " + "ComponentServer %C successfully spawned and configured!\n", + server->uuid_.c_str ())); + + return ::Components::Deployment::ComponentServer::_duplicate (server->ref_.in ()); + } + + ACE_CString + CIAO_ServerActivator_i::construct_command_line (Server_Info &server) + { + CIAO_TRACE ("CIAO_ServerActivator_i::construct_command_line"); + + // Build our command line to launch the component server + ACE_CString cmd_options (this->cs_args_); + + CORBA::Any val; + + if (server.cmap_->find (SERVER_UUID, val) == 0) + { + // Nodeapplication has requested a custom uuid + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::construct_command_line - Using provided UUID\n")); + const char *uuid = 0; + val >>= uuid; + server.uuid_ = uuid; + } + else + { + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::construct_command_line - Using generated UUID\n")); + ACE_Utils::UUID uuid; + ACE_Utils::UUID_GENERATOR::instance ()->generate_UUID (uuid); + server.uuid_ = *uuid.to_string (); + } + + if (server.cmap_->find (SERVER_ARGUMENTS, val) == 0) + { + const char *args = 0; + val >>= args; + + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::construct_command_line - " + "Adding provided server arguments %C\n", args)); + + cmd_options += ' '; + cmd_options += args; + cmd_options += ' '; + } + + CIAO_DEBUG (6, (LM_DEBUG, CLINFO + "CIAO_ServerActivator_i::construct_command_line - Creating component server" + " with UUID %C\n", server.uuid_.c_str ())); + + cmd_options += " -u "; + cmd_options += server.uuid_; + + return cmd_options; + } + + pid_t + CIAO_ServerActivator_i::spawn_component_server (const Server_Info &si, + const ACE_CString &cmd_line) + { + CIAO_TRACE ("CIAO_ServerActivator_i::spawn_component_server"); + + // Get my object reference + CORBA::Object_var obj = this->poa_->servant_to_reference (this); + CORBA::String_var ior = this->orb_->object_to_string (obj.in ()); + CORBA::Any val; + + const char *path = this->cs_path_.c_str (); + + if (si.cmap_->find (SERVER_EXECUTABLE, val) == 0) + { + val >>= path; + CIAO_DEBUG (6, (LM_DEBUG, CLINFO "CIAO_ServerActivator_i::spawn_component_server - " + "Using provided component server executable: %C\n", path)); + } + else + { + CIAO_DEBUG (6, (LM_DEBUG, CLINFO "CIAO_ServerActivator_i::spawn_component_server - " + "Using default component server executable\n")); + } + + ACE_Process_Options options (true, + ACE_OS::strlen (path) + ACE_OS::strlen (cmd_line.c_str()) + ACE_OS::strlen (ior.in ()) + 15); + if (options.command_line ("%s %s -c %s", + path, + cmd_line.c_str (), + ior.in ()) != 0) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "Failed to create commandline\n")); + throw Components::CreateFailure (CIAO::SERVER_SPAWN_FAILURE); + } + + options.avoid_zombies (0); + + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::spawn_component_server - Spawning process, command line is %s\n", + options.command_line_buf ())); + + pid_t const pid = this->process_manager_.spawn (options, + &this->child_handler_); + + if (pid == ACE_INVALID_PID) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "Failed to spawn a ComponentServer process\n")); + throw Components::CreateFailure (CIAO::SERVER_SPAWN_FAILURE); + } + + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::spawn_component_server - Process successfully spawned with pid %u\n", + pid)); + return pid; + } + + void + CIAO_ServerActivator_i:: + single_threaded_wait_for_callback (const Server_Info &si, + ACE_Time_Value &timeout) + { + CIAO_TRACE ("CIAO_ServerActivator_i::single_threaded_wait_for_callback"); + + // Below code is broken for thread-per-connection concurrency model, + // since the main thread is running ORB event loop and will spawn + // a different thread to handle the call <register_node_application>, + // the <perform_work> operation will not be invoked and finally + // a timeout will occur. For a similar reason, it won't work + // for thread-pool concurrency model. + while (true) + { + this->orb_->perform_work (timeout); + + if (timeout == ACE_Time_Value::zero) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::single_threaded_wait_for_callback - " + "Timed out while waiting for ComponentServer %C to call back.\n", + si.uuid_.c_str ())); + throw ::Components::CreateFailure (CIAO::CALLBACK_TIMEOUT_EXCEEDED); + } + + if (si.activated_) + { + break; + } + } + } + + void + CIAO_ServerActivator_i:: + multi_threaded_wait_for_callback (const Server_Info &si, + ACE_Time_Value &timeout) + { + CIAO_TRACE ("CIAO_ServerActivator_i::multi_threaded_wait_for_callback"); + + // Wait for a conditional variable + ACE_GUARD_THROW_EX ( TAO_SYNCH_MUTEX, + guard, + this->mutex_, + CORBA::NO_RESOURCES ()); + + while (! si.activated_ ) + if (this->condition_.wait (&timeout) == -1) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::multi_threaded_wait_for_callback - " + "Timed out while waiting for ComponentServer %C to call back.\n", + si.uuid_.c_str ())); + throw Components::CreateFailure (CIAO::CALLBACK_TIMEOUT_EXCEEDED); + } + } + + void + CIAO_ServerActivator_i::remove_component_server (::Components::Deployment::ComponentServer_ptr server) + { + CIAO_TRACE ("CIAO_ServerActivator_i::remove_component_server"); + + Server_Info *info = 0; + + for (SERVER_INFOS::ITERATOR i (this->server_infos_); + !i.done (); ++i) + { + if ((*i)->ref_->_is_equivalent (server)) + { + info = (*i).get (); + } + } + + if (!info) + { + CIAO_ERROR (1, (LM_ERROR, CLINFO + "CIAO_ServerActivator_i::remove_component_server - " + "Failed to find equivalent ComponentServer under my management.\n")); + throw ::Components::RemoveFailure (); + } + + try + { + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::remove_component_server - " + "Calling remove () on ComponentServer %C\n", + info->uuid_.c_str ())); + server->remove (); + } + catch (::Components::RemoveFailure &) + { + CIAO_ERROR (1, (LM_WARNING, CLINFO + "CIAO_ServerActivator_i::remove_component_server - " + "Received RemoveFailure exception from ComponentServer %C\n", + info->uuid_.c_str ())); + } + + // If this is a CIAO component server, call shutdown + CIAO::Deployment::ComponentServer_var ccs = + CIAO::Deployment::ComponentServer::_narrow (server); + if (!CORBA::is_nil (ccs)) + { + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::remove_component_server - " + "Calling shutdown () on ComponentServer %C\n", + info->uuid_.c_str ())); + ccs->shutdown (); + } + else + CIAO_DEBUG (9, (LM_TRACE, CLINFO + "CIAO_ServerActivator_i::remove_component_server - " + "ComponentServer %C is not a CIAO_ComponentServer, not calling shutdown.\n", + info->uuid_.c_str ())); + + CIAO_DEBUG (6, (LM_INFO, CLINFO + "CIAO_ServerActivator_i::remove_component_server - " + "ComponentServer %C successfully shut down.\n", + info->uuid_.c_str ())); + } + + ::Components::Deployment::ComponentServers * + CIAO_ServerActivator_i::get_component_servers (void) + { + CIAO_TRACE ("CIAO_ServerActivator_i::get_component_servers"); + + ::Components::Deployment::ComponentServers_var retval = new + Components::Deployment::ComponentServers (this->server_infos_.size ()); + + CORBA::ULong pos = 0; + + for (SERVER_INFOS::ITERATOR i (this->server_infos_); + !i.done (); ++i) + { + retval[pos++] = + ::Components::Deployment::ComponentServer::_duplicate ((*i)->ref_); + } + + return retval._retn (); + } + + void + CIAO_ServerActivator_i::create_component_server_config_values ( + const Server_Info &, + Components::ConfigValues_out &config) + { + ACE_NEW_THROW_EX (config, + Components::ConfigValues (1), + CORBA::NO_MEMORY ()); + + Components::Deployment::ComponentInstallation_ptr ci = + Components::Deployment::ComponentInstallation::_duplicate (this->ci_.in ()); + CORBA::Any ci_any; + ci_any <<= ci; + + OBV_Components::ConfigValue* p = 0; + ACE_NEW_THROW_EX (p, + OBV_Components::ConfigValue (), + CORBA::NO_MEMORY ()); + p->name (CIAO::Deployment::COMPONENTINSTALLATION_REF); + p->value (ci_any); + config->length (1); + config.operator[](0) = p; + } + } +} + |