diff options
Diffstat (limited to 'TAO/orbsvcs/ImplRepo_Service')
53 files changed, 9396 insertions, 0 deletions
diff --git a/TAO/orbsvcs/ImplRepo_Service/.cvsignore b/TAO/orbsvcs/ImplRepo_Service/.cvsignore new file mode 100644 index 00000000000..114bf08db80 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/.cvsignore @@ -0,0 +1,3 @@ +ImR_Activator +ImplRepo_Service +tao_imr diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_Info.cpp b/TAO/orbsvcs/ImplRepo_Service/Activator_Info.cpp new file mode 100644 index 00000000000..7833dce79ca --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_Info.cpp @@ -0,0 +1,20 @@ +// $Id$ +#include "Activator_Info.h" + +Activator_Info::Activator_Info +(const ACE_CString& aname, + CORBA::Long atoken, + const ACE_CString& aior, + ImplementationRepository::Activator_ptr act) + : name(aname) + , token(atoken) + , ior(aior) + , activator (ImplementationRepository::Activator::_duplicate (act)) +{ +} +void +Activator_Info::reset() +{ + ior = ""; + activator = ImplementationRepository::Activator::_nil(); +} diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_Info.h b/TAO/orbsvcs/ImplRepo_Service/Activator_Info.h new file mode 100644 index 00000000000..a054fa24cd9 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_Info.h @@ -0,0 +1,36 @@ +// $Id$ +#ifndef ACTIVATOR_INFO_H +#define ACTIVATOR_INFO_H + +#include "ace/Bound_Ptr.h" +#include "ace/SString.h" + +#include "ImR_ActivatorC.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** +* @brief Information about IMR registered Activators. +*/ +struct Activator_Info +{ + Activator_Info (const ACE_CString& aname, + CORBA::Long atoken, + const ACE_CString& aior, + ImplementationRepository::Activator_ptr act = + ImplementationRepository::Activator::_nil ()); + + /// Reset the connection portion + void reset(); + + ACE_CString name; + CORBA::Long token; + ACE_CString ior; + ImplementationRepository::Activator_var activator; +}; + +typedef ACE_Strong_Bound_Ptr<Activator_Info, ACE_Null_Mutex> Activator_Info_Ptr; + +#endif /* ACTIVATOR_INFO_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_Loader.cpp b/TAO/orbsvcs/ImplRepo_Service/Activator_Loader.cpp new file mode 100644 index 00000000000..9f222a54739 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_Loader.cpp @@ -0,0 +1,109 @@ +// $Id$ + +#include "Activator_Loader.h" +#include "ace/Dynamic_Service.h" +#include "ace/Task.h" + +class ImR_Activator_ORB_Runner : public ACE_Task_Base +{ + ImR_Activator_Loader& service_; +public: + ImR_Activator_ORB_Runner (ImR_Activator_Loader& service) + : service_ (service) + { + } + virtual int svc () + { + // Block until service_.fini() calls orb->destroy() + this->service_.run (); + return 0; + } +}; + +ImR_Activator_Loader::ImR_Activator_Loader (void) +{ +} + +// For now, we will assume that it's sufficient to start +// the service in its own thread. Later, if necessary, we +// can add a command line option to allow the imr to use +// the same orb as other tao services, however the imr +// is currently written with the assumption that it's running +// in its own orb. +int +ImR_Activator_Loader::init (int argc, ACE_TCHAR *argv[] ACE_ENV_ARG_DECL) +{ + ACE_TRY + { + int err = this->opts_.init (argc, argv); + if (err != 0) + return -1; + + // Creates it's own internal orb, which we must run later + err = this->service_.init (this->opts_ ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + if (err != 0) + return -1; + + // Create a thread in which to run the service + ACE_ASSERT (this->runner_.get () == 0); + this->runner_.reset (new ImR_Activator_ORB_Runner (*this)); + this->runner_->activate (); + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; + return 0; +} + +int +ImR_Activator_Loader::fini (void) +{ + ACE_ASSERT (this->runner_.get() != 0); + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int ret = this->service_.fini (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->runner_->wait (); + this->runner_.reset (0); + return ret; + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; +} + +CORBA::Object_ptr +ImR_Activator_Loader::create_object (CORBA::ORB_ptr, + int, + ACE_TCHAR ** + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_THROW_RETURN(CORBA::NO_IMPLEMENT (), CORBA::Object::_nil ()); +} + +int +ImR_Activator_Loader::run (void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + return this->service_.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR ((LM_ERROR, "Exception in ImR_Locator_ORB_Runner()\n")); + return -1; + } + ACE_ENDTRY; +} + +ACE_FACTORY_DEFINE (Activator, ImR_Activator_Loader) diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_Loader.h b/TAO/orbsvcs/ImplRepo_Service/Activator_Loader.h new file mode 100644 index 00000000000..2871c38e56b --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_Loader.h @@ -0,0 +1,52 @@ +// -*- C++ -*- +// +// $Id$ + +#ifndef TAO_IMR_ACTIVATOR_LOADER_H +#define TAO_IMR_ACTIVATOR_LOADER_H + +#include "ImR_Activator_i.h" +#include "Activator_Options.h" + +#include "tao/Object_Loader.h" + +#include "ace/Auto_Ptr.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ImR_Activator_ORB_Runner; + +class Activator_Export ImR_Activator_Loader : public TAO_Object_Loader +{ +public: + ImR_Activator_Loader(void); + + virtual int init (int argc, ACE_TCHAR *argv[] ACE_ENV_ARG_DECL); + + virtual int fini (void); + + virtual CORBA::Object_ptr create_object (CORBA::ORB_ptr orb, + int argc, + ACE_TCHAR *argv[] + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + + // Unlike other service objects, we have our own orb. + int run(void); + +private: + ImR_Activator_i service_; + Activator_Options opts_; + ACE_Auto_Ptr<ImR_Activator_ORB_Runner> runner_; + +private: + // Disallow copying and assignment. + ImR_Activator_Loader (const ImR_Activator_Loader &); + ImR_Activator_Loader &operator = (const ImR_Activator_Loader &); +}; + +ACE_FACTORY_DECLARE (Activator, ImR_Activator_Loader) + +#endif diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_NT_Service.cpp b/TAO/orbsvcs/ImplRepo_Service/Activator_NT_Service.cpp new file mode 100644 index 00000000000..eac94f086bb --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_NT_Service.cpp @@ -0,0 +1,115 @@ +//============================================================================= +/** + * @file Activator_NT_Service.cpp + * + * $Id$ + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + * @author Jeff Parsons <parsons@cs.wustl.edu> + * @author John Tucker <jtucker@infoglide.com> + * @author Mike Vitalo <mvitalo@infoglide.com> + */ +//============================================================================= + +#include "Activator_NT_Service.h" + +#if defined (ACE_WIN32) + +#include "ImR_Activator_i.h" +#include "Activator_Options.h" + +#include "tao/ORB_Core.h" + +#include "ace/Reactor.h" +/** + * Handles the SERVICE_CONTROL_SHUTDOWN and SERVICE_CONTROL_STOP commands + * by shutting down the ORB. Otherwise ACE_NT_Service::handle_control + * handles the command. + */ +void +Activator_NT_Service::handle_control (DWORD control_code) +{ + if (control_code == SERVICE_CONTROL_SHUTDOWN + || control_code == SERVICE_CONTROL_STOP) + { + report_status (SERVICE_STOP_PENDING); + TAO_ORB_Core_instance ()->reactor ()->end_reactor_event_loop (); + TAO_ORB_Core_instance ()->orb ()->shutdown (1); + } + else + { + ACE_NT_Service::handle_control (control_code); + } +} + + +/** + */ +int +Activator_NT_Service::handle_exception (ACE_HANDLE) +{ + return 0; +} + + +/** + * We do almost the same thing as we do in run_standalone () except that + * we update the report_status after init. + */ +int +Activator_NT_Service::svc (void) +{ + ImR_Activator_i server; + Activator_Options opts; + + if (opts.init_from_registry() != 0) + { + report_status (SERVICE_STOPPED); + return -1; + } + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int status = server.init (opts ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (status == -1) + { + report_status (SERVICE_STOPPED); + return -1; + } + else + { + report_status (SERVICE_RUNNING); + server.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + status = server.fini (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + report_status (SERVICE_STOPPED); + + } + if (status != -1) + return 0; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, IMR_ACTIVATOR_DISPLAY_NAME); + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, IMR_ACTIVATOR_DISPLAY_NAME); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, IMR_ACTIVATOR_DISPLAY_NAME); + } + ACE_ENDTRY; + + report_status (SERVICE_STOPPED); + return -1; +} + +#endif /* ACE_WIN32 */ diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_NT_Service.h b/TAO/orbsvcs/ImplRepo_Service/Activator_NT_Service.h new file mode 100644 index 00000000000..bde40cf1cd9 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_NT_Service.h @@ -0,0 +1,65 @@ +/* -*- C++ -*- */ +//============================================================================= +/** + * @file Activator_NT_Service.h + * + * $Id$ + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + * @author Jeff Parsons <parsons@cs.wustl.edu> + * @author John Tucker <jtucker@infoglide.com> + * @author Mike Vitalo <mvitalo@infoglide.com> + */ +//============================================================================= + +#ifndef Activator_NT_Service_H +#define Activator_NT_Service_H + +#include "ace/config-all.h" + +#if defined (ACE_WIN32) + +#include "ace/NT_Service.h" +#include "ace/Singleton.h" +#include "ace/Synch.h" +#include "tao/orbconf.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +static const char * IMR_ACTIVATOR_SERVICE_NAME = "TAOImRActivator"; +static const char * IMR_ACTIVATOR_DISPLAY_NAME = "TAO Implementation Repository Activator"; +static const char * IMR_ACTIVATOR_DESCRIPTION = "Implementation Repository Activator service for TAO"; + +/** + * @class Activator_NT_Service + * + * @brief Allows the Implementation Repository to act as a Windows NT Service. + */ +class Activator_NT_Service : public ACE_NT_Service +{ +public: + typedef TAO_SYNCH_RECURSIVE_MUTEX MUTEX; + + /// We override <handle_control> because it handles stop requests + /// privately. + virtual void handle_control (DWORD control_code); + + /// We override <handle_exception> so a 'stop' control code can wake + /// the reactor off of its wait. + virtual int handle_exception (ACE_HANDLE h); + + /// This is a virtual method inherited from ACE_NT_Service. + virtual int svc (void); +private: + friend class ACE_Singleton<Activator_NT_Service, MUTEX>; +}; + +typedef ACE_Singleton<Activator_NT_Service, ACE_Mutex> SERVICE; + +#endif /* ACE_WIN32 */ + +#endif /* Activator_NT_Service_H */ + + diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_Options.cpp b/TAO/orbsvcs/ImplRepo_Service/Activator_Options.cpp new file mode 100644 index 00000000000..072ca61ba38 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_Options.cpp @@ -0,0 +1,348 @@ +//============================================================================= +/** + * @file Activator_Options.cpp + * + * $Id$ + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= +#include "Activator_Options.h" + +#include "ace/Arg_Shifter.h" +#include "ace/OS_NS_strings.h" +#include "ace/Log_Msg.h" + +ACE_RCSID (ImplRepo_Service, + Activator_Options, + "$Id$") + +#if defined (ACE_WIN32) +static const HKEY SERVICE_REG_ROOT = HKEY_LOCAL_MACHINE; +// This string must agree with the one used in Activator_NT_Service.h +static const ACE_TCHAR *SERVICE_REG_PATH = + ACE_TEXT ("SYSTEM\\CurrentControlSet\\Services\\TAOImRActivator\\Parameters"); +#endif /* ACE_WIN32 */ + +Activator_Options::Activator_Options () +: debug_ (1) +, service_ (false) +, notify_imr_ (false) +, service_command_(SC_NONE) +{ +} + +int +Activator_Options::parse_args (int &argc, char *argv[]) +{ + ACE_Arg_Shifter shifter (argc, argv); + + while (shifter.is_anything_left ()) + { + if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-c")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -c option needs a command\n")); + this->print_usage (); + return -1; + } + + if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("install")) == 0) + { + this->service_command_ = SC_INSTALL; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("remove")) == 0) + { + this->service_command_ = SC_REMOVE; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("install_no_imr")) == 0) + { + this->service_command_ = SC_INSTALL_NO_LOCATOR; + } + else + { + ACE_ERROR((LM_ERROR, "Error: Unknown service command : %s\n", shifter.get_current())); + this->print_usage (); + return -1; + } + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-d")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -d option needs a debuglevel\n")); + this->print_usage (); + return -1; + } + + this->debug_ = ACE_OS::atoi (shifter.get_current ()); + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-o")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -o option needs a filename\n")); + this->print_usage (); + return -1; + } + this->ior_output_file_ = shifter.get_current (); + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-s")) == 0) + { + this->service_ = true; + } + else if ((ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-?")) == 0) + || (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-h")) == 0)) + { + this->print_usage (); + return 1; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-n")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -n option needs a name\n")); + this->print_usage (); + return -1; + } + this->name_ = shifter.get_current (); + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-l")) == 0) + { + this->notify_imr_ = true; + } + else + { + shifter.ignore_arg (); + continue; + } + + shifter.consume_arg (); + } + return 0; +} + +int +Activator_Options::init (int argc, char *argv[]) +{ + // Make an initial pass through and grab the arguments that we recognize. + // This may also run the commands to install or remove the nt service. + int result = this->parse_args (argc, argv); + if (result != 0) + { + return result; + } + + for (int i = 0; i < argc; ++i) + { + this->cmdline_ += ACE_CString (argv[i]) + ACE_CString (" "); + } + + return 0; +} + +int +Activator_Options::init_from_registry (void) +{ + this->load_registry_options(); + return 0; +} + +void +Activator_Options::print_usage (void) const +{ + ACE_ERROR ((LM_ERROR, + "Usage:\n" + "\n" + "ImR_Activator [-c cmd] [-d 0|1|2] [-o file] [-l] [-n name]\n" + "\n" + " -c command Runs service commands \n" + " ('install' or 'remove' or 'install_no_imr')\n" + " -d level Sets the debug level\n" + " -o file Outputs the ImR's IOR to a file\n" + " -l Notify the ImR when a process exits\n" + " -n name Specify a name for the Activator\n") + ); +} + +int +Activator_Options::save_registry_options() +{ +#if defined (ACE_WIN32) + HKEY key = 0; + // Create or open the parameters key + LONG err = ACE_TEXT_RegCreateKeyEx (SERVICE_REG_ROOT, + SERVICE_REG_PATH, + 0, + "", // class + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &key, + NULL + ); + if (err != ERROR_SUCCESS) + { + return -1; + } + err = ACE_TEXT_RegSetValueEx (key, "ORBInitOptions", 0, REG_SZ, + (LPBYTE) this->cmdline_.c_str (), this->cmdline_.length () + 1); + ACE_ASSERT (err == ERROR_SUCCESS); + + err = ACE_TEXT_RegSetValueEx (key, "IORFile", 0, REG_SZ, + (LPBYTE) this->ior_output_file_.c_str (), this->ior_output_file_.length () + 1); + ACE_ASSERT (err == ERROR_SUCCESS); + + err = ACE_TEXT_RegSetValueEx (key, "DebugLevel", 0, REG_DWORD, + (LPBYTE) &this->debug_ , sizeof (this->debug_)); + ACE_ASSERT (err == ERROR_SUCCESS); + + err = ACE_TEXT_RegSetValueEx( key, "Name", 0, REG_SZ, + (LPBYTE) this->name_.c_str (), this->name_.length () + 1); + ACE_ASSERT (err == ERROR_SUCCESS); + + DWORD tmpint = this->notify_imr_; + err = ACE_TEXT_RegSetValueEx (key, "NotifyImR", 0, REG_DWORD, + (LPBYTE) &tmpint , sizeof (tmpint)); + ACE_ASSERT (err == ERROR_SUCCESS); + + err = ::RegCloseKey (key); + ACE_ASSERT (err == ERROR_SUCCESS); +#endif + return 0; +} + +int +Activator_Options::load_registry_options () +{ +#if defined (ACE_WIN32) + HKEY key = 0; + // Create or open the parameters key + LONG err = ACE_TEXT_RegOpenKeyEx (SERVICE_REG_ROOT, + SERVICE_REG_PATH, + 0, + KEY_READ, + &key + ); + if (err != ERROR_SUCCESS) + { + // If there aren't any saved parameters, then that's ok. + return 0; + } + char tmpstr[4096]; + DWORD sz = sizeof (tmpstr); + DWORD type = 0; + err = ACE_TEXT_RegQueryValueEx (key, "ORBInitOptions", 0, &type, + (LPBYTE) tmpstr, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_SZ); + tmpstr[sz - 1] = '\0'; + this->cmdline_ = tmpstr; + } + + sz = sizeof(tmpstr); + err = ACE_TEXT_RegQueryValueEx (key, "IORFile", 0, &type, + (LPBYTE) tmpstr, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_SZ); + tmpstr[sz - 1] = '\0'; + this->ior_output_file_ = tmpstr; + } + + sz = sizeof(debug_); + err = ACE_TEXT_RegQueryValueEx (key, "DebugLevel", 0, &type, + (LPBYTE) &this->debug_ , &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + } + + sz = sizeof(tmpstr); + err = ACE_TEXT_RegQueryValueEx (key, "Name", 0, &type, + (LPBYTE) tmpstr, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_SZ); + tmpstr[sz - 1] = '\0'; + this->name_ = tmpstr; + } + + DWORD tmpint = 0; + sz = sizeof(tmpint); + err = ACE_TEXT_RegQueryValueEx (key, "NotifyImR", 0, &type, + (LPBYTE) &tmpint , &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + } + this->notify_imr_ = tmpint != 0; + + err = ::RegCloseKey (key); + ACE_ASSERT(err == ERROR_SUCCESS); +#endif /* ACE_WIN32 */ + return 0; +} + +bool +Activator_Options::service (void) const +{ + return this->service_; +} + +bool +Activator_Options::notify_imr (void) const +{ + return this->notify_imr_; +} + +unsigned int +Activator_Options::debug (void) const +{ + return this->debug_; +} + +const ACE_CString& +Activator_Options::ior_filename (void) const +{ + return this->ior_output_file_; +} + +Activator_Options::SERVICE_COMMAND +Activator_Options::service_command (void) const +{ + return this->service_command_; +} + +const char* +Activator_Options::cmdline (void) const +{ + return this->cmdline_.c_str (); +} + +const ACE_CString& +Activator_Options::name (void) const +{ + return this->name_; +} diff --git a/TAO/orbsvcs/ImplRepo_Service/Activator_Options.h b/TAO/orbsvcs/ImplRepo_Service/Activator_Options.h new file mode 100644 index 00000000000..45f351a0f44 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Activator_Options.h @@ -0,0 +1,105 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Activator_Options.h + * + * $Id$ + * + * @brief Definition of the Options class for the Implementation Repository. + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#ifndef ACTIVATOR_OPTIONS_H +#define ACTIVATOR_OPTIONS_H + +#include "activator_export.h" + +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class Options + * + * This is where all the settings for TAO's Implementation Repository are + * stored. + */ +class Activator_Export Activator_Options +{ +public: + + enum SERVICE_COMMAND { + SC_NONE, + SC_INSTALL, + SC_REMOVE, + SC_INSTALL_NO_LOCATOR + }; + + Activator_Options (); + + /// Parse the command-line arguments and initialize the options. + int init (int argc, char *argv[]); + /// This version should only be used when run as an nt service. + int init_from_registry(); + + /// Service Mode + bool service (void) const; + + /// Notify the ImR when server processes die. + /// Note : Currently this only works on Unix. + bool notify_imr (void) const; + + /// Debug level for the Implementation Repository. + unsigned int debug (void) const; + + /// Returns the file where the IOR should be stored. + const ACE_CString& ior_filename (void) const; + + /// The nt service command to run (install/remove) + SERVICE_COMMAND service_command(void) const; + + /// Save the command line arguments as registry settings. (Windows only) + int save_registry_options (); + + const char* cmdline(void) const; + + const ACE_CString& name(void) const; + +private: + /// Parses and pulls out arguments for the ImR + int parse_args (int &argc, char *argv[]); + + /// Print the usage information. + void print_usage (void) const; + + /// Loads options from the registry + int load_registry_options (); + +private: + + /// Our extra command line arguments + ACE_CString cmdline_; + + /// Debug level. + unsigned int debug_; + + /// File where the IOR of the server object is stored. + ACE_CString ior_output_file_; + + /// Should we run as a service? + bool service_; + + bool notify_imr_; + + /// SC_NONE, SC_INSTALL, SC_REMOVE, ... + SERVICE_COMMAND service_command_; + + ACE_CString name_; +}; + +#endif diff --git a/TAO/orbsvcs/ImplRepo_Service/Adapter_Activator.cpp b/TAO/orbsvcs/ImplRepo_Service/Adapter_Activator.cpp new file mode 100644 index 00000000000..e68bdbcf4f9 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Adapter_Activator.cpp @@ -0,0 +1,95 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file Adapter_Activator.cpp + * + * $Id$ + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#include "Adapter_Activator.h" + +#include "ace/Log_Msg.h" + +ImR_Adapter::ImR_Adapter (void) +: servant_locator_ (0) +{ +} + +void +ImR_Adapter::init (PortableServer::ServantLocator_ptr servant) +{ + servant_locator_ = servant; +} + +CORBA::Boolean +ImR_Adapter::unknown_adapter (PortableServer::POA_ptr parent, + const char *name + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_ASSERT (! CORBA::is_nil(parent)); + ACE_ASSERT (name != 0); + CORBA::PolicyList policies (2); + policies.length (2); + + const char *exception_message = "Null Message"; + + ACE_TRY + { + // Servant Retention Policy + exception_message = "While PortableServer::POA::create_servant_retention_policy"; + policies[0] = + parent->create_servant_retention_policy (PortableServer::NON_RETAIN ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Request Processing Policy + exception_message = "While PortableServer::POA::create_request_processing_policy"; + policies[1] = + parent->create_request_processing_policy (PortableServer::USE_SERVANT_MANAGER ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + PortableServer::POAManager_var poa_manager = + parent->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + exception_message = "While create_POA"; + PortableServer::POA_var child = + parent->create_POA (name, + poa_manager.in (), + policies + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + exception_message = "While unknown_adapter::policy->destroy"; + for (CORBA::ULong i = 0; i < policies.length (); ++i) + { + CORBA::Policy_ptr policy = policies[i]; + policy->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + exception_message = "While child->the_activator"; + child->the_activator (this ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + exception_message = "While unknown_adapter, set_servant_manager"; + child->set_servant_manager (this->servant_locator_ ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_ERROR ((LM_ERROR, + "IMR_Adapter_Activator::unknown_adapter - %s\n", + exception_message)); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "System Exception"); + return 0; + } + ACE_ENDTRY; + + // Finally, now everything is fine + return 1; +} + diff --git a/TAO/orbsvcs/ImplRepo_Service/Adapter_Activator.h b/TAO/orbsvcs/ImplRepo_Service/Adapter_Activator.h new file mode 100644 index 00000000000..d62d8f3cfcf --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Adapter_Activator.h @@ -0,0 +1,59 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file Adapter_Activator.h + * + * $Id$ + * + * @brief This class implements ImR's Adapter Activator. + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#ifndef IMR_ADAPTER_ACTIVATOR_H +#define IMR_ADAPTER_ACTIVATOR_H + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/AdapterActivatorC.h" +#include "tao/PortableServer/ServantLocatorC.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/LocalObject.h" + + +/** + * @class ImR_Adapter_Activator + * + * @brief Implementation Repository Adapter Activator + * + * Part of the ServantLocator/AdapterActivator combination that is used to + * receive forwardable requests from clients. The Adapter Activator creates + * the POA structure that the request expects. For each POA created, the + * same ServantLocator will be registered in each one. + */ +class ImR_Adapter + : public PortableServer::AdapterActivator, + public CORBA::LocalObject +{ +public: + ImR_Adapter(); + + /// Called when a POA needs to be created. + virtual CORBA::Boolean unknown_adapter ( + PortableServer::POA_ptr parent, + const char *name + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC ((CORBA::SystemException)); + + void init(PortableServer::ServantLocator_ptr servant); +private: + /// The ServantLocator registered in each new POA. + PortableServer::ServantLocator_ptr servant_locator_; +}; + +#endif /* IMR_ADAPTER_ACTIVATOR_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter.idl b/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter.idl new file mode 100644 index 00000000000..92a908888d9 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter.idl @@ -0,0 +1,18 @@ +// -*- IDL -*- + +// $Id$ + +module ImplementationRepository +{ + struct StartupInfo { + string name; + string partial_ior; + string ior; + }; + + interface AsyncStartupWaiter + { + StartupInfo wait_for_startup(in string name); + }; +}; + diff --git a/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter_i.cpp b/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter_i.cpp new file mode 100644 index 00000000000..2cebbc590bd --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter_i.cpp @@ -0,0 +1,171 @@ +// -*- C++ -*- +// +// $Id$ + +#include "AsyncStartupWaiter_i.h" +#include "ImR_Locator_i.h" + +using namespace ImplementationRepository; + +AsyncStartupWaiter_i::PendingData::PendingData (const char* p, const char* i) +: partial_ior (p) +, ior( i) +{ +} + +AsyncStartupWaiter_i::PendingData::PendingData () +{ +} + + +void AsyncStartupWaiter_i::debug (bool dbg) +{ + debug_ = dbg; +} + +void AsyncStartupWaiter_i::wait_for_startup (AMH_AsyncStartupWaiterResponseHandler_ptr rh, + const char* name ACE_ENV_ARG_DECL_NOT_USED) ACE_THROW_SPEC ((CORBA::SystemException)) +{ + PendingListPtr plst; + pending_.find(name, plst); + if (! plst.null () && plst->size () > 0) + { + PendingList& tmp = *plst; + PendingData& pd = tmp[tmp.size () - 1]; + tmp.pop_back (); + + if (debug_) + ACE_DEBUG ((LM_DEBUG, "ImR: Skipping wait due to queued startup info for <%s>.\n", name)); + + send_response (*rh, name, pd.partial_ior.c_str(), pd.ior.c_str()); + + } + else + { + RHListPtr lst; + waiting_.find (name, lst); + if (lst.null ()) + { + lst = RHListPtr (new RHList); + int err = waiting_.bind (name, lst); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); + } + lst->push_back (AMH_AsyncStartupWaiterResponseHandler::_duplicate (rh)); + } +} + +void +AsyncStartupWaiter_i::send_response (ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler& rh, + const char* name, const char* partial_ior, const char* ior) +{ + StartupInfo_var si = new StartupInfo(); + si->name = name; + si->partial_ior = partial_ior; + si->ior = ior; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + rh.wait_for_startup (si.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + if (debug_) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "AsyncStartupWaiter_i::send_response ()"); + } + ACE_ENDTRY; +} + +void +AsyncStartupWaiter_i::unblock_one (const char* name, const char* partial_ior, const char* ior, bool queue) { + ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_var rh = get_one_waiter(name); + if (! CORBA::is_nil(rh.in ())) + { + send_response (*rh.in (), name, partial_ior, ior); + } + else if (queue) + { + if (debug_) + ACE_DEBUG((LM_DEBUG, "ImR: Queuing startup info.\n")); + + PendingListPtr lst; + pending_.find (name, lst); + if (lst.null ()) + { + lst = PendingListPtr (new PendingList); + int err = pending_.bind (name, lst); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); + } + lst->push_back (PendingData (partial_ior, ior)); + } +} + +void +AsyncStartupWaiter_i::unblock_all (const char* name) { + RHList tmp; + + get_all_waiters (name, tmp); + + // This startup info should be ignored when unblocking all, because we + // don't know the ior or partial_ior at this point. + StartupInfo_var si = new StartupInfo (); + si->name = name; + + // Note : This method may be called when there are no waiters. + + for (size_t i = 0; i < tmp.size(); ++i) + { + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_var& rh = tmp[i]; + + rh->wait_for_startup (si.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + if (debug_) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "AsyncStartupWaiter_i::unblock_all ()"); + } + ACE_ENDTRY; + } +} + +ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_ptr +AsyncStartupWaiter_i::get_one_waiter (const char* name) +{ + RHListPtr lst; + waiting_.find (name, lst); + if (! lst.null() && lst->size () > 0) + { + RHList& rhlst = *lst; + ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_var& tmp = rhlst[rhlst.size () - 1]; + ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_ptr ret = tmp._retn (); + rhlst.pop_back (); + return ret; + } + return ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler::_nil (); +} + +void +AsyncStartupWaiter_i::get_all_waiters (const char* name, RHList& ret) +{ + RHListPtr lst; + waiting_.find (name, lst); + if (! lst.null ()) { + for (size_t i = 0; i < lst->size (); ++i) + { + RHList& tmp = *lst; + ret.push_back (tmp[i]); + // The ACE_Vector will not destruct the elements when cleared, so we must + // make sure to do so here. + tmp[i] = ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler::_nil (); + } + lst->clear (); + } +} + diff --git a/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter_i.h b/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter_i.h new file mode 100644 index 00000000000..b4b527e1d40 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/AsyncStartupWaiter_i.h @@ -0,0 +1,75 @@ +// -*- C++ -*- +// +// $Id$ + +#ifndef IMR_AsyncStartupWaiterI_H_ +#define IMR_AsyncStartupWaiterI_H_ + +#include "locator_export.h" +#include "AsyncStartupWaiterS.h" + +#include "ace/Vector_T.h" +#include "ace/Hash_Map_Manager.h" +#include "ace/Bound_Ptr.h" +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +#pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + + +class ImR_Locator_i; + +class Locator_Export AsyncStartupWaiter_i : public virtual POA_ImplementationRepository::AMH_AsyncStartupWaiter +{ + struct PendingData { + PendingData(); + PendingData(const char* partial_ior, const char* ior); + ACE_CString partial_ior; + ACE_CString ior; + }; + typedef ACE_Vector<PendingData> PendingList; + typedef ACE_Strong_Bound_Ptr<PendingList, ACE_Null_Mutex> PendingListPtr; + typedef ACE_Hash_Map_Manager_Ex<ACE_CString, + PendingListPtr, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> PendingMap; + + typedef ACE_Vector<ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_var> RHList; + typedef ACE_Strong_Bound_Ptr<RHList, ACE_Null_Mutex> RHListPtr; + typedef ACE_Hash_Map_Manager_Ex<ACE_CString, + RHListPtr, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> WaitingMap; + +public: + + void wait_for_startup ( + ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_ptr rh, + const char* name ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + + void unblock_one(const char* name, const char* partial_ior, const char* ior, bool queue); + void unblock_all(const char* name); + + void debug(bool dbg); + +private: + +ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler_ptr + get_one_waiter(const char* name); + +void get_all_waiters(const char* name, RHList& ret); + +void send_response(ImplementationRepository::AMH_AsyncStartupWaiterResponseHandler& rh, + const char* name, const char* partial_ior, const char* ior); +private: + WaitingMap waiting_; + PendingMap pending_; + bool debug_; +}; + +#endif /* AsyncStartupWaiterI_H_ */ + diff --git a/TAO/orbsvcs/ImplRepo_Service/Forwarder.cpp b/TAO/orbsvcs/ImplRepo_Service/Forwarder.cpp new file mode 100644 index 00000000000..7337af511e9 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Forwarder.cpp @@ -0,0 +1,162 @@ +//============================================================================= +/** +* @file Forwarder.cpp +* +* $Id$ +* +* @brief Definition of ImR_Forwarder +* +* @author Darrell Brunsch <brunsch@cs.wustl.edu> +* @author Priyanka Gontla <pgontla@doc.ece.uci.edu> +*/ +//============================================================================= + +#include "Forwarder.h" +#include "ImR_Locator_i.h" + +#include "tao/ORB.h" +#include "tao/Object_KeyC.h" +#include "tao/ORB_Constants.h" + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/POA_Current_Impl.h" +#include "tao/PortableServer/POA_Current.h" + +/** +* This constructor takes in orb and ImR_Locator_i pointers to store for later +* use. It also grabs a reference to the POACurrent object for use in +* preinvoke. +*/ +ImR_Forwarder::ImR_Forwarder (ImR_Locator_i& imr_impl) + : locator_ (imr_impl) +{ +} + +void +ImR_Forwarder::init (CORBA::ORB_ptr orb ACE_ENV_ARG_DECL) +{ + ACE_ASSERT (! CORBA::is_nil(orb)); + this->orb_ = orb; + ACE_TRY_NEW_ENV + { + CORBA::Object_var tmp = + orb->resolve_initial_references ("POACurrent" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->poa_current_var_ = + PortableServer::Current::_narrow (tmp.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_DEBUG ((LM_DEBUG, "ImR_Forwarder::init() Exception ignored.\n")); + } + ACE_ENDTRY; + ACE_CHECK; + ACE_ASSERT (!CORBA::is_nil (this->poa_current_var_.in ())); +} + +/** +* We figure out the intended recipient from the POA name. After activating +* the server, we throw a forwarding exception to the correct server. +* +* The big complicated thing here is that we have to create the forwarding +* ior based on what we already have. So we combine the endpoint received +* from activate_server_i and append the objectid from the request to it. +*/ +PortableServer::Servant +ImR_Forwarder::preinvoke (const PortableServer::ObjectId &, + PortableServer::POA_ptr poa, + const char *, + PortableServer::ServantLocator::Cookie & + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, PortableServer::ForwardRequest)) +{ + ACE_ASSERT (! CORBA::is_nil(poa)); + CORBA::Object_var forward_obj; + + ACE_TRY + { + CORBA::String_var server_name = poa->the_name(); + + if (locator_.debug() > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Activating server <%s>.\n", server_name.in())); + + // The activator stores a partial ior with each server. We can + // just tack on the current ObjectKey to get a valid ior for + // the desired server. + CORBA::String_var pior = locator_.activate_server_by_name (server_name.in (), false ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_CString ior = pior.in (); + + // Check that the returned ior is the expected partial ior with + // missing ObjectKey. + if (ior.find ("corbaloc:") != 0 || ior[ior.length () - 1] != '/') + { + ACE_ERROR ((LM_ERROR, "ImR_Forwarder::preinvoke () Invalid corbaloc ior.\n\t<%s>\n", ior.c_str())); + ACE_TRY_THROW (CORBA::OBJECT_NOT_EXIST ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + + CORBA::String_var key_str; + // Unlike POA Current, this implementation cannot be cached. + TAO::Portable_Server::POA_Current* tao_current = + dynamic_cast <TAO::Portable_Server::POA_Current*> (this->poa_current_var_.in ()); + + ACE_ASSERT(tao_current != 0); + TAO::Portable_Server::POA_Current_Impl* impl = tao_current->implementation (); + TAO::ObjectKey::encode_sequence_to_string (key_str.out (), impl->object_key ()); + + ior += key_str.in(); + + if (locator_.debug() > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Forwarding invocation on <%s> to <%s>\n", server_name.in(), ior.c_str())); + + forward_obj = + this->orb_->string_to_object (ior.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (ImplementationRepository::CannotActivate, ex) + { + ACE_TRY_THROW (CORBA::TRANSIENT ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + ACE_CATCH (ImplementationRepository::NotFound, ex) + { + ACE_TRY_THROW (CORBA::TRANSIENT ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Forwarder"); + ACE_TRY_THROW (CORBA::TRANSIENT ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (0); + + if (!CORBA::is_nil (forward_obj.in ())) + ACE_THROW_RETURN (PortableServer::ForwardRequest (forward_obj.in ()), 0); + + ACE_ERROR ((LM_ERROR, "Error: Forward_to reference is nil.\n")); + ACE_THROW_RETURN (CORBA::OBJECT_NOT_EXIST ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO), 0); +} + +void +ImR_Forwarder::postinvoke (const PortableServer::ObjectId &, + PortableServer::POA_ptr, + const char *, + PortableServer::ServantLocator::Cookie, + PortableServer::Servant + ACE_ENV_ARG_DECL_NOT_USED + ) ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + diff --git a/TAO/orbsvcs/ImplRepo_Service/Forwarder.h b/TAO/orbsvcs/ImplRepo_Service/Forwarder.h new file mode 100644 index 00000000000..31bf107b602 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Forwarder.h @@ -0,0 +1,77 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file Forwarder.h + * + * $Id$ + * + * @brief This class implements ImR's forwarding ServantLocator + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + * @author Priyanka Gontla <pgontla@doc.ece.uci.edu> + */ +//============================================================================= + +#ifndef IMR_FORWARDER_H +#define IMR_FORWARDER_H + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/ServantLocatorC.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/LocalObject.h" + + +class ImR_Locator_i; + +/** + * @class ImR_Forwarder: + * + * @brief Implementation Repository Forwarder + * + * This class provides a ServantLocator implementation that + * is used to handle arbitrary calls and forward them to the + * correct place. + */ +class ImR_Forwarder + : public PortableServer::ServantLocator, + public CORBA::LocalObject +{ +public: + ImR_Forwarder (ImR_Locator_i& imr_impl); + + /// Called before the invocation begins. + virtual PortableServer::Servant preinvoke ( + const PortableServer::ObjectId &oid, + PortableServer::POA_ptr poa, + const char * operation, + PortableServer::ServantLocator::Cookie &cookie + ACE_ENV_ARG_DECL + ) ACE_THROW_SPEC ((CORBA::SystemException, PortableServer::ForwardRequest)); + + virtual void postinvoke ( + const PortableServer::ObjectId & oid, + PortableServer::POA_ptr adapter, + const char * operation, + PortableServer::ServantLocator::Cookie the_cookie, + PortableServer::Servant the_servant + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) ACE_THROW_SPEC ((CORBA::SystemException)); + + void init(CORBA::ORB_ptr orb ACE_ENV_ARG_DECL); + +private: + /// Where we find out where to forward to. + ImR_Locator_i& locator_; + + /// POA reference. + PortableServer::Current_var poa_current_var_; + + /// Variable to save the ORB reference passed to the constr. + CORBA::ORB_ptr orb_; +}; + +#endif /* IMR_FORWARDER_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/INS_Locator.cpp b/TAO/orbsvcs/ImplRepo_Service/INS_Locator.cpp new file mode 100644 index 00000000000..3057a8d6622 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/INS_Locator.cpp @@ -0,0 +1,64 @@ +//============================================================================= +/** +* @file INS_Locator.cpp +* +* $Id$ +* +* @brief Implementation of the ImR's INS Locator class +* +* @author Darrell Brunsch <brunsch@cs.wustl.edu> +*/ +//============================================================================= + +#include "INS_Locator.h" +#include "ImR_Locator_i.h" +#include "tao/ORB_Constants.h" + +INS_Locator::INS_Locator (ImR_Locator_i& loc) +: imr_locator_ (loc) +{ +} + +char * +INS_Locator::locate (const char* object_key ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, IORTable::NotFound)) +{ + ACE_ASSERT (object_key != 0); + ACE_TRY + { + ACE_CString key (object_key); + ssize_t poaidx = key.find ('/'); + if (poaidx >= 0) + { + key = key.substring (0, poaidx); + } + + if (imr_locator_.debug () > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Activating server <%s>.\n", key.c_str ())); + + CORBA::String_var located = + this->imr_locator_.activate_server_by_object (key.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_CString tmp = located.in (); + tmp += object_key; + + if (imr_locator_.debug () > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Forwarding invocation on <%s> to <%s>\n", key.c_str (), tmp.c_str())); + + return CORBA::string_dup (tmp.c_str ()); + } + ACE_CATCH (ImplementationRepository::CannotActivate, ex) + { + ACE_TRY_THROW (CORBA::TRANSIENT ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + ACE_CATCH (ImplementationRepository::NotFound, ex) + { + ACE_TRY_THROW (CORBA::TRANSIENT ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + ACE_ENDTRY; +} diff --git a/TAO/orbsvcs/ImplRepo_Service/INS_Locator.h b/TAO/orbsvcs/ImplRepo_Service/INS_Locator.h new file mode 100644 index 00000000000..88fca61b5ba --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/INS_Locator.h @@ -0,0 +1,53 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file INS_Locator.h + * + * $Id$ + * + * @brief This class implements the ImR's INS Locator class + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#ifndef IMR_INS_LOCATOR_H +#define IMR_INS_LOCATOR_H +#include /**/ "ace/pre.h" + +#include "tao/IORTable/IORTable.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +#include "tao/LocalObject.h" + + +class ImR_Locator_i; + +/** + * @class INS_Locator + * + * @brief Implementation Repository INS Locator class + * + * This class provides a callback for the IORTable to call when it needs + * to dynamically receive a IOR to forward in response to an INS request. + */ +class INS_Locator + : public virtual IORTable::Locator, + public virtual CORBA::LocalObject +{ +public: + INS_Locator (ImR_Locator_i& loc); + + /// Locate the appropriate IOR. + char* locate (const char *object_key ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, IORTable::NotFound)); + +private: + ImR_Locator_i& imr_locator_; +}; + +#include /**/ "ace/post.h" +#endif diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR.xsd b/TAO/orbsvcs/ImplRepo_Service/ImR.xsd new file mode 100644 index 00000000000..013bd6dd849 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR.xsd @@ -0,0 +1,30 @@ +<?xml version="1.0" ?> +<xs:schema id="ImplementationRepository" targetNamespace="http://www.theaceorb.com/ImplementationRepository.xsd" xmlns:mstns="http://www.theaceorb.com/ImplementationRepository.xsd" + xmlns="http://www.theaceorb.com/ImplementationRepository.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" + attributeFormDefault="qualified" elementFormDefault="qualified"> + <xs:element name="ImplementationRepository" msdata:IsDataSet="true" msdata:EnforceConstraints="False"> + <xs:complexType> + <xs:choice maxOccurs="unbounded"> + <xs:element name="Servers"> + <xs:complexType> + <xs:attribute name="name" form="unqualified" type="xs:string" /> + <xs:attribute name="activator" form="unqualified" type="xs:string" /> + <xs:attribute name="command_line" form="unqualified" type="xs:string" /> + <xs:attribute name="working_dir" form="unqualified" type="xs:string" /> + <xs:attribute name="activation_mode" form="unqualified" type="xs:string" /> + <xs:attribute name="start_limit" form="unqualified" type="xs:string" /> + <xs:attribute name="partial_ior" form="unqualified" type="xs:string" /> + <xs:attribute name="ior" form="unqualified" type="xs:string" /> + </xs:complexType> + </xs:element> + <xs:element name="Activators"> + <xs:complexType> + <xs:attribute name="name" form="unqualified" type="xs:string" /> + <xs:attribute name="token" form="unqualified" type="xs:string" /> + <xs:attribute name="ior" form="unqualified" type="xs:string" /> + </xs:complexType> + </xs:element> + </xs:choice> + </xs:complexType> + </xs:element> +</xs:schema>
\ No newline at end of file diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Activator.cpp b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator.cpp new file mode 100644 index 00000000000..34da1320caf --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator.cpp @@ -0,0 +1,216 @@ +/* -*- C++ -*- */ +// $Id$ + +#include "Activator_Options.h" +#include "ImR_Activator_i.h" +#include "Activator_NT_Service.h" + +#include "orbsvcs/Shutdown_Utilities.h" + +class ImR_Activator_Shutdown : public Shutdown_Functor +{ +public: + ImR_Activator_Shutdown (ImR_Activator_i& act); + + void operator() (int which_signal); +private: + ImR_Activator_i& act_; +}; + +ImR_Activator_Shutdown::ImR_Activator_Shutdown (ImR_Activator_i &act) + : act_(act) +{ +} + +void +ImR_Activator_Shutdown::operator() (int /*which_signal*/) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->act_.shutdown (true ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR Activator: "); + } + ACE_ENDTRY; +} + +int +run_standalone (Activator_Options& opts) +{ + ImR_Activator_i server; + + ImR_Activator_Shutdown killer (server); + Service_Shutdown kill_contractor (killer); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int status = server.init (opts ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (status == -1) + { + return 1; + } + else + { + // Run the server if it is initialized correctly. + server.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // End the server after its work is done. + status = server.fini (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (status == -1) + return 1; + } + return 0; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, "System Exception"); + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, "User Exception"); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Unknown Exception"); + } + ACE_ENDTRY; + + return 1; +} + +#if defined (ACE_WIN32) +ACE_NT_SERVICE_DEFINE (service, Activator_NT_Service, IMR_ACTIVATOR_SERVICE_NAME); +#endif /* ACE_WIN32 */ + +int +run_service (void) +{ +#if defined (ACE_WIN32) + SERVICE::instance()->name (IMR_ACTIVATOR_SERVICE_NAME, IMR_ACTIVATOR_DISPLAY_NAME); + ACE_NT_SERVICE_RUN (service, SERVICE::instance (), ret); + + if (ret == 0) + ACE_ERROR ((LM_ERROR, "%p\n", "Couldn't start service")); + + return ret; +#else /* ACE_WIN32 */ + return 1; +#endif /* ACE_WIN32 */ +} + +/** + * Executes the various commands that are useful for a NT service. Right + * now these include 'install' and 'remove'. Others, such as 'start' and + * 'stop' can be added, but the 'net' program in Windows already handles + * these commands. + */ +static int +run_service_command (Activator_Options& opts) +{ + if (opts.service_command () == Activator_Options::SC_NONE) + return 0; + +#if defined (ACE_WIN32) + SERVICE::instance()->name (IMR_ACTIVATOR_SERVICE_NAME, IMR_ACTIVATOR_DISPLAY_NAME); + + if (opts.service_command () == Activator_Options::SC_INSTALL || + opts.service_command () == Activator_Options::SC_INSTALL_NO_LOCATOR) + { + const DWORD MAX_PATH_LENGTH = 4096; + char pathname[MAX_PATH_LENGTH]; + + DWORD length = ACE_TEXT_GetModuleFileName(NULL, pathname, MAX_PATH_LENGTH); + if (length == 0 || length >= MAX_PATH_LENGTH - sizeof(" -s")) + { + ACE_ERROR ((LM_ERROR, "Error: Could not get module file name\n")); + return -1; + } + + // Append the command used for running the implrepo as a service + ACE_OS::strcat (pathname, ACE_TEXT (" -s")); + int ret = -1; + if (opts.service_command () == Activator_Options::SC_INSTALL) + { + const char* DEPENDS_ON = "TAOImR"; // Must match Locator_NT_Service.h + + ret = SERVICE::instance ()->insert (SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + pathname, + 0, // group + 0, // tag + DEPENDS_ON + ); + } + else + { + ret = SERVICE::instance ()->insert (SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + pathname); + } + if (ret != -1) + { + ACE_DEBUG ((LM_DEBUG, "ImR Activator: Service installed.\n")); + opts.save_registry_options (); + } + else + { + ACE_ERROR ((LM_ERROR, "Error: Failed to install service.\n")); + } + if (ret == 0) + return 1; + } + else if (opts.service_command () == Activator_Options::SC_REMOVE) + { + int ret = SERVICE::instance ()->remove (); + ACE_DEBUG ((LM_DEBUG, "ImR Activator: Service removed.\n")); + if (ret == 0) + return 1; // If successfull, then we don't want to continue. + } + else + { + ACE_ERROR ((LM_ERROR, "Error: Unknown service command :%d \n", + opts.service_command ())); + return -1; + } + + return -1; + +#else /* ACE_WIN32 */ + ACE_ERROR ((LM_ERROR, "NT Service not supported on this platform")); + return -1; +#endif /* ACE_WIN32 */ +} + +int +main (int argc, char *argv[]) +{ + Activator_Options opts; + + int result = opts.init (argc, argv); + if (result < 0) + return 1; // Error + else if (result > 0) + return 0; // No error, but we should exit anyway. + + result = run_service_command (opts); + if (result < 0) + return 1; // Error + else if (result > 0) + return 0; // No error, but we should exit anyway. + + if (opts.service ()) + return run_service (); + + return run_standalone (opts); +} + diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Activator.idl b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator.idl new file mode 100644 index 00000000000..aa0fecbd401 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator.idl @@ -0,0 +1,18 @@ +// -*- IDL -*- + +// $Id$ + +#include "tao/ImR_Client/ImplRepo.pidl" + +module ImplementationRepository +{ + interface Activator + { + // Tells the activator to launch a server with the given information. + void start_server(in string name, in string cmdline, + in string dir, in EnvironmentList env) raises(CannotActivate); + + oneway void shutdown(); + }; +}; + diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp new file mode 100644 index 00000000000..7017ec1827d --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator_i.cpp @@ -0,0 +1,395 @@ +// $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 ()) +{ +} + +static PortableServer::POA_ptr +createPersistentPOA (PortableServer::POA_ptr root_poa, const char* poa_name ACE_ENV_ARG_DECL) +{ + PortableServer::LifespanPolicy_var life = + root_poa->create_lifespan_policy (PortableServer::PERSISTENT ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + PortableServer::IdAssignmentPolicy_var assign = + root_poa->create_id_assignment_policy (PortableServer::USER_ID ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + 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 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(PortableServer::POA::_nil ()); + + life->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + assign->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + 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.) +void +ImR_Activator_i::register_with_imr (ImplementationRepository::Activator_ptr activator) +{ + ACE_TRY_NEW_ENV + { + 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" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->process_mgr_.open (ACE_Process_Manager::DEFAULT_SIZE, + this->orb_->orb_core ()->reactor ()); + + locator_ = ImplementationRepository::Locator::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (!CORBA::is_nil (locator_.in ())) + { + this->registration_token_ = + locator_->register_activator (name_.c_str (), activator ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (debug_ > 0) + ACE_DEBUG((LM_DEBUG, "ImR Activator: Registered with ImR.\n")); + + return; + } + } + ACE_CATCHANY + { + if (debug_ > 1) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR Activator: Can't register with ImR."); + } + ACE_ENDTRY; + + 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_ENV_ARG_DECL) +{ + ACE_ASSERT(! CORBA::is_nil (orb)); + orb_ = CORBA::ORB::_duplicate (orb); + debug_ = opts.debug (); + notify_imr_ = opts.notify_imr (); + if (opts.name ().length () > 0) + { + name_ = opts.name(); + } + + ACE_TRY + { + CORBA::Object_var obj = orb->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + ACE_ASSERT (! CORBA::is_nil (obj.in ())); + this->root_poa_ = PortableServer::POA::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + 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_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + 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 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + obj = this->imr_poa_->id_to_reference (id.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + ImplementationRepository::Activator_var activator = + ImplementationRepository::Activator::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + ACE_ASSERT(! CORBA::is_nil (activator.in ())); + + CORBA::String_var ior = this->orb_->object_to_string (activator.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + 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 (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + poaman->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + 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); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Activator_i::init_with_orb"); + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +ImR_Activator_i::init (Activator_Options& opts ACE_ENV_ARG_DECL) +{ + 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" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(-1); + + int ret = this->init_with_orb(orb.in (), opts ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN(-1); + + return ret; +} + +int +ImR_Activator_i::fini (ACE_ENV_SINGLE_ARG_DECL) +{ + ACE_TRY_EX (try_block_1) + { + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR Activator: Shutting down...\n")); + + this->process_mgr_.close (); + + this->root_poa_->destroy (1, 1 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK_EX (try_block_1); + + if (! CORBA::is_nil (this->locator_.in ()) && this->registration_token_ != 0) + { + this->locator_->unregister_activator (name_.c_str(), + this->registration_token_ ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK_EX (try_block_1); + } + } + ACE_CATCH(CORBA::COMM_FAILURE, ex) + { + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR Activator: Unable to unregister from ImR.\n")); + } + ACE_CATCH(CORBA::TRANSIENT, ex) + { + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR Activator: Unable to unregister from ImR.\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR Activator: fini"); + ACE_RE_THROW_EX (try_block_1); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + + ACE_TRY_EX (try_block_2) + { + this->orb_->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK_EX (try_block_2); + + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR Activator: Shut down successfully.\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR Activator: fini 2"); + ACE_RE_THROW_EX (try_block_2); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +int +ImR_Activator_i::run (ACE_ENV_SINGLE_ARG_DECL) +{ + this->orb_->run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + return 0; +} + +void +ImR_Activator_i::shutdown (ACE_ENV_SINGLE_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException)) +{ + shutdown (false ACE_ENV_ARG_PARAMETER); +} + +void +ImR_Activator_i::shutdown (bool wait_for_completion ACE_ENV_ARG_DECL) +{ + this->orb_->shutdown (wait_for_completion ACE_ENV_ARG_PARAMETER); +} + +void +ImR_Activator_i::start_server(const char* name, + const char* cmdline, + const char* dir, + const ImplementationRepository::EnvironmentList & env ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::CannotActivate)) +{ + 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; + proc_opts.command_line (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_inheritence (0); + + proc_opts.setenv ("TAO_USE_IMR", "1"); + if (!CORBA::is_nil (this->locator_.in ())) + { + CORBA::String_var ior = orb_->object_to_string (locator_.in ()); + proc_opts.setenv ("ImplRepoServiceIOR", ior.in()); + } + + for (CORBA::ULong i = 0; i < env.length (); ++i) + { + proc_opts.setenv (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)); + + ACE_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>. \n", name)); + } +} + +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; +} diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Activator_i.h b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator_i.h new file mode 100644 index 00000000000..7b62dc525cf --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Activator_i.h @@ -0,0 +1,128 @@ +// -*- C++ -*- +//============================================================================= +/** +* @file ImR_Activator_i.h +* +* $Id$ +* +* @author Priyanka Gontla <gontla_p@ociweb.com> +* @author Darrell Brunsch <brunsch@cs.wustl.edu> +*/ +//============================================================================= + +#ifndef IMR_ACTIVATOR_I_H +#define IMR_ACTIVATOR_I_H + +#include "activator_export.h" + +#include "ImR_ActivatorS.h" +#include "ImR_LocatorC.h" + +#include "ace/Process_Manager.h" +#include "ace/Hash_Map_Manager.h" +#include "ace/Null_Mutex.h" +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class Activator_Options; + +// ace/Functor.h doesn't provide functors for every built in integer type. +// Depending on the platform and what pid_t maps to, the functors may be missing. +struct ACE_Hash_pid_t +{ + unsigned long operator () (pid_t t) const + { + return t; + } +}; + +struct ACE_Equal_To_pid_t +{ + int operator () (const pid_t lhs, const pid_t rhs) const + { + return lhs == rhs; + } +}; + + +/** +* @class ImR_Activator_i +* +* @brief IMR Activator Interface. +* +* This class provides the interface for the various activities +* that can be done by the ImR_Activator. +* +*/ +class Activator_Export ImR_Activator_i : public POA_ImplementationRepository::Activator, + public ACE_Event_Handler +{ +public: + ImR_Activator_i (void); + + void start_server ( + const char* name, + const char* cmdline, + const char* dir, + const ImplementationRepository::EnvironmentList & env ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::CannotActivate)); + + void shutdown(ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + + /// Initialize the Server state - parsing arguments and waiting. + int init (Activator_Options& opts ACE_ENV_ARG_DECL_WITH_DEFAULTS); + + /// Cleans up any state created by init*. + int fini (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + + /// Runs the orb. + int run (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS); + + /// Shutdown the orb. + void shutdown (bool wait_for_completion ACE_ENV_ARG_DECL); + +private: + + int init_with_orb (CORBA::ORB_ptr orb, const Activator_Options& opts ACE_ENV_ARG_DECL_WITH_DEFAULTS); + + void register_with_imr(ImplementationRepository::Activator_ptr activator); + + // Handles the death of the child processes of the ImR_Activator. + // Informs the ImR_Locator too. + int handle_exit (ACE_Process * process); + +private: + + typedef ACE_Hash_Map_Manager_Ex<pid_t, + ACE_CString, + ACE_Hash_pid_t, + ACE_Equal_To_pid_t, + ACE_Null_Mutex> ProcessMap; + + ACE_Process_Manager process_mgr_; + + PortableServer::POA_var root_poa_; + PortableServer::POA_var imr_poa_; + + ImplementationRepository::Locator_var locator_; + + /// We're given a token when registering with the locator, which + /// we must use when unregistering. + CORBA::Long registration_token_; + + CORBA::ORB_var orb_; + + unsigned int debug_; + + bool notify_imr_; + + ACE_CString name_; + + ProcessMap process_map_; +}; + +#endif /* IMR_ACTIVATOR_I_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Locator.cpp b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator.cpp new file mode 100644 index 00000000000..12be58dd8cd --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator.cpp @@ -0,0 +1,201 @@ +// $Id$ + +#include "ImR_Locator_i.h" +#include "Locator_NT_Service.h" +#include "Locator_Options.h" +#include "orbsvcs/Shutdown_Utilities.h" + +class ImR_Locator_Shutdown : public Shutdown_Functor +{ +public: + ImR_Locator_Shutdown (ImR_Locator_i& imr); + + void operator() (int which_signal); +private: + ImR_Locator_i& imr_; +}; + +ImR_Locator_Shutdown::ImR_Locator_Shutdown (ImR_Locator_i &imr) + : imr_(imr) +{ +} + +void +ImR_Locator_Shutdown::operator () (int /*which_signal*/) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->imr_.shutdown (true ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR: "); + } + ACE_ENDTRY; +} + +int +run_standalone (Options& opts) +{ + ImR_Locator_i server; + + ImR_Locator_Shutdown killer (server); + Service_Shutdown kill_contractor(killer); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int status = server.init (opts ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + if (status == -1) + { + return 1; + } + else + { + // Run the server if it is initialized correctly. + server.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // End the server after its work is done. + status = server.fini (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (status == -1) + return 1; + } + return 0; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, "System Exception"); + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, "User Exception"); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Unknown Exception"); + } + ACE_ENDTRY; + + return 1; +} + +#if defined (ACE_WIN32) +ACE_NT_SERVICE_DEFINE (service, Locator_NT_Service, IMR_LOCATOR_SERVICE_NAME); +#endif /* ACE_WIN32 */ + +int +run_service (void) +{ +#if defined (ACE_WIN32) + + SERVICE::instance ()->name (IMR_LOCATOR_SERVICE_NAME, IMR_LOCATOR_DISPLAY_NAME); + + ACE_NT_SERVICE_RUN (service, SERVICE::instance (), ret); + + if (ret == 0) + ACE_ERROR ((LM_ERROR, "%p\n", "Couldn't start service")); + + return ret; +#else /* ACE_WIN32 */ + return 1; +#endif /* ACE_WIN32 */ +} + +/** + * Executes the various commands that are useful for a NT service. Right + * now these include 'install' and 'remove'. Others, such as 'start' and + * 'stop' can be added, but the 'net' program in Windows already handles + * these commands. + */ +static int +run_service_command (Options& opts) +{ + if (opts.service_command () == Options::SC_NONE) + return 0; + +#if defined (ACE_WIN32) + SERVICE::instance()->name (IMR_LOCATOR_SERVICE_NAME, IMR_LOCATOR_DISPLAY_NAME); + + if (opts.service_command () == Options::SC_INSTALL) + { + const DWORD MAX_PATH_LENGTH = 4096; + char pathname[MAX_PATH_LENGTH]; + + DWORD length = ACE_TEXT_GetModuleFileName (NULL, pathname, MAX_PATH_LENGTH); + if (length == 0 || length >= MAX_PATH_LENGTH - sizeof(" -s")) + { + ACE_ERROR ((LM_ERROR, "Error: Could not get module file name\n")); + return -1; + } + + // Append the command used for running the implrepo as a service + ACE_OS::strcat (pathname, ACE_TEXT (" -s")); + + int ret = SERVICE::instance ()->insert (SERVICE_DEMAND_START, + SERVICE_ERROR_NORMAL, + pathname); + if (ret != -1) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Service installed.\n")); + opts.save_registry_options (); + } + else + { + ACE_ERROR ((LM_ERROR, "Error: Failed to install service. error:%d\n", errno)); + } + if (ret == 0) + return 1; + } + else if (opts.service_command () == Options::SC_REMOVE) + { + int ret = SERVICE::instance ()->remove (); + ACE_DEBUG ((LM_DEBUG, "ImR: Service removed.\n")); + if (ret == 0) + return 1; // If successfull, then we don't want to continue. + } + else + { + ACE_ERROR ((LM_ERROR, "Error: Unknown service command :%d \n", + opts.service_command ())); + return -1; + } + + return -1; + +#else /* ACE_WIN32 */ + ACE_ERROR ((LM_ERROR, "NT Service not supported on this platform")); + return -1; +#endif /* ACE_WIN32 */ +} + +int +main (int argc, char *argv[]) +{ + Options opts; + + int result = opts.init (argc, argv); + if (result < 0) + return 1; // Error + else if (result > 0) + return 0; // No error, but we should exit anyway. + + result = run_service_command(opts); + if (result < 0) + return 1; // Error + else if (result > 0) + return 0; // No error, but we should exit anyway. + + if (opts.service ()) + { + return run_service (); + } + + return run_standalone (opts); +} + diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Locator.idl b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator.idl new file mode 100644 index 00000000000..acae98bb07f --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator.idl @@ -0,0 +1,22 @@ +// -*- IDL -*- + +// $Id$ + +#include "ImR_Activator.idl" + +module ImplementationRepository +{ + interface Locator : Administration + { + // returns a token that can be used (along with activator name) to unregister the activator. + long register_activator (in string name, in Activator act); + + // You must pass in the token returned from register_activator. + void unregister_activator (in string name, in long token); + + // The ImR_Activator calls this method to notify death of child + // process that it had started. + void notify_child_death (in string name); + }; +}; + diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp new file mode 100644 index 00000000000..95684378c77 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.cpp @@ -0,0 +1,1532 @@ +// $Id$ + +#include "ImR_Locator_i.h" +#include "utils.h" +#include "Iterator.h" +#include "INS_Locator.h" + +#include "orbsvcs/Time_Utilities.h" + +#include "tao/IORTable/IORTable.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/ORB_Core.h" +#include "tao/default_ports.h" +#include "tao/Messaging/Messaging.h" +#include "tao/AnyTypeCode/Any.h" + +#include "ace/ARGV.h" +#include "ace/OS_NS_sys_time.h" +#include "ace/Vector_T.h" + +static const int DEFAULT_START_LIMIT = 1; + +static const int PING_RETRY_SCHEDULE[] = {0, 10, 100, 500, 1000, 1000, 1000, 1000, 5000, 5000}; + +static const ACE_Time_Value DEFAULT_SERVER_TIMEOUT (0, 10 * 1000); // 10ms +// We want to give shutdown a little more time to work, so that we +// can guarantee to the tao_imr utility that it has shutdown. The tao_imr +// utility prints a different message depending on whether shutdown succeeds +// or times out. +static const ACE_Time_Value DEFAULT_SHUTDOWN_TIMEOUT (0, 5000 * 1000); + +static PortableServer::POA_ptr +createPersistentPOA (PortableServer::POA_ptr root_poa, const char* poa_name ACE_ENV_ARG_DECL) { + + PortableServer::LifespanPolicy_var life = + root_poa->create_lifespan_policy (PortableServer::PERSISTENT ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + PortableServer::IdAssignmentPolicy_var assign = + root_poa->create_id_assignment_policy (PortableServer::USER_ID ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + 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 ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + life->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + assign->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (PortableServer::POA::_nil ()); + + return poa._retn (); +} + +ImR_Locator_i::ImR_Locator_i (void) + : forwarder_ (*this) + , ins_locator_ (0) + , debug_ (0) + , read_only_ (false) +{ + // Visual C++ 6.0 is not smart enough to do a direct assignment + // while allocating the INS_Locator. So, we have to do it in + // two steps. + INS_Locator* locator; + ACE_NEW (locator, + INS_Locator (*this)); + ins_locator_ = locator; +} + +ImR_Locator_i::~ImR_Locator_i (void) +{ + // For some reason g++ 4.0 needs this out-of-line destructor instead + // of the default one generated by the compiler. Without this + // destructor, we get a number of "undefined reference" link errors + // related to the virtual tables of the INS_Locator, ImR_Adapter and + // ImR_Forwarder members in this class. +} + +int +ImR_Locator_i::init_with_orb (CORBA::ORB_ptr orb, Options& opts ACE_ENV_ARG_DECL) +{ + orb_ = CORBA::ORB::_duplicate (orb); + debug_ = opts.debug (); + read_only_ = opts.readonly (); + startup_timeout_ = opts.startup_timeout (); + ping_interval_ = opts.ping_interval (); + + CORBA::Object_var obj = + this->orb_->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + this->root_poa_ = PortableServer::POA::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + ACE_ASSERT (! CORBA::is_nil (this->root_poa_.in ())); + + this->forwarder_.init (orb ACE_ENV_ARG_PARAMETER); + this->adapter_.init (& this->forwarder_); + + // Register the Adapter_Activator reference to be the RootPOA's + // Adapter Activator. + root_poa_->the_activator (&this->adapter_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Use a persistent POA so that any IOR + this->imr_poa_ = createPersistentPOA (this->root_poa_.in (), + "ImplRepo_Service" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + ACE_ASSERT (! CORBA::is_nil (this->imr_poa_.in ())); + + waiter_svt_.debug (debug_ > 1); + PortableServer::ObjectId_var id = PortableServer::string_to_ObjectId ("ImR_AsyncStartupWaiter"); + this->imr_poa_->activate_object_with_id (id.in (), &waiter_svt_ ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + obj = this->imr_poa_->id_to_reference (id.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + if (startup_timeout_ > ACE_Time_Value::zero) + { + obj = set_timeout_policy (obj.in (), startup_timeout_); + } + waiter_ = ImplementationRepository::AsyncStartupWaiter::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + id = PortableServer::string_to_ObjectId ("ImplRepo_Service"); + this->imr_poa_->activate_object_with_id (id.in (), this ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + obj = this->imr_poa_->id_to_reference (id.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + CORBA::String_var ior = this->orb_->object_to_string (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Register the ImR for use with INS + obj = orb->resolve_initial_references ("IORTable" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + IORTable::Table_var ior_table = IORTable::Table::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + ACE_ASSERT (! CORBA::is_nil (ior_table.in ())); + ior_table->bind ("ImplRepoService", ior.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + ior_table->bind ("ImR", ior.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + ior_table->set_locator (this->ins_locator_.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // Set up multicast support (if enabled) + if (opts.multicast ()) + { + ACE_Reactor* reactor = orb->orb_core ()->reactor (); + if (this->setup_multicast (reactor, ior.in ()) != 0) + return -1; + } + + // Initialize the persistent storage. This will load any values that + // may have been persisted before. + // The init can return 1 if there is no persistent file yet. In + // that case, we need not do anything for now. + int init_result = + this->repository_.init (opts); + if (init_result == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, "Repository failed to initialize\n"), -1); + } + + // Activate the two poa managers + PortableServer::POAManager_var poaman = + this->root_poa_->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + poaman->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + poaman = this->imr_poa_->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + poaman->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + // We write the ior file last so that the tests can know we are ready. + if (opts.ior_filename ().length () > 0) + { + FILE* fp = ACE_OS::fopen (opts.ior_filename ().c_str (), "w"); + if (fp == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + "ImR: Could not open file: %s\n", opts.ior_filename ().c_str ()), -1); + } + ACE_OS::fprintf (fp, "%s", ior.in ()); + ACE_OS::fclose (fp); + } + + return 0; +} + +int +ImR_Locator_i::init (Options& opts ACE_ENV_ARG_DECL) +{ + ACE_CString cmdline = opts.cmdline (); + cmdline += " -orbcollocation no -orbuseimr 0"; + ACE_ARGV av (cmdline.c_str ()); + int argc = av.argc (); + char** argv = av.argv (); + + CORBA::ORB_var orb = CORBA::ORB_init (argc, argv, "TAO_ImR_Locator" ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + int err = this->init_with_orb (orb.in (), opts ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + return err; +} + +int +ImR_Locator_i::run (ACE_ENV_SINGLE_ARG_DECL) +{ + if (debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, "Implementation Repository: Running\n" + "\tPing Interval : %dms\n" + "\tStartup Timeout : %ds\n" + "\tPersistence : %s\n" + "\tMulticast : %s\n" + "\tDebug : %d\n" + "\tLocked : %s\n\n", + ping_interval_.msec (), + startup_timeout_.sec (), + repository_.repo_mode (), + ior_multicast_.reactor () != 0 ? "Enabled" : "Disabled", + debug (), + read_only_ ? "True" : "False")); + } + this->auto_start_servers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + this->orb_->run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + return 0; +} + +void +ImR_Locator_i::shutdown (CORBA::Boolean activators, CORBA::Boolean servers ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (servers != 0 && this->repository_.servers ().current_size () > 0) + { + // Note : shutdown is oneway, so we can't throw + ACE_ERROR ((LM_ERROR, "ImR: Shutdown of all servers not implemented.\n")); + } + if (activators != 0 && this->repository_.activators ().current_size () > 0) + { + ACE_Vector<ImplementationRepository::Activator_var> acts; + Locator_Repository::AIMap::ENTRY* entry = 0; + Locator_Repository::AIMap::ITERATOR it (this->repository_.activators ()); + for (;it.next (entry) != 0; it.advance ()) + { + Activator_Info_Ptr info = entry->int_id_; + ACE_ASSERT (! info.null ()); + connect_activator (*info); + if (! CORBA::is_nil (info->activator.in ())) + acts.push_back (info->activator); + } + + int shutdown_errs = 0; + + for (size_t i = 0; i < acts.size (); ++i) + { + ACE_TRY + { + acts[i]->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + acts[i] = ImplementationRepository::Activator::_nil (); + } + ACE_CATCHANY + { + ++shutdown_errs; + if (debug_ > 1) + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR: shutdown activator"); + } + } + ACE_ENDTRY; + ACE_CHECK; + } + if (debug_ > 0 && shutdown_errs > 0) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Some activators could not be shut down.\n")); + } + } + // Technically, we should wait for all the activators to unregister, but + // ,for now at least, it doesn't seem worth it. + shutdown (false ACE_ENV_ARG_PARAMETER); +} + +void +ImR_Locator_i::shutdown (bool wait_for_completion ACE_ENV_ARG_DECL) +{ + this->orb_->shutdown (wait_for_completion ACE_ENV_ARG_PARAMETER); +} + +int +ImR_Locator_i::fini (ACE_ENV_SINGLE_ARG_DECL) +{ + ACE_TRY + { + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Shutting down...\n")); + + teardown_multicast (); + + this->root_poa_->destroy (1, 1 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->orb_->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Shut down successfully.\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::fini"); + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK_RETURN (-1); + return 0; +} + +void +ImR_Locator_i::teardown_multicast () +{ + ACE_Reactor* r = ior_multicast_.reactor (); + if (r != 0) { + r->remove_handler (&ior_multicast_, ACE_Event_Handler::READ_MASK); + ior_multicast_.reactor (0); + } +} + +int +ImR_Locator_i::setup_multicast (ACE_Reactor* reactor, const char* ior) +{ + ACE_ASSERT (reactor != 0); + ACE_ASSERT (ior != 0); +#if defined (ACE_HAS_IP_MULTICAST) + + TAO_ORB_Core* core = TAO_ORB_Core_instance (); + // See if the -ORBMulticastDiscoveryEndpoint option was specified. + ACE_CString mde (core->orb_params ()->mcast_discovery_endpoint ()); + + if (mde.length () != 0) + { + if (this->ior_multicast_.init (ior, + mde.c_str (), TAO_SERVICEID_IMPLREPOSERVICE) == -1) + { + return -1; + } + } + else + { + // Port can be specified as param, env var, or default + CORBA::UShort port = + core->orb_params ()->service_port (TAO::MCAST_IMPLREPOSERVICE); + if (port == 0) + { + // Check environment var. for multicast port. + const char* port_number = ACE_OS::getenv ("ImplRepoServicePort"); + + if (port_number != 0) + port = static_cast<CORBA::UShort> (ACE_OS::atoi (port_number)); + } + if (port == 0) + port = TAO_DEFAULT_IMPLREPO_SERVER_REQUEST_PORT; + + if (this->ior_multicast_.init (ior, port, + ACE_DEFAULT_MULTICAST_ADDR, TAO_SERVICEID_IMPLREPOSERVICE) == -1) + { + return -1; + } + } + + // Register event handler for the ior multicast. + if (reactor->register_handler (&this->ior_multicast_, + ACE_Event_Handler::READ_MASK) == -1) + { + if (debug_ >= 1) + ACE_DEBUG ((LM_DEBUG, "ImR: cannot register Event handler\n")); + return -1; + } +#else /* ACE_HAS_IP_MULTICAST*/ + ACE_UNUSED_ARG (reactor); + ACE_UNUSED_ARG (ior); +#endif /* ACE_HAS_IP_MULTICAST*/ + return 0; +} + +CORBA::Long +ImR_Locator_i::register_activator (const char* aname, + ImplementationRepository::Activator_ptr activator + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_ASSERT (aname != 0); + ACE_ASSERT (! CORBA::is_nil (activator)); + + // Before we can register the activator, we need to ensure that any existing + // registration is purged. + this->unregister_activator_i (aname); + ACE_CHECK_RETURN (0); + + CORBA::String_var ior = + this->orb_->object_to_string (activator ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (-1); + + CORBA::Long token = ACE_OS::gettimeofday ().msec (); + + int err = this->repository_.add_activator (aname, token, ior.in (), activator); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Activator registered for %s.\n", aname)); + + return token; +} + +void +ImR_Locator_i::unregister_activator (const char* aname, + CORBA::Long token + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_ASSERT (aname != 0); + Activator_Info_Ptr info = this->get_activator (aname); + + if (! info.null ()) + { + if (info->token != token && this->debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Ignoring unregister activator:%s. Wrong token.\n", aname)); + return; + } + + this->unregister_activator_i (aname); + ACE_CHECK; + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Activator %s unregistered.\n", aname)); + } + else + { + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Ignoring unregister activator:%s. Unknown activator.\n", aname)); + } +} + +void +ImR_Locator_i::unregister_activator_i (const char* aname) +{ + ACE_ASSERT (aname != 0); + int err = this->repository_.remove_activator (aname); + ACE_UNUSED_ARG (err); +} + +void +ImR_Locator_i::notify_child_death (const char* name ACE_ENV_ARG_DECL_NOT_USED) +ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_ASSERT (name != 0); + + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Server has died <%s>.\n", name)); + + Server_Info_Ptr info = this->repository_.get_server (name); + if (! info.null ()) + { + info->ior = ""; + info->partial_ior = ""; + + int err = this->repository_.update_server (*info); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); + } + else + { + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, + "ImR: Failed to find server in repository.\n")); + } +} + +void +ImR_Locator_i::activate_server (const char* server ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Manually activating server <%s>\n", server)); + + // This is the version called by tao_imr to activate the server, manually + // starting it if necessary. + activate_server_by_name (server, true ACE_ENV_ARG_PARAMETER); +} + +char* +ImR_Locator_i::activate_server_by_name (const char* name, bool manual_start ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + // Activate the server, starting it if necessary. Don't start MANUAL + // servers unless manual_start=true + ACE_ASSERT (name != 0); + + Server_Info_Ptr info = this->repository_.get_server (name); + if (info.null ()) + { + ACE_ERROR ((LM_ERROR, "ImR: Cannot find info for server <%s>\n", name)); + ACE_THROW_RETURN (ImplementationRepository::NotFound (), 0); + } + + return activate_server_i (*info, manual_start ACE_ENV_ARG_PARAMETER); +} + +char* +ImR_Locator_i::activate_server_by_object (const char* object_name ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + ACE_ASSERT (object_name != 0); + + // We assume that the first part of the object name is the server name. + // So a name of foo/bar means that the server name is foo. + ACE_CString server_name (object_name); + ACE_CString::size_type pos = server_name.find ('/'); + if (pos != ACE_CString::npos) + server_name = server_name.substr (pos + 1); + + return activate_server_by_name (server_name.c_str (), false ACE_ENV_ARG_PARAMETER); +} + +char* +ImR_Locator_i::activate_server_i (Server_Info& info, bool manual_start ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + if (info.activation_mode == ImplementationRepository::PER_CLIENT) + { + return activate_perclient_server_i (info, manual_start ACE_ENV_ARG_PARAMETER); + } + + while (true) + { + if (is_alive (info)) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Successfully activated <%s> at \n\t%s\n", + info.name.c_str (), info.partial_ior.c_str ())); + } + info.start_count = 0; + + waiter_svt_.unblock_all (info.name.c_str ()); + + return CORBA::string_dup (info.partial_ior.c_str ()); + } + + info.reset (); + + if (! info.starting && info.start_count >= info.start_limit) + { + if (this->debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: Cannot Activate <%s>.\n", info.name.c_str ())); + } + + waiter_svt_.unblock_all (info.name.c_str ()); + + ACE_THROW_RETURN (ImplementationRepository::CannotActivate + (CORBA::string_dup ("Cannot start server.")), 0); + } + + // Note : We already updated info with StartupInfo in server_is_running () + ImplementationRepository::StartupInfo_var si = + start_server (info, manual_start ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + } +} + +char* +ImR_Locator_i::activate_perclient_server_i (Server_Info info, bool manual_start ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + do + { + ImplementationRepository::StartupInfo* psi = + start_server (info, manual_start ACE_ENV_ARG_PARAMETER); + ACE_CHECK_RETURN (0); + + if (psi != 0) + { + ImplementationRepository::StartupInfo_var si = psi; + ACE_ASSERT (info.name == si->name.in ()); + info.partial_ior = si->partial_ior.in (); + info.ior = si->ior.in (); + + if (is_alive (info)) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Successfully activated <%s> at \n\t%s\n", + info.name.c_str (), info.partial_ior.c_str ())); + } + return CORBA::string_dup (info.partial_ior.c_str ()); + } + info.reset (); + } + } while (info.start_count < info.start_limit); + + if (this->debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: Cannot Activate <%s>.\n", info.name.c_str ())); + } + ACE_THROW_RETURN (ImplementationRepository::CannotActivate + (CORBA::string_dup ("Cannot start server.")), 0); +} + +ImplementationRepository::StartupInfo* +ImR_Locator_i::start_server (Server_Info& info, bool manual_start ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)) +{ + if (info.activation_mode == ImplementationRepository::MANUAL && ! manual_start) + { + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Cannot start server <%s>. ActivationMode=MANUAL\n", info.name.c_str ())); + ACE_THROW_RETURN (ImplementationRepository::CannotActivate + (CORBA::string_dup ("Cannot implicitly activate MANUAL server.")), 0); + } + if (info.cmdline.length () == 0) + { + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Cannot start server <%s>." + " No command line.\n", info.name.c_str ())); + ACE_THROW_RETURN (ImplementationRepository::CannotActivate + (CORBA::string_dup ("No command line registered for server.")), 0); + } + + Activator_Info_Ptr ainfo = get_activator (info.activator); + + if (ainfo.null () || CORBA::is_nil (ainfo->activator.in ())) + { + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Cannot start server <%s>. " + "Activator <%s> not found.\n", info.name.c_str (), info.activator.c_str ())); + ACE_THROW_RETURN (ImplementationRepository::CannotActivate + (CORBA::string_dup ("No activator registered for server.")), 0); + } + + ACE_TRY + { + ++ info.waiting_clients; + + if (info.waiting_clients <= 1 || info.activation_mode == ImplementationRepository::PER_CLIENT) + { + info.starting = true; + ++info.start_count; + ACE_ASSERT (info.start_count <= info.start_limit); + if (this->debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Starting server <%s>. Attempt %d/%d.\n", + info.name.c_str (), info.start_count, info.start_limit)); + } + ainfo->activator->start_server ( + info.name.c_str (), + info.cmdline.c_str (), + info.dir.c_str (), + info.env_vars + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + if (info.partial_ior.length () == 0) + { + if (this->debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Waiting for <%s> to start...\n", info.name.c_str ())); + } + + ImplementationRepository::StartupInfo_var si = + waiter_->wait_for_startup (info.name.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + -- info.waiting_clients; + info.starting = false; + + return si._retn (); + } + else // The server_is_running () came in before the wait_for_startup () + { + if (this->debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, "ImR: <%s> Skipping wait. Already started.\n", info.name.c_str ())); + } + -- info.waiting_clients; + info.starting = false; + } + } + ACE_CATCH (CORBA::TIMEOUT, ex) + { + -- info.waiting_clients; + info.starting = false; + // We may have connected successfully, because the timeout could occur before + // the AsyncStartupWaiter manages to return. In fact, when the ImR is very busy + // this is the most likely code path. + if (info.partial_ior.length () == 0) + { + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR : Timeout waiting for <%s> to start.\n", info.name.c_str ())); + info.reset (); + } + } + ACE_CATCH (ImplementationRepository::CannotActivate, ex) + { + -- info.waiting_clients; + info.starting = false; + info.reset (); + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Activator cannot start <%s>.\n", info.name.c_str ())); + } + ACE_CATCHANY + { + -- info.waiting_clients; + info.starting = false; + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Unexpected exception while starting <%s>.\n", info.name.c_str ())); + if (debug_ > 1) + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, ""); + ainfo->reset (); + info.reset (); + } + ACE_ENDTRY; + return 0; // This is not a corba call, so a zero should be ok +} + +CORBA::Object_ptr +ImR_Locator_i::set_timeout_policy (CORBA::Object_ptr obj, const ACE_Time_Value& to) +{ + CORBA::Object_var ret (CORBA::Object::_duplicate (obj)); + + ACE_TRY_NEW_ENV + { + TimeBase::TimeT timeout; + ORBSVCS_Time::Time_Value_to_TimeT (timeout, to); + CORBA::Any tmp; + tmp <<= timeout; + + CORBA::PolicyList policies (1); + policies.length (1); + policies[0] = orb_->create_policy (Messaging::RELATIVE_RT_TIMEOUT_POLICY_TYPE, tmp ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ret = obj->_set_policy_overrides (policies, CORBA::ADD_OVERRIDE ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + policies[0]->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (ret.in ())) + { + if (this->debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Unable to set timeout policy.\n")); + } + ret = CORBA::Object::_duplicate (obj); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ImR_Locator_i::set_timeout_policy ()"); + } + ACE_ENDTRY; + + return ret._retn (); +} + +void +ImR_Locator_i::add_or_update_server (const char* server, + const ImplementationRepository::StartupOptions &options + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound)) +{ + ACE_ASSERT (server != 0); + + if (this->read_only_) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Cannot add/update server <%s> due to locked database.\n", server)); + ACE_THROW (CORBA::NO_PERMISSION ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + + if (debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Add/Update server <%s>.\n", server)); + + int limit = options.start_limit; + if (limit < 0) + { + limit = -limit; + } + else if (limit == 0) + { + limit = 1; + } + + Server_Info_Ptr info = this->repository_.get_server (server); + if (info.null ()) + { + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Adding server <%s>.\n", server)); + + this->repository_.add_server (server, + options.activator.in (), + options.command_line.in (), + options.environment, + options.working_directory.in (), + options.activation, + limit); + } + else + { + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Updating server <%s>.\n", server)); + + info->activator = options.activator.in (); + info->cmdline = options.command_line.in (); + info->env_vars = options.environment; + info->dir = options.working_directory.in (); + info->activation_mode = options.activation; + info->start_limit = limit; + info->start_count = 0; + int err = this->repository_.update_server (*info); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); + } + + if (this->debug_ > 1) + { + // Note : The info var may be null, so we use options. + ACE_DEBUG ((LM_DEBUG, "ImR: Server: %s\n" + "\tActivator: %s\n" + "\tCommand Line: %s\n" + "\tWorking Directory: %s\n" + "\tActivation: %s\n" + "\tStart Limit: %d\n" + "\n", + server, + options.activator.in (), + options.command_line.in (), + options.working_directory.in (), + ImR_Utils::activationModeToString (options.activation).c_str (), + limit + )); + + for (CORBA::ULong i = 0; i < options.environment.length (); ++i) + ACE_DEBUG ((LM_DEBUG, "Environment variable %s=%s\n", + options.environment[i].name.in (), + options.environment[i].value.in ())); + } +} + +void +ImR_Locator_i::remove_server (const char* name ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +{ + ACE_ASSERT (name != 0); + if (this->read_only_) + { + ACE_ERROR ((LM_ERROR, + "ImR: Can't remove server <%s> due to locked database.\n", name)); + ACE_THROW (CORBA::NO_PERMISSION ( + CORBA::SystemException::_tao_minor_code (TAO_IMPLREPO_MINOR_CODE, 0), + CORBA::COMPLETED_NO)); + } + + // Note : This will be safe, because any Server_Info_Ptr objects will still + // be valid, and the actual Server_Info will be destroyed when the last + // one goes out of scope. + + Server_Info_Ptr info = this->repository_.get_server (name); + if (! info.null ()) + { + if (this->repository_.remove_server (name) == 0) + { + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Removing Server <%s>...\n", name)); + + PortableServer::POA_var poa = findPOA (name); + ACE_CHECK; + if (! CORBA::is_nil (poa.in ())) + { + bool etherealize = true; + bool wait = false; + poa->destroy (etherealize, wait ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Removed Server <%s>.\n", name)); + } + } + else + { + ACE_ERROR ((LM_ERROR, + "ImR: Can't remove unknown server <%s>.\n", name)); + ACE_THROW (ImplementationRepository::NotFound ()); + } +} + +PortableServer::POA_ptr +ImR_Locator_i::findPOA (const char* name) +{ + ACE_TRY_NEW_ENV + { + bool activate_it = false; + return root_poa_->find_POA (name, activate_it ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + {// Ignore + } + ACE_ENDTRY; + return PortableServer::POA::_nil (); +} + +void +ImR_Locator_i::shutdown_server (const char* server ACE_ENV_ARG_DECL) +ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +{ + ACE_ASSERT (server != 0); + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Shutting down server <%s>.\n", server)); + + Server_Info_Ptr info = this->repository_.get_server (server); + if (info.null ()) + { + ACE_ERROR ((LM_ERROR, + "ImR: shutdown_server () Cannot find info for server <%s>\n", server)); + ACE_THROW (ImplementationRepository::NotFound ()); + } + + connect_server (*info); + + if (CORBA::is_nil (info->server.in ())) + { + ACE_ERROR ((LM_ERROR, + "ImR: shutdown_server () Cannot connect to server <%s>\n", server)); + ACE_THROW (ImplementationRepository::NotFound ()); + } + + ACE_TRY_NEW_ENV + { + CORBA::Object_var obj = set_timeout_policy (info->server.in (), DEFAULT_SHUTDOWN_TIMEOUT); + ImplementationRepository::ServerObject_var server = + ImplementationRepository::ServerObject::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + server->shutdown (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCH (CORBA::TIMEOUT, ex) + { + info->reset (); + int err = this->repository_.update_server (*info); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); + // Note : This is a good thing. It means we didn't waste our time waiting for + // the server to finish shutting down. + if (this->debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Timeout while waiting for <%s> shutdown.\n", server)); + } + ACE_RE_THROW; + } + ACE_CATCHANY + { + if (this->debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, "ImR: Exception ignored while shutting down <%s>\n", server)); + } + } + ACE_ENDTRY; + + // Note : In most cases this has already been done in the server_is_shutting_down () + // operation, but it doesn't hurt to update it again. + info->reset (); + + int err = this->repository_.update_server (*info); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); +} + +void +ImR_Locator_i::server_is_running (const char* name, + const char* partial_ior, + ImplementationRepository::ServerObject_ptr server + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound)) +{ + ACE_ASSERT (name != 0); + ACE_ASSERT (partial_ior != 0); + ACE_ASSERT (! CORBA::is_nil (server)); + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Server %s is running at %s.\n", name, partial_ior)); + + CORBA::String_var ior = orb_->object_to_string (server ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Server %s callback at %s.\n", name, ior.in ())); + + Server_Info_Ptr info = this->repository_.get_server (name); + if (info.null ()) + { + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Auto adding NORMAL server <%s>.\n", name)); + + ImplementationRepository::EnvironmentList env (0); + this->repository_.add_server (name, + "", // no activator + "", // no cmdline + ImplementationRepository::EnvironmentList (), + "", // no working dir + ImplementationRepository::NORMAL, + DEFAULT_START_LIMIT, + partial_ior, + ior.in (), + ImplementationRepository::ServerObject::_nil () // Will connect at first access + ); + } + else + { + if (info->activation_mode != ImplementationRepository::PER_CLIENT) { + info->ior = ior.in (); + info->partial_ior = partial_ior; + info->server = ImplementationRepository::ServerObject::_nil (); // Will connect at first access + + int err = this->repository_.update_server (*info); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); + + waiter_svt_.unblock_one (name, partial_ior, ior.in (), false); + } else { + // Note : There's no need to unblock all the waiting request until + // we know the final status of the server. + waiter_svt_.unblock_one (name, partial_ior, ior.in (), true); + } + } +} + +void +ImR_Locator_i::server_is_shutting_down (const char* server ACE_ENV_ARG_DECL_NOT_USED) +ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)) +{ + ACE_ASSERT (server != 0); + Server_Info_Ptr info = this->repository_.get_server (server); + if (info.null ()) + { + if (this->debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR_Locator_i::server_is_shutting_down: Unknown server:%s\n", server)); + } + return; + } + + if (this->debug_ > 0) + ACE_DEBUG ((LM_DEBUG, "ImR: Server <%s> is shutting down.\n", server)); + + info->reset (); + + int err = this->repository_.update_server (*info); + ACE_ASSERT (err == 0); + ACE_UNUSED_ARG (err); +} + +void +ImR_Locator_i::find (const char* server, + ImplementationRepository::ServerInformation_out imr_info + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_ASSERT (server != 0); + ACE_NEW_THROW_EX (imr_info, ImplementationRepository::ServerInformation, CORBA::NO_MEMORY ()); + + Server_Info_Ptr info = this->repository_.get_server (server); + if (! info.null ()) + { + imr_info = info->createImRServerInfo (ACE_ENV_SINGLE_ARG_PARAMETER); + + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Found server %s.\n", server)); + } + else + { + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Cannot find server <%s>\n", server)); + } +} + +void +ImR_Locator_i::list (CORBA::ULong how_many, + ImplementationRepository::ServerInformationList_out server_list, + ImplementationRepository::ServerInformationIterator_out server_iterator + ACE_ENV_ARG_DECL + ) ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: List servers.\n")); + + // Initialize the out variables, so if we return early, they will + // not be dangling. + server_iterator = ImplementationRepository::ServerInformationIterator::_nil (); + ACE_NEW_THROW_EX (server_list, + ImplementationRepository::ServerInformationList (0), CORBA::NO_MEMORY ()); + + Locator_Repository::SIMap::ENTRY* entry = 0; + Locator_Repository::SIMap::ITERATOR it (this->repository_.servers ()); + + // Number of servers that will go into the server_list. + CORBA::ULong n = this->repository_.servers ().current_size (); + if (how_many > 0 && n > how_many) + { + n = how_many; + } + + server_list->length (n); + + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR_Locator_i::list: Filling ServerList with %d servers\n", n)); + + for (CORBA::ULong i = 0; i < n; i++) + { + it.next (entry); + it.advance (); + ACE_ASSERT (entry != 0); + + Server_Info_Ptr info = entry->int_id_; + + ImplementationRepository::ServerInformation_var imr_info = info->createImRServerInfo (ACE_ENV_SINGLE_ARG_PARAMETER); + server_list[i] = *imr_info; + } + + if (this->repository_.servers ().current_size () > n) + { + if (this->debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR_Locator_i::list: Creating ServerInformation Iterator\n")); + + ImR_Iterator* imr_iter; + + ACE_NEW_THROW_EX (imr_iter, + ImR_Iterator (n, this->repository_, this->imr_poa_.in ()), + CORBA::NO_MEMORY ()); + + PortableServer::ServantBase_var tmp (imr_iter); + + ACE_TRY + { + PortableServer::ObjectId_var id = + this->imr_poa_->activate_object (imr_iter ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + CORBA::Object_var obj = this->imr_poa_->id_to_reference (id.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + server_iterator = ImplementationRepository:: + ServerInformationIterator::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_RE_THROW; + } + ACE_ENDTRY; + ACE_CHECK; + } +} + +Activator_Info_Ptr +ImR_Locator_i::get_activator (const ACE_CString& aname) +{ + Activator_Info_Ptr info = this->repository_.get_activator (aname); + if (! info.null ()) + { + this->connect_activator (*info); + } + return info; +} + +void +ImR_Locator_i::connect_activator (Activator_Info& info) +{ + if (! CORBA::is_nil (info.activator.in ()) || info.ior.length () == 0) + return; + + ACE_TRY_NEW_ENV + { + CORBA::Object_var obj = + this->orb_->string_to_object (info.ior.c_str () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (obj.in ())) + { + info.reset (); + return; + } + + if (startup_timeout_ > ACE_Time_Value::zero) + { + obj = set_timeout_policy (obj.in (), startup_timeout_); + } + + info.activator = + ImplementationRepository::Activator::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (info.activator.in ())) + { + info.reset (); + return; + } + + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Connected to activator <%s>\n", info.name.c_str ())); + } + ACE_CATCHANY + { + info.reset (); + } + ACE_ENDTRY; +} + +void +ImR_Locator_i::auto_start_servers (ACE_ENV_SINGLE_ARG_DECL) +{ + if (this->repository_.servers ().current_size () == 0) + return; + + Locator_Repository::SIMap::ENTRY* server_entry; + Locator_Repository::SIMap::ITERATOR server_iter (this->repository_.servers ()); + + // For each of the entries in the Locator_Repository, get the startup + // information and activate the servers, if they are not already + // running. + for (;server_iter.next (server_entry) != 0; server_iter.advance ()) + { + Server_Info_Ptr info = server_entry->int_id_; + ACE_ASSERT (! info.null ()); + + ACE_TRY + { + if (info->activation_mode == ImplementationRepository::AUTO_START + && info->cmdline.length () > 0) + { + this->activate_server_i (*info, true ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + if (this->debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: AUTO_START Could not activate <%s>\n", + server_entry->ext_id_.c_str ())); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "AUTO_START"); + } + // Ignore exceptions + } + ACE_ENDTRY; + ACE_CHECK; + } +} + +void +ImR_Locator_i::connect_server (Server_Info& info) +{ + if (! CORBA::is_nil (info.server.in ())) + { + return; // already connected + } + + if (info.ior.length () == 0) + { + info.reset (); + return; // can't connect + } + + ACE_TRY_NEW_ENV + { + CORBA::Object_var obj = orb_->string_to_object (info.ior.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (obj.in ())) + { + info.reset (); + return; + } + + obj = set_timeout_policy (obj.in (), DEFAULT_SERVER_TIMEOUT); + + info.server = + ImplementationRepository::ServerObject::_unchecked_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (info.server.in ())) + { + info.reset (); + return; + } + + if (debug_ > 1) + ACE_DEBUG ((LM_DEBUG, "ImR: Connected to server <%s>\n", info.name.c_str ())); + } + ACE_CATCHANY + { + info.reset (); + } + ACE_ENDTRY; +} + +bool +ImR_Locator_i::is_alive (Server_Info& info) +{ + const size_t table_size = sizeof (PING_RETRY_SCHEDULE) / + sizeof (*PING_RETRY_SCHEDULE); + + for (size_t i = 0; i < table_size; ++i) + { + int status = this->is_alive_i (info); + if (status == 0) + return false; + if (status == 1) + return true; + + // This is evil, but there's not much else we can do for now. We + // should never reach this code once the ImR Servers are fixed + // so that they don't lie about server_is_running. Currently, + // they send this notification during poa creation. We have to + // run the orb, because the very thing that may be slowing the + // aliveness of the servers is the fact that they're trying to + // register more objects with us. In practical testing, we + // never retried the ping more than once, because the second + // ping always timed out, even if the servers poa manager had + // not been activated. The only way we saw multiple retries was + // if we ran the orb on the server before the poa manager was + // activated. For this reason, the first retry is immediate, + // and the orb->run () call is not required. The call will + // likely timeout, and is_alive will return true. + if (PING_RETRY_SCHEDULE[i] > 0) + { + ACE_Time_Value tv (0, PING_RETRY_SCHEDULE[i] * 1000); + this->orb_->run (tv); + } + } + if (debug_ > 0) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> Ping retry count exceeded. alive=maybe.\n", info.name.c_str ())); + } + // We return true here, because the server *might* be alive, it's just not starting in a timely + // manner. We can't return false, because then we'll just try to start another instance, and the + // same thing will likely happen. + info.last_ping = ACE_OS::gettimeofday (); + return true; +} + +int +ImR_Locator_i::is_alive_i (Server_Info& info) +{ + // This is used by the ACE_TRY below when exceptions are turned off. + ACE_DECLARE_NEW_CORBA_ENV; + + if (info.ior.length () == 0 || info.partial_ior.length () == 0) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> not running. alive=false.\n", info.name.c_str ())); + } + info.last_ping = ACE_Time_Value::zero; + return 0; + } + + if (ping_interval_ == ACE_Time_Value::zero) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> Ping verification disabled. alive=true.\n", info.name.c_str ())); + } + return 1; + } + + if ((ACE_OS::gettimeofday () - info.last_ping) < ping_interval_) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> within ping interval. alive=true.\n", info.name.c_str ())); + } + return 1; + } + + // If we don't have enough information to start the server if it isn't already + // then we might as well assume it is running. That way the client can get the + // status directly from the server. + if (info.cmdline.length () == 0 || ! repository_.has_activator (info.activator)) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: Ping verification skipped. <%s> not startable.\n", info.name.c_str ())); + } + return 1; + } + + connect_server (info); + + if (CORBA::is_nil (info.server.in ())) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> Could not connect. alive=false.\n", info.name.c_str ())); + } + return 0; + } + + ACE_TRY + { + // Make a copy, in case the info is updated during the ping. + ImplementationRepository::ServerObject_var server = info.server; + + // This will timeout if it takes too long + server->ping (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> Ping successful. alive=true\n", info.name.c_str ())); + } + info.last_ping = ACE_OS::gettimeofday (); + } + ACE_CATCH (CORBA::TRANSIENT, ex) + { + const CORBA::ULong BITS_5_THRU_12_MASK = 0x00000f80; + switch (ex.minor () & BITS_5_THRU_12_MASK) + { + case TAO_INVOCATION_SEND_REQUEST_MINOR_CODE: + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> Local TRANSIENT. alive=false.\n", info.name.c_str ())); + } + } + info.last_ping = ACE_Time_Value::zero; + return 0; + case TAO_POA_DISCARDING: + case TAO_POA_HOLDING: + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> Remote TRANSIENT. alive=maybe.\n", info.name.c_str ())); + } + } + return -1; // We keep trying to ping, because returning 1 now, would just lead + // to clients getting the same exception. If we can't ping after several + // attempts, then we'll give up and return 1, letting the client worry about it. + default: + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> TRANSIENT exception. alive=false.\n", info.name.c_str ())); + } + info.last_ping = ACE_Time_Value::zero; + } + return 0; + } + } + ACE_CATCH (CORBA::TIMEOUT, ex) + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, + "ImR: <%s> Ping timed out. alive=true.\n", info.name.c_str ())); + } + return 1; // This is "alive" as far as we're concerned. Presumably the client + // will have a less stringent timeout policy, or will want to know + // about the timeout. In any case, we're only guaranteeing that the + // server is alive, not that it's responsive. + } + ACE_CATCHANY + { + if (debug_ > 1) + { + ACE_DEBUG ((LM_DEBUG, "ImR: <%s> Unexpected Ping exception. alive=false\n", info.name.c_str ())); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "\n"); + } + info.last_ping = ACE_Time_Value::zero; + return false; + } + ACE_ENDTRY; + return 1; +} + +int +ImR_Locator_i::debug () const +{ + return debug_; +} diff --git a/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.h b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.h new file mode 100644 index 00000000000..7dd3033bcbc --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImR_Locator_i.h @@ -0,0 +1,187 @@ +// $Id$ + +#ifndef IMR_LOCATOR_I_H +#define IMR_LOCATOR_I_H +#include /**/ "ace/pre.h" + +#include "locator_export.h" + +#include "Adapter_Activator.h" +#include "Forwarder.h" +#include "Locator_Options.h" +#include "Locator_Repository.h" +#include "AsyncStartupWaiter_i.h" +#include "tao/IORTable/IORTable.h" + +#include "orbsvcs/IOR_Multicast.h" + +#include "ImR_LocatorS.h" +#include "AsyncStartupWaiterS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +ACE_BEGIN_VERSIONED_NAMESPACE_DECL +class ACE_Reactor; +ACE_END_VERSIONED_NAMESPACE_DECL + +class INS_Locator; + +// Gets a request from a client and depending on the POA name, +// requests an activator to take care of activating the +// corresponding server and raises a forward exception to the +// client pointing to the correct server. +class Locator_Export ImR_Locator_i + : public virtual POA_ImplementationRepository::Locator +{ +public: + ImR_Locator_i(); + + ~ImR_Locator_i (void); + + /// Initialize the service, creating its own orb, poa, etc. + int init (Options& opts ACE_ENV_ARG_DECL); + + /// Same as above, but use the given orb + int init_with_orb (CORBA::ORB_ptr orb, Options& opts ACE_ENV_ARG_DECL); + + /// Cleans up any state created by init*. + int fini (ACE_ENV_SINGLE_ARG_DECL); + + /// Run using the orb reference created during init() + int run (ACE_ENV_SINGLE_ARG_DECL); + + /// Shutdown the orb. + void shutdown (bool wait_for_completion ACE_ENV_ARG_DECL); + + int debug() const; + // Note : See the IDL for descriptions of the operations. + + // Activator->Locator + + virtual CORBA::Long register_activator (const char* name, + ImplementationRepository::Activator_ptr admin + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + virtual void unregister_activator (const char* name, + CORBA::Long token ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + virtual void notify_child_death (const char* name ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + + // tao_imr->Locator + + virtual void activate_server (const char * name + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)); + virtual void add_or_update_server (const char * name, + const ImplementationRepository::StartupOptions &options ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)); + virtual void remove_server (const char * name ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)); + virtual void shutdown_server (const char * name ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)); + virtual void find (const char * name, + ImplementationRepository::ServerInformation_out info ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + virtual void list ( + CORBA::ULong how_many, + ImplementationRepository::ServerInformationList_out server_list, + ImplementationRepository::ServerInformationIterator_out server_iterator ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + virtual void shutdown(CORBA::Boolean activators, CORBA::Boolean servers ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + + // Server->Locator + + virtual void server_is_running (const char* name, + const char* partial_ior, + ImplementationRepository::ServerObject_ptr server_object + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)); + virtual void server_is_shutting_down (const char * name ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, ImplementationRepository::NotFound)); + + // Used by the INS_Locator to start a sever given an object name + char* activate_server_by_object (const char* object_name ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)); + + char* activate_server_by_name (const char * name, bool manual_start ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)); + +private: + + char* activate_server_i (Server_Info& info, bool manual_start ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)); + + char* activate_perclient_server_i (Server_Info info, bool manual_start ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)); + + ImplementationRepository::StartupInfo* + start_server(Server_Info& info, bool manual_start ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException, + ImplementationRepository::NotFound, + ImplementationRepository::CannotActivate)); + + bool is_alive(Server_Info& info); + int is_alive_i(Server_Info& info); + + // Set up the multicast related if 'm' is passed on the command + // line. + int setup_multicast (ACE_Reactor *reactor, const char *ior); + void teardown_multicast(); + + void unregister_activator_i(const char* activator); + + Activator_Info_Ptr get_activator (const ACE_CString& name); + void connect_activator (Activator_Info& info); + + void auto_start_servers(ACE_ENV_SINGLE_ARG_DECL); + + CORBA::Object_ptr set_timeout_policy(CORBA::Object_ptr obj, const ACE_Time_Value& to); + + void connect_server(Server_Info& info); + + PortableServer::POA_ptr findPOA(const char* name); +private: + + // The class that handles the forwarding. + ImR_Forwarder forwarder_; + + // Used for the forwarding of any type of POA. + ImR_Adapter adapter_; + + /// The locator interface for the IORTable + IORTable::Locator_var ins_locator_; + + CORBA::ORB_var orb_; + PortableServer::POA_var root_poa_; + PortableServer::POA_var imr_poa_; + + int debug_; + + TAO_IOR_Multicast ior_multicast_; + + Locator_Repository repository_; + + AsyncStartupWaiter_i waiter_svt_; + ImplementationRepository::AsyncStartupWaiter_var waiter_; + + bool read_only_; + ACE_Time_Value startup_timeout_; + ACE_Time_Value ping_interval_; +}; + +#include /**/ "ace/post.h" +#endif /* IMR_LOCATOR_I_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/ImplRepo_Service.mpc b/TAO/orbsvcs/ImplRepo_Service/ImplRepo_Service.mpc new file mode 100644 index 00000000000..24d5c6e2a0c --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/ImplRepo_Service.mpc @@ -0,0 +1,142 @@ +// $Id$ + +project(ImR_Activator_IDL) : orbsvcslib, conv_lib, portableserver, imr_client, tao_versioning_idl_defaults { + sharedname = TAO_ImR_Activator_IDL + dynamicflags = ACTIVATOR_IDL_BUILD_DLL + idlflags += -Wb,export_macro=ActivatorIDL_Export -Wb,export_include=activator_idl_export.h + idl_files { + ImR_Activator.idl + } + source_files { + ImR_ActivatorS.cpp + ImR_ActivatorC.cpp + } + header_files { + activator_idl_export.h + } +} + +project(ImR_Locator_IDL) : orbsvcslib, conv_lib, valuetype, portableserver, imr_client, messaging, tao_versioning_idl_defaults { + sharedname = TAO_ImR_Locator_IDL + after += ImR_Activator_IDL + libs += TAO_ImR_Activator_IDL + // Dont try to build this project if ImR_Activator_IDL is not built + requires += corba_messaging + + dynamicflags = LOCATOR_IDL_BUILD_DLL + idlflags += -Wb,export_macro=LocatorIDL_Export -Wb,export_include=locator_idl_export.h + idl_files { + ImR_Locator.idl + } + + idl_files { + idlflags += -GH + AsyncStartupWaiter.idl + } + + source_files { + ImR_LocatorS.cpp + ImR_LocatorC.cpp + AsyncStartupWaiterS.cpp + AsyncStartupWaiterC.cpp + } + header_files { + locator_idl_export.h + } +} + +project(ImR_Activator) : orbsvcslib, conv_lib, acexml, minimum_corba, valuetype, portableserver, imr_client, messaging, pi, codecfactory { + sharedname = TAO_ImR_Activator + dynamicflags = ACTIVATOR_BUILD_DLL + after += ImR_Activator_IDL ImR_Locator_IDL + libs += TAO_ImR_Activator_IDL TAO_ImR_Locator_IDL + // Dont try to build this project if ImR_Activator_IDL is not built + requires += corba_messaging + + Source_Files { + ImR_Activator_i.cpp + Activator_Options.cpp + Activator_Loader.cpp + } + header_files { + activator_export.h + } + idl_files { + } +} + +project(ImR_Locator) : orbsvcslib, conv_lib, minimum_corba, iortable, portableserver, messaging, svc_utils, acexml, imr_client { + sharedname = TAO_ImR_Locator + dynamicflags = LOCATOR_BUILD_DLL + after += ImR_Locator_IDL ImR_Activator_IDL + libs += TAO_ImR_Locator_IDL TAO_ImR_Activator_IDL + Source_Files { + Activator_Info.cpp + Adapter_Activator.cpp + Forwarder.cpp + ImR_Locator_i.cpp + AsyncStartupWaiter_i.cpp + INS_Locator.cpp + Locator_XMLHandler.cpp + Locator_Loader.cpp + Locator_Options.cpp + Iterator.cpp + Server_Info.cpp + Locator_Repository.cpp + } + header_files { + utils.h + locator_export.h + } + idl_files { + } +} + +project(ImR_Locator_Service) : orbsvcsexe, install_bin, minimum_corba, iortable, messaging, acexml ,svc_utils, pi_server, imr_client { + exename = ImplRepo_Service + after += ImR_Locator ImR_Activator_IDL ImR_Locator_IDL + libs += TAO_ImR_Locator TAO_ImR_Activator_IDL TAO_ImR_Locator_IDL + + // Static Debug builds on Windows will not link properly due + // to a linker bug. It complains that the ACEXML library duplicates + // a couple of template instantiations from the TAO_ImR_Locator library. + // The FORCE:MULTIPLE option works around that bug. Unfortunately, + // there is no way to narrow the options down to only static debug builds. + // Incremental linking has also been turned off since it is + // incompatible with this option, producing warnings at link time. + specific(em3, nmake, vc6, vc71) { + link_options += /FORCE:MULTIPLE /INCREMENTAL:NO + } + + Source_Files { + ImR_Locator.cpp + Locator_NT_Service.cpp + } + idl_files { + } +} + + +project(ImR_Activator_Service) : orbsvcsexe, install_bin, acexml, minimum_corba, messaging, svc_utils, imr_client { + exename = ImR_Activator + after += ImR_Activator ImR_Activator_IDL ImR_Locator_IDL + libs += TAO_ImR_Activator TAO_ImR_Activator_IDL TAO_ImR_Locator_IDL + Source_Files { + ImR_Activator.cpp + Activator_NT_Service.cpp + } + idl_files { + } +} + + +project(tao_imr) : orbsvcsexe, install_bin, minimum_corba, portableserver, imr_client { + exename = tao_imr + install = $(ACE_ROOT)/bin + Source_Files { + tao_imr.cpp + tao_imr_i.cpp + } + idl_files { + } +} diff --git a/TAO/orbsvcs/ImplRepo_Service/Iterator.cpp b/TAO/orbsvcs/ImplRepo_Service/Iterator.cpp new file mode 100644 index 00000000000..1ed369991c2 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Iterator.cpp @@ -0,0 +1,91 @@ +//============================================================================= +/** + * @file Iterator.cpp + * + * $Id$ + * + * @brief This file declares ImR's iterator. + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#include "Iterator.h" + +ImR_Iterator::ImR_Iterator (CORBA::ULong n, Locator_Repository& repo, PortableServer::POA_ptr poa) + : repo_(repo) + , count_(n) + , poa_(poa) +{ +} + + +CORBA::Boolean +ImR_Iterator::next_n (CORBA::ULong how_many, + ImplementationRepository::ServerInformationList_out server_list + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_NEW_THROW_EX (server_list, + ImplementationRepository::ServerInformationList(0), CORBA::NO_MEMORY()); + + Locator_Repository::SIMap::ENTRY* entry = 0; + Locator_Repository::SIMap::ITERATOR it (this->repo_.servers ()); + + // Number of servers that will go into the server_list. + CORBA::ULong n = this->repo_.servers().current_size(); + if (n <= this->count_) + { + return 0; // We already finished. + } + else + { + n -= this->count_; + } + + if (how_many > 0 && n > how_many) + { + n = how_many; + } + + server_list->length (n); + + CORBA::ULong i = 0; + for (; i < this->count_; ++i) + { + it.advance (); + } + + for (i = 0; i < n; ++i) + { + it.next (entry); + it.advance (); + ACE_ASSERT(entry != 0); + + Server_Info_Ptr info = entry->int_id_; + + server_list[i].server = info->name.c_str (); + server_list[i].startup.command_line = info->cmdline.c_str (); + server_list[i].startup.environment = info->env_vars; + server_list[i].startup.working_directory = info->dir.c_str (); + server_list[i].startup.activation = info->activation_mode; + server_list[i].startup.activator = info->activator.c_str (); + server_list[i].startup.start_limit = info->start_limit; + server_list[i].partial_ior = info->partial_ior.c_str (); + } + + this->count_ += n; + + return 1; +} + + +void +ImR_Iterator::destroy (ACE_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + PortableServer::ObjectId_var oid = poa_->servant_to_id (this ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + poa_->deactivate_object (oid.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; +} diff --git a/TAO/orbsvcs/ImplRepo_Service/Iterator.h b/TAO/orbsvcs/ImplRepo_Service/Iterator.h new file mode 100644 index 00000000000..d592146fbb7 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Iterator.h @@ -0,0 +1,55 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file Iterator.h + * + * $Id$ + * + * @brief This file declares ImR's iterator. + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#ifndef IMR_ITERATOR_H +#define IMR_ITERATOR_H + +#include "Locator_Repository.h" +#include "tao/PortableServer/PortableServer.h" +#include "tao/ImR_Client/ImplRepoS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class ImR_Iterator + * + * @brief The Iterator for servers in the ImR. + * + */ +class ImR_Iterator + : public POA_ImplementationRepository::ServerInformationIterator +{ +public: + ImR_Iterator (CORBA::ULong n, Locator_Repository& repo, PortableServer::POA_ptr poa); + + /// Returns the next list of up to <how_many> servers. If empty, will return + /// false. + virtual CORBA::Boolean next_n ( + CORBA::ULong how_many, + ImplementationRepository::ServerInformationList_out server_list + ACE_ENV_ARG_DECL_WITH_DEFAULTS + ) + ACE_THROW_SPEC ((CORBA::SystemException)); + + virtual void destroy (ACE_ENV_SINGLE_ARG_DECL_WITH_DEFAULTS) + ACE_THROW_SPEC ((CORBA::SystemException)); + +private: + Locator_Repository& repo_; + CORBA::ULong count_; + PortableServer::POA_ptr poa_; +}; + +#endif /* IMR_ITERATOR_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_Loader.cpp b/TAO/orbsvcs/ImplRepo_Service/Locator_Loader.cpp new file mode 100644 index 00000000000..be8dd5e0e1f --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_Loader.cpp @@ -0,0 +1,105 @@ +// $Id$ + +#include "Locator_Loader.h" +#include "ace/Dynamic_Service.h" +#include "ace/Task.h" + +class ImR_Locator_ORB_Runner : public ACE_Task_Base +{ +public: + ImR_Locator_ORB_Runner (ImR_Locator_Loader& service) + : service_ (service) + { + } + virtual int svc () + { + // Block until service_.fini () calls orb->destroy () + this->service_.run (); + return 0; + } +private: + ImR_Locator_Loader& service_; +}; + +ImR_Locator_Loader::ImR_Locator_Loader() +{ +} + +int +ImR_Locator_Loader::init (int argc, ACE_TCHAR *argv[]) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int err = this->opts_.init (argc, argv); + if (err != 0) + return -1; + + err = this->service_.init (this->opts_ ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + if (err != 0) + return -1; + + // Create a thread in which to run the service + ACE_ASSERT(this->runner_.get () == 0); + this->runner_.reset(new ImR_Locator_ORB_Runner (*this)); + this->runner_->activate (); + } + ACE_CATCHANY + { + return -1; + } + ACE_ENDTRY; + return 0; +} + +int +ImR_Locator_Loader::fini (void) +{ + ACE_ASSERT(this->runner_.get () != 0); + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int ret = this->service_.fini (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->runner_->wait (); + this->runner_.reset (0); + return ret; + } + ACE_CATCHANY + { + } + ACE_ENDTRY; + return -1; +} + +CORBA::Object_ptr +ImR_Locator_Loader::create_object (CORBA::ORB_ptr, + int, + ACE_TCHAR** + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + ACE_THROW_RETURN (CORBA::NO_IMPLEMENT(), CORBA::Object::_nil ()); +} + +int +ImR_Locator_Loader::run(void) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + return this->service_.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHALL + { + ACE_ERROR((LM_ERROR, "Exception in ImR_Locator_ORB_Runner ()\n")); + return -1; + } + ACE_ENDTRY; +} + + +ACE_FACTORY_DEFINE (Locator, ImR_Locator_Loader) diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_Loader.h b/TAO/orbsvcs/ImplRepo_Service/Locator_Loader.h new file mode 100644 index 00000000000..ca90c61c6fb --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_Loader.h @@ -0,0 +1,50 @@ +// -*- C++ -*- +// +// $Id$ + +#ifndef TAO_IMR_LOCATOR_LOADER_H +#define TAO_IMR_LOCATOR_LOADER_H + +#include "ImR_Locator_i.h" + +#include "tao/Object_Loader.h" + +#include "ace/Auto_Ptr.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ImR_Locator_ORB_Runner; + +class Locator_Export ImR_Locator_Loader : public TAO_Object_Loader +{ +public: + ImR_Locator_Loader(); + + virtual int init (int argc, ACE_TCHAR *argv[]); + + virtual int fini (void); + + virtual CORBA::Object_ptr create_object (CORBA::ORB_ptr orb, + int argc, + ACE_TCHAR *argv[] + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + + // Unlike other service objects, we have our own orb. + int run(void); + +private: + ImR_Locator_i service_; + Options opts_; + ACE_Auto_Ptr<ImR_Locator_ORB_Runner> runner_; +private: + // Disallow copying and assignment. + ImR_Locator_Loader (const ImR_Locator_Loader &); + ImR_Locator_Loader &operator = (const ImR_Locator_Loader &); +}; + +ACE_FACTORY_DECLARE (Locator, ImR_Locator_Loader) + +#endif diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_NT_Service.cpp b/TAO/orbsvcs/ImplRepo_Service/Locator_NT_Service.cpp new file mode 100644 index 00000000000..e13a4f8080f --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_NT_Service.cpp @@ -0,0 +1,116 @@ +//============================================================================= +/** + * @file Locator_NT_Service.cpp + * + * $Id$ + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + * @author Jeff Parsons <parsons@cs.wustl.edu> + * @author John Tucker <jtucker@infoglide.com> + * @author Mike Vitalo <mvitalo@infoglide.com> + */ +//============================================================================= + +#include "Locator_NT_Service.h" + +#if defined (ACE_WIN32) + +#include "ImR_Locator_i.h" +#include "Locator_Options.h" + +#include "tao/ORB_Core.h" +#include "tao/corba.h" +#include "ace/Reactor.h" + +/** + * Handles the SERVICE_CONTROL_SHUTDOWN and SERVICE_CONTROL_STOP commands + * by shutting down the ORB. Otherwise ACE_NT_Service::handle_control + * handles the command. + */ +void +Locator_NT_Service::handle_control (DWORD control_code) +{ + if (control_code == SERVICE_CONTROL_SHUTDOWN + || control_code == SERVICE_CONTROL_STOP) + { + report_status (SERVICE_STOP_PENDING); + TAO_ORB_Core_instance ()->reactor ()->end_reactor_event_loop (); + TAO_ORB_Core_instance ()->orb ()->shutdown (1); + } + else + { + ACE_NT_Service::handle_control (control_code); + } +} + + +/** + */ +int +Locator_NT_Service::handle_exception (ACE_HANDLE) +{ + return 0; +} + + +/** + * We do almost the same thing as we do in run_standalone () + */ +int +Locator_NT_Service::svc (void) +{ + ImR_Locator_i server; + Options opts; + + if (opts.init_from_registry () != 0) + { + report_status (SERVICE_STOPPED); + return -1; + } + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + int status = server.init (opts ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (status == -1) + { + report_status (SERVICE_STOPPED); + return -1; + } + else + { + report_status (SERVICE_RUNNING); + server.run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + status = server.fini (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + report_status (SERVICE_STOPPED); + + } + if (status != -1) + return 0; + } + ACE_CATCH (CORBA::SystemException, sysex) + { + ACE_PRINT_EXCEPTION (sysex, IMR_LOCATOR_DISPLAY_NAME); + } + ACE_CATCH (CORBA::UserException, userex) + { + ACE_PRINT_EXCEPTION (userex, IMR_LOCATOR_DISPLAY_NAME); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, IMR_LOCATOR_DISPLAY_NAME); + } + ACE_ENDTRY; + + report_status (SERVICE_STOPPED); + + return -1; +} + +#endif /* ACE_WIN32 */ diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_NT_Service.h b/TAO/orbsvcs/ImplRepo_Service/Locator_NT_Service.h new file mode 100644 index 00000000000..c2199926f63 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_NT_Service.h @@ -0,0 +1,62 @@ +/* -*- C++ -*- */ +//============================================================================= +/** + * @file Locator_NT_Service.h + * + * $Id$ + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + * @author Jeff Parsons <parsons@cs.wustl.edu> + * @author John Tucker <jtucker@infoglide.com> + * @author Mike Vitalo <mvitalo@infoglide.com> + */ +//============================================================================= + +#ifndef Locator_NT_Service_H +#define Locator_NT_Service_H + +#include "ace/config-all.h" + +#if defined (ACE_WIN32) + +#include "ace/NT_Service.h" +#include "ace/Singleton.h" +#include "ace/Synch.h" +#include "tao/orbconf.h" + +static const char * IMR_LOCATOR_SERVICE_NAME = "TAOImR"; +static const char * IMR_LOCATOR_DISPLAY_NAME = "TAO Implementation Repository"; +static const char * IMR_LOCATOR_DESCRIPTION = "Implementation Repository Locator service for TAO"; + +/** + * @class Locator_NT_Service + * + * @brief Allows the Implementation Repository to act as a Windows NT Service. + */ +class Locator_NT_Service : public ACE_NT_Service +{ +public: + typedef TAO_SYNCH_RECURSIVE_MUTEX MUTEX; + + /// We override <handle_control> because it handles stop requests + /// privately. + virtual void handle_control (DWORD control_code); + + /// We override <handle_exception> so a 'stop' control code can wake + /// the reactor off of its wait. + virtual int handle_exception (ACE_HANDLE h); + + /// This is a virtual method inherited from ACE_NT_Service. + virtual int svc (void); + +private: + friend class ACE_Singleton<Locator_NT_Service, MUTEX>; +}; + +typedef ACE_Singleton<Locator_NT_Service, ACE_Mutex> SERVICE; + +#endif /* ACE_WIN32 */ + +#endif /* Locator_NT_Service_H */ + + diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_Options.cpp b/TAO/orbsvcs/ImplRepo_Service/Locator_Options.cpp new file mode 100644 index 00000000000..810649d2bb5 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_Options.cpp @@ -0,0 +1,505 @@ +//============================================================================= +/** + * @file Locator_Options.cpp + * + * $Id$ + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#include "Locator_Options.h" +#include "ace/Arg_Shifter.h" +#include "ace/Log_Msg.h" +#include "ace/OS_NS_strings.h" + +ACE_RCSID (ImplRepo_Service, + Options, + "$Id$") + + +#if defined (ACE_WIN32) +static const HKEY SERVICE_REG_ROOT = HKEY_LOCAL_MACHINE; +// This string must agree with the one used in Locator_NT_Service.h +static const ACE_TCHAR *SERVICE_REG_PATH = + ACE_TEXT ("SYSTEM\\CurrentControlSet\\Services\\TAOImR\\Parameters"); +#endif /* ACE_WIN32 */ + +static const int DEFAULT_PING_INTERVAL = 10; // seconds +static const int DEFAULT_START_TIMEOUT = 60; // seconds + +Options::Options () +: repo_mode_ (REPO_NONE) +, erase_repo_ (false) +, debug_ (1) +, multicast_ (false) +, service_ (false) +, ping_interval_(DEFAULT_PING_INTERVAL) +, startup_timeout_(DEFAULT_START_TIMEOUT) +, readonly_ (false) +, service_command_(SC_NONE) +{ +} + +int +Options::parse_args (int &argc, char *argv[]) +{ + ACE_Arg_Shifter shifter (argc, argv); + + while (shifter.is_anything_left ()) + { + if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-c")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -c option needs a command\n")); + this->print_usage (); + return -1; + } + + if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("install")) == 0) + { + this->service_command_ = SC_INSTALL; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("remove")) == 0) + { + this->service_command_ = SC_REMOVE; + } + else + { + ACE_ERROR((LM_ERROR, "Error: Unknown service command : %s\n", shifter.get_current())); + this->print_usage (); + return -1; + } + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-d")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -d option needs a debuglevel\n")); + this->print_usage (); + return -1; + } + + this->debug_ = ACE_OS::atoi (shifter.get_current ()); + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-m")) == 0) + { + this->multicast_ = true; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-o")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -o option needs a filename\n")); + this->print_usage (); + return -1; + } + this->ior_output_file_ = shifter.get_current(); + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-s")) == 0) + { + // Run as a service + this->service_ = true; + } + else if ((ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-?")) == 0) + || (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-h")) == 0)) + { + this->print_usage (); + return 1; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-l")) == 0) + { + this->readonly_ = true; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-p")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -p option needs a filename\n")); + this->print_usage (); + return -1; + } + + this->persist_file_name_ = shifter.get_current (); + this->repo_mode_ = REPO_HEAP_FILE; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-r")) == 0) + { + this->repo_mode_ = REPO_REGISTRY; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-x")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -x option needs a filename\n")); + this->print_usage (); + return -1; + } + + this->persist_file_name_ = shifter.get_current (); + this->repo_mode_ = REPO_XML_FILE; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-e")) == 0) + { + this->erase_repo_ = true; + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-t")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -t option needs a value\n")); + this->print_usage (); + return -1; + } + this->startup_timeout_ = + ACE_Time_Value (ACE_OS::atoi (shifter.get_current ())); + } + else if (ACE_OS::strcasecmp (shifter.get_current (), + ACE_TEXT ("-v")) == 0) + { + shifter.consume_arg (); + + if (!shifter.is_anything_left () || shifter.get_current ()[0] == '-') + { + ACE_ERROR ((LM_ERROR, "Error: -v option needs a value\n")); + this->print_usage (); + return -1; + } + this->ping_interval_ = + ACE_Time_Value (0, 1000 * ACE_OS::atoi (shifter.get_current ())); + } + else + { + shifter.ignore_arg (); + continue; + } + + shifter.consume_arg (); + } + + return 0; +} + +int +Options::init (int argc, char *argv[]) +{ + // Make an initial pass through and grab the arguments that we recognize. + // This may also run the commands to install or remove the nt service. + int result = this->parse_args (argc, argv); + if (result != 0) + { + return result; + } + + for (int i = 0; i < argc; ++i) + { + this->cmdline_ += ACE_CString (argv[i]) + ACE_CString (" "); + } + return 0; +} + +int +Options::init_from_registry (void) +{ + this->load_registry_options (); + return 0; +} + + +void +Options::print_usage (void) const +{ + ACE_ERROR ((LM_ERROR, + "Usage:\n" + "\n" + "ImR_Locator [-c cmd] [-d 0|1|2] [-m] [-o file]\n" + " [-r|-p file|-x file] [-s] [-t secs] [-v secs]\n" + " -c command Runs nt service commands ('install' or 'remove')\n" + " -d level Sets the debug level (default 1)\n" + " -l Lock the database\n" + " -m Turn on multicast\n" + " -o file Outputs the ImR's IOR to a file\n" + " -p file Use file for storing/loading settings\n" + " -x file Use XML file for storing/loading setting\n" + " -r Use the registry for storing/loading settings\n" + " -t secs Server startup timeout.(Default=60s)\n" + " -v msecs Server verification interval.(Default=10s)\n" + )); +} + +int +Options::save_registry_options () +{ +#if defined (ACE_WIN32) + HKEY key = 0; + // Create or open the parameters key + LONG err = ACE_TEXT_RegCreateKeyEx (SERVICE_REG_ROOT, + SERVICE_REG_PATH, + 0, + "", // class + REG_OPTION_NON_VOLATILE, + KEY_ALL_ACCESS, + NULL, + &key, + NULL + ); + if (err != ERROR_SUCCESS) + { + return -1; + } + err = ACE_TEXT_RegSetValueEx (key, "ORBInitOptions", 0, REG_SZ, + (LPBYTE) this->cmdline_.c_str (), this->cmdline_.length () + 1); + ACE_ASSERT (err == ERROR_SUCCESS); + + err = ACE_TEXT_RegSetValueEx (key, "IORFile", 0, REG_SZ, + (LPBYTE) ior_output_file_.c_str (), ior_output_file_.length () + 1); + ACE_ASSERT (err == ERROR_SUCCESS); + + err = ACE_TEXT_RegSetValueEx (key, "DebugLevel", 0, REG_DWORD, + (LPBYTE) &debug_ , sizeof (debug_)); + ACE_ASSERT(err == ERROR_SUCCESS); + + err = ACE_TEXT_RegSetValueEx (key, "PersistFile", 0, REG_SZ, + (LPBYTE) this->persist_file_name_.c_str (), this->persist_file_name_.length () + 1); + ACE_ASSERT (err == ERROR_SUCCESS); + + DWORD tmp = this->ping_interval_.msec (); + err = ACE_TEXT_RegSetValueEx (key, "PingInterval", 0, REG_DWORD, + (LPBYTE) &tmp, sizeof (DWORD)); + ACE_ASSERT (err == ERROR_SUCCESS); + + tmp = this->readonly_ ? 1 : 0; + err = ACE_TEXT_RegSetValueEx (key, "Lock", 0, REG_DWORD, + (LPBYTE) &tmp, sizeof (DWORD)); + ACE_ASSERT (err == ERROR_SUCCESS); + + tmp = this->repo_mode_; + err = ACE_TEXT_RegSetValueEx (key, "PersistType", 0, REG_DWORD, + (LPBYTE) &tmp, sizeof (DWORD)); + ACE_ASSERT (err == ERROR_SUCCESS); + + tmp = this->startup_timeout_.sec(); + err = ACE_TEXT_RegSetValueEx (key, "Timeout", 0, REG_DWORD, + (LPBYTE) &tmp, sizeof (DWORD)); + ACE_ASSERT (err == ERROR_SUCCESS); + + tmp = multicast_ ? 1 : 0; + err = ACE_TEXT_RegSetValueEx (key, "Multicast", 0, REG_DWORD, + (LPBYTE) &tmp, sizeof (DWORD)); + ACE_ASSERT (err == ERROR_SUCCESS); + + err = ::RegCloseKey (key); + ACE_ASSERT (err == ERROR_SUCCESS); +#endif + return 0; +} + +int +Options::load_registry_options () +{ +#if defined (ACE_WIN32) + HKEY key = 0; + // Create or open the parameters key + LONG err = ACE_TEXT_RegOpenKeyEx (SERVICE_REG_ROOT, + SERVICE_REG_PATH, + 0, + KEY_READ, + &key + ); + if (err != ERROR_SUCCESS) + { + // If there aren't any saved parameters, then that's ok. + return 0; + } + ACE_TCHAR tmpstr[4096]; + DWORD sz = sizeof (tmpstr); + DWORD type = 0; + err = ACE_TEXT_RegQueryValueEx (key, "ORBInitOptions", 0, &type, + (LPBYTE) tmpstr, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_SZ); + tmpstr[sz - 1] = '\0'; + this->cmdline_ = tmpstr; + } + + sz = sizeof(tmpstr); + err = ACE_TEXT_RegQueryValueEx (key, "IORFile", 0, &type, + (LPBYTE) tmpstr, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_SZ); + tmpstr[sz - 1] = '\0'; + this->ior_output_file_ = tmpstr; + } + + sz = sizeof(debug_); + err = ACE_TEXT_RegQueryValueEx (key, "DebugLevel", 0, &type, + (LPBYTE) &this->debug_ , &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + } + + DWORD tmp = 0; + sz = sizeof(tmp); + err = ACE_TEXT_RegQueryValueEx (key, "PingInterval", 0, &type, + (LPBYTE) &tmp, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + ping_interval_.msec (tmp); + } + + tmp = 0; + sz = sizeof(tmp); + err = ACE_TEXT_RegQueryValueEx (key, "Lock", 0, &type, + (LPBYTE) &tmp, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + readonly_ = tmp != 0; + } + + sz = sizeof(this->repo_mode_); + err = ACE_TEXT_RegQueryValueEx (key, "PersistType", 0, &type, + (LPBYTE) &this->repo_mode_, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + } + + tmp = 0; + sz = sizeof(tmp); + err = ACE_TEXT_RegQueryValueEx (key, "Timeout", 0, &type, + (LPBYTE) &tmp, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + this->startup_timeout_.sec (tmp); + } + + tmp = 0; + sz = sizeof(tmp); + err = ACE_TEXT_RegQueryValueEx (key, "Multicast", 0, &type, + (LPBYTE) &tmp, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_DWORD); + this->multicast_ = tmp != 0; + } + + sz = sizeof(tmpstr); + err = ACE_TEXT_RegQueryValueEx (key, "PersistFile", 0, &type, + (LPBYTE) tmpstr, &sz); + if (err == ERROR_SUCCESS) + { + ACE_ASSERT (type == REG_SZ); + tmpstr[sz - 1] = '\0'; + this->persist_file_name_ = tmpstr; + } + + err = ::RegCloseKey (key); + ACE_ASSERT (err == ERROR_SUCCESS); +#endif + return 0; +} + +bool +Options::service (void) const +{ + return this->service_; +} + +unsigned int +Options::debug (void) const +{ + return this->debug_; +} + +const ACE_CString& +Options::ior_filename (void) const +{ + return this->ior_output_file_; +} + +bool +Options::multicast (void) const +{ + return this->multicast_; +} + +Options::SERVICE_COMMAND +Options::service_command(void) const +{ + return this->service_command_; +} + +const char* +Options::cmdline(void) const { + return this->cmdline_.c_str (); +} + +const ACE_CString& +Options::persist_file_name(void) const { + return this->persist_file_name_; +} + +ACE_Time_Value +Options::startup_timeout (void) const +{ + return this->startup_timeout_; +} + +ACE_Time_Value +Options::ping_interval (void) const +{ + return this->ping_interval_; +} + +Options::RepoMode +Options::repository_mode (void) const +{ + return this->repo_mode_; +} + +bool +Options::repository_erase (void) const +{ + return this->erase_repo_; +} + +bool +Options::readonly (void) const +{ + return this->readonly_; +} + diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_Options.h b/TAO/orbsvcs/ImplRepo_Service/Locator_Options.h new file mode 100644 index 00000000000..4d7019bccf3 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_Options.h @@ -0,0 +1,147 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Locator_Options.h + * + * $Id$ + * + * @brief Definition of the Options class for the Implementation Repository. + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= + +#ifndef LOCATOR_OPTIONS_H +#define LOCATOR_OPTIONS_H + +#include "locator_export.h" + +#include "ace/SString.h" +#include "ace/Time_Value.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * @class Options + * + * @brief Maintains the global options. + * + * This is where the settings for TAO's Implementation Repository are stored. + */ +class Locator_Export Options +{ +public: + + enum SERVICE_COMMAND { + SC_NONE, + SC_INSTALL, + SC_REMOVE + }; + + enum RepoMode { + REPO_NONE, + REPO_XML_FILE, + REPO_HEAP_FILE, + REPO_REGISTRY + }; + + Options (); + + /// Parse the command-line arguments and initialize the options. + int init (int argc, char *argv[]); + /// This version should only be used when run as an nt service. + int init_from_registry(); + + /// Service Mode + bool service (void) const; + + /// Debug level for the Implementation Repository. + unsigned int debug (void) const; + + /// Returns the file where the IOR should be stored. + const ACE_TString& ior_filename (void) const; + + /// Will we listen for multicast location requests? + bool multicast (void) const; + + /// The nt service command to run (install/remove) + SERVICE_COMMAND service_command(void) const; + + int save_registry_options(); + + const char* cmdline(void) const; + + /// File that contains the activator related information + /// that the persistent locator has to save. + const ACE_TString& persist_file_name(void) const; + + /// Do we allow modifications to the servers? + bool readonly (void) const; + + RepoMode repository_mode (void) const; + + /// Do we wish to clear out the repository + bool repository_erase (void) const; + + /// Returns the timeout value for program starting. + ACE_Time_Value startup_timeout (void) const; + + /// If the server hasn't been verified for a while, then we'll + /// ping it. Note : No timers are currently used. We simply ping() + /// during indirect invocations, if this interval has elapsed. + ACE_Time_Value ping_interval (void) const; + +private: + /// Parses and pulls out arguments for the ImR + int parse_args (int &argc, char *argv[]); + + /// Print the usage information. + void print_usage (void) const; + + /// Run a service command. + int run_service_command (const ACE_TString& cmdline); + + int load_registry_options(); +private: + + // xml, heap, or registry + RepoMode repo_mode_; + + // do we clear out the repository on load + bool erase_repo_; + + /// Debug level. + unsigned int debug_; + + /// File where the IOR of the server object is stored. + ACE_TString ior_output_file_; + + /// Will we listen for multicast location requests? + bool multicast_; + + /// Are we running as a service? + bool service_; + + /// The amount of time between successive "are you started yet?" pings. + ACE_Time_Value ping_interval_; + + /// The amount of time to wait for a server to response after starting it. + ACE_Time_Value startup_timeout_; + + /// Can the server_repository be modified? + bool readonly_; + + /// SC_NONE, SC_INSTALL, SC_REMOVE, ... + SERVICE_COMMAND service_command_; + + /// Our extra command line arguments + ACE_CString cmdline_; + + /// The persistent XML file name. + ACE_TString persist_file_name_; +}; + +#endif diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp b/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp new file mode 100644 index 00000000000..ed44f22f9ad --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.cpp @@ -0,0 +1,574 @@ +#include "Locator_Repository.h" +#include "Locator_XMLHandler.h" +#include "utils.h" +#include "ace/OS_NS_stdio.h" +#include "ace/OS_NS_ctype.h" +#include "ace/OS_NS_unistd.h" + +#include "ACEXML/parser/parser/Parser.h" +#include "ACEXML/common/FileCharStream.h" +#include "ACEXML/common/XML_Util.h" + +ACE_RCSID (ImplRepo_Service, Locator_Repository, "$Id$") + +static const char* STARTUP_COMMAND = "StartupCommand"; +static const char* WORKING_DIR = "WorkingDir"; +static const char* ENVIRONMENT = "Environment"; +static const char* ACTIVATION = "Activation"; +static const char* PARTIAL_IOR = "Location"; +static const char* IOR = "IOR"; +static const char* START_LIMIT = "StartLimit"; +static const char* ACTIVATOR = "Activator"; +static const char* SERVERS_ROOT_KEY = "Servers"; +static const char* ACTIVATORS_ROOT_KEY = "Activators"; +static const char* TOKEN = "Token"; + +#if defined (ACE_WIN32) +static const char* WIN32_REG_KEY = "Software\\TAO\\ImplementationRepository"; +#endif + +static ACE_CString lcase (const ACE_CString& s) +{ + ACE_CString ret(s); + for (size_t i = 0; i < ret.length (); ++i) + { + ret[i] = static_cast<char>(ACE_OS::ace_tolower (s[i])); + } + return ret; +} + +static void loadActivatorsAsBinary (ACE_Configuration& config, Locator_Repository::AIMap& map) +{ + ACE_Configuration_Section_Key root; + int err = config.open_section (config.root_section (), ACTIVATORS_ROOT_KEY, 0, root); + if (err == 0) + { + int index = 0; + ACE_CString name; + while (config.enumerate_sections (root, index, name) == 0) + { + ACE_CString ior; + u_int token; + + ACE_Configuration_Section_Key key; + + // Can't fail, because we're enumerating + config.open_section (root, name.c_str(), 0, key); + + config.get_string_value (key, IOR, ior); + config.get_integer_value (key, TOKEN, token); + + Activator_Info_Ptr info (new Activator_Info (name, token, ior)); + map.bind (lcase (name), info); + index++; + } + } +} + +static void loadServersAsBinary(ACE_Configuration& config, Locator_Repository::SIMap& map) +{ + ACE_Configuration_Section_Key root; + int err = config.open_section (config.root_section (), SERVERS_ROOT_KEY, 0, root); + if (err == 0) + { + int index = 0; + ACE_CString name; + while (config.enumerate_sections (root, index, name) == 0) + { + ACE_CString cmdline, dir, envstr, partial_ior, ior, aname; + u_int amodeint = ImplementationRepository::MANUAL; + u_int start_limit; + + ACE_Configuration_Section_Key key; + + // Can't fail, because we're enumerating + config.open_section (root, name.c_str (), 0, key); + + // Ignore any missing values. Server name is enough on its own. + config.get_string_value (key, ACTIVATOR, aname); + config.get_string_value (key, STARTUP_COMMAND, cmdline); + config.get_string_value (key, WORKING_DIR, dir); + config.get_string_value (key, ENVIRONMENT, envstr); + config.get_integer_value(key, ACTIVATION, amodeint); + config.get_string_value (key, PARTIAL_IOR, partial_ior); + config.get_string_value (key, IOR, ior); + config.get_integer_value(key, START_LIMIT, start_limit); + + ImplementationRepository::ActivationMode amode = + static_cast <ImplementationRepository::ActivationMode> (amodeint); + + ImplementationRepository::EnvironmentList env_vars = + ImR_Utils::parseEnvList (envstr); + + Server_Info_Ptr info (new Server_Info(name, aname, cmdline, + env_vars, dir, amode, start_limit, partial_ior, ior)); + map.bind (name, info); + index++; + } + } +} + +static void loadAsBinary (ACE_Configuration& config, Locator_Repository& repo) +{ + loadServersAsBinary (config, repo.servers ()); + loadActivatorsAsBinary (config, repo.activators ()); +} + +// Note : There is no saveAsBinary(), because the ACE_Configuration class +// supports saving of individual entries. + +static void convertEnvList (const Locator_XMLHandler::EnvList& in, ImplementationRepository::EnvironmentList& out) +{ + CORBA::ULong sz = in.size (); + out.length (sz); + for (CORBA::ULong i = 0; i < sz; ++i) + { + out[i].name = in[i].name.c_str (); + out[i].value = in[i].value.c_str (); + } +} + +class Server_Repo_XML_Callback : public Locator_XMLHandler::Callback +{ +public: + Server_Repo_XML_Callback(Locator_Repository& repo) + : repo_ (repo) + { + } + virtual void next_server (const ACE_CString& name, + const ACE_CString& aname, const ACE_CString& cmdline, + const Locator_XMLHandler::EnvList& envlst, const ACE_CString& dir, + const ACE_CString& amodestr, int start_limit, + const ACE_CString& partial_ior, const ACE_CString& ior) + { + ImplementationRepository::ActivationMode amode = + ImR_Utils::parseActivationMode (amodestr); + + ImplementationRepository::EnvironmentList env_vars; + convertEnvList (envlst, env_vars); + + int limit = start_limit < 1 ? 1 : start_limit; + + Server_Info_Ptr si (new Server_Info (name, aname, cmdline, + env_vars, dir, amode, limit, partial_ior, ior)); + + this->repo_.servers ().bind (name, si); + } + virtual void next_activator (const ACE_CString& aname, + long token, + const ACE_CString& ior) + { + Activator_Info_Ptr si (new Activator_Info (aname, token, ior)); + this->repo_.activators ().bind (lcase (aname), si); + } +private: + Locator_Repository& repo_; +}; + +static int loadAsXML (const ACE_CString& fname, Locator_Repository& repo) +{ + ACEXML_FileCharStream* fstm = new ACEXML_FileCharStream; // xml input source will take ownership + + if (fstm->open (fname.c_str()) != 0) + { + // This is not a real error. The xml file may not exist yet. + delete fstm; + return 0; + } + + Server_Repo_XML_Callback cb (repo); + + Locator_XMLHandler handler (cb); + + ACEXML_Parser parser; + + // InputSource takes ownership + ACEXML_InputSource input (fstm); + + parser.setContentHandler (&handler); + parser.setDTDHandler (&handler); + parser.setErrorHandler (&handler); + parser.setEntityResolver (&handler); + + ACEXML_TRY_NEW_ENV + { + parser.parse (&input ACEXML_ENV_ARG_PARAMETER); + ACEXML_TRY_CHECK; + } + ACEXML_CATCH (ACEXML_Exception, ex) + { + ACE_ERROR ((LM_ERROR, "Error during load of ImR persistence xml file.")); + ex.print (); + return -1; + } + ACEXML_ENDTRY; + return 0; +} + +// Note : Would pass servers by const&, but ACE hash map const_iterator is broken. +static void saveAsXML (const ACE_CString& fname, Locator_Repository& repo) +{ + FILE* fp = ACE_OS::fopen (fname.c_str (), "w"); + if (fp == 0) + { + ACE_ERROR ((LM_ERROR, "Couldn't write to file %s\n", fname.c_str())); + return; + } + ACE_OS::fprintf (fp,"<?xml version=\"1.0\"?>\n"); + ACE_OS::fprintf (fp,"<%s>\n", Locator_XMLHandler::ROOT_TAG); + + // Save servers + Locator_Repository::SIMap::ENTRY* sientry = 0; + Locator_Repository::SIMap::ITERATOR siit (repo.servers ()); + for (; siit.next (sientry); siit.advance() ) + { + Server_Info_Ptr& info = sientry->int_id_; + + ACE_CString name = ACEXML_escape_string (info->name); + ACE_CString activator = ACEXML_escape_string (info->activator); + ACE_CString cmdline = ACEXML_escape_string (info->cmdline); + ACE_CString wdir = ACEXML_escape_string (info->dir); + ACE_CString partial_ior = ACEXML_escape_string (info->partial_ior); + ACE_CString ior = ACEXML_escape_string (info->ior); + + ACE_OS::fprintf (fp,"\t<%s", Locator_XMLHandler::SERVER_INFO_TAG); + ACE_OS::fprintf (fp," name=\"%s\"", name.c_str ()); + ACE_OS::fprintf (fp," activator=\"%s\"", activator.c_str ()); + ACE_OS::fprintf (fp," command_line=\"%s\"", cmdline.c_str ()); + ACE_OS::fprintf (fp," working_dir=\"%s\"", wdir.c_str ()); + ACE_CString amodestr = ImR_Utils::activationModeToString (info->activation_mode); + ACE_OS::fprintf (fp," activation_mode=\"%s\"", amodestr.c_str ()); + ACE_OS::fprintf (fp," start_limit=\"%d\"", info->start_limit); + ACE_OS::fprintf (fp," partial_ior=\"%s\"", partial_ior.c_str ()); + ACE_OS::fprintf (fp," ior=\"%s\"", ior.c_str ()); + ACE_OS::fprintf (fp,">\n"); + + for (CORBA::ULong i = 0; i < info->env_vars.length (); ++i) + { + ACE_OS::fprintf (fp,"\t\t<%s", Locator_XMLHandler::ENVIRONMENT_TAG); + ACE_OS::fprintf (fp," name=\"%s\"", info->env_vars[i].name.in ()); + ACE_CString val = ACEXML_escape_string (info->env_vars[i].value.in ()); + ACE_OS::fprintf (fp," value=\"%s\"", val.c_str ()); + ACE_OS::fprintf (fp,"/>\n"); + } + + ACE_OS::fprintf (fp,"\t</%s>\n", Locator_XMLHandler::SERVER_INFO_TAG); + } + + // Save Activators + Locator_Repository::AIMap::ENTRY* aientry = 0; + Locator_Repository::AIMap::ITERATOR aiit (repo.activators ()); + for (; aiit.next (aientry); aiit.advance ()) + { + ACE_CString aname = aientry->ext_id_; + Activator_Info_Ptr& info = aientry->int_id_; + ACE_OS::fprintf (fp,"\t<%s", Locator_XMLHandler::ACTIVATOR_INFO_TAG); + ACE_OS::fprintf( fp," name=\"%s\"", aname.c_str ()); + ACE_OS::fprintf (fp," token=\"%d\"", info->token); + ACE_OS::fprintf (fp," ior=\"%s\"", info->ior.c_str ()); + ACE_OS::fprintf (fp,"/>\n"); + } + + ACE_OS::fprintf (fp,"</%s>\n", Locator_XMLHandler::ROOT_TAG); + ACE_OS::fclose (fp); +} + +Locator_Repository::Locator_Repository () +: rmode_ (Options::REPO_NONE) +, config_ (0) +{ +} + +int +Locator_Repository::init(const Options& opts) +{ + this->rmode_ = opts.repository_mode (); + this->fname_ = opts.persist_file_name (); + + int err = 0; + switch (this->rmode_) + { + case Options::REPO_NONE: + { + break; + } + case Options::REPO_HEAP_FILE: + { + if (opts.repository_erase ()) + { + ACE_OS::unlink ( this->fname_.c_str () ); + } + ACE_Configuration_Heap* heap = new ACE_Configuration_Heap (); + this->config_.reset (heap); + err = heap->open (this->fname_.c_str ()); + if (err == 0) + { + loadAsBinary (*this->config_, *this); + } + break; + } + case Options::REPO_REGISTRY: + { +#if defined (ACE_WIN32) + if (opts.repository_erase ()) + { + ACE_Configuration_Win32Registry config ( HKEY_LOCAL_MACHINE ); + ACE_Configuration_Section_Key root; + config.open_section (config.root_section(), "Software\\TAO", 0, root); + config.remove_section (root, "ImplementationRepository", 1); + } + HKEY root = ACE_Configuration_Win32Registry:: + resolve_key (HKEY_LOCAL_MACHINE, WIN32_REG_KEY); + this->config_.reset (new ACE_Configuration_Win32Registry( root)); + loadAsBinary (*this->config_, *this); +#else + ACE_ERROR ((LM_ERROR, "Registry persistence is only " + "supported on Windows\n")); + err = -1; +#endif + break; + } + case Options::REPO_XML_FILE: + { + if (opts.repository_erase ()) + { + ACE_OS::unlink ( this->fname_.c_str() ); + } + err = loadAsXML (this->fname_, *this); + break; + } + default: + { + bool invalid_rmode_specified = false; + ACE_ASSERT (invalid_rmode_specified); + ACE_UNUSED_ARG (invalid_rmode_specified); + err = -1; + } + } + return err; +} + +int +Locator_Repository::add_server (const ACE_CString& name, + const ACE_CString& aname, + const ACE_CString& startup_command, + const ImplementationRepository::EnvironmentList& env_vars, + const ACE_CString& working_dir, + ImplementationRepository::ActivationMode activation, + int start_limit, + const ACE_CString& partial_ior, + const ACE_CString& ior, + ImplementationRepository::ServerObject_ptr svrobj) +{ + int limit = start_limit < 1 ? 1 : start_limit; + Server_Info_Ptr info(new Server_Info (name, aname, startup_command, + env_vars, working_dir, activation, limit, partial_ior, ior, svrobj)); + + int err = servers ().bind (name, info); + if (err != 0) + { + return err; + } + this->update_server (*info); + return 0; +} + +int +Locator_Repository::add_activator (const ACE_CString& name, + const CORBA::Long token, + const ACE_CString& ior, + ImplementationRepository::Activator_ptr act) +{ + Activator_Info_Ptr info (new Activator_Info (name, token, ior, act)); + + int err = activators ().bind (lcase (name), info); + if (err != 0) + { + return err; + } + this->update_activator (*info); + return 0; +} + +int +Locator_Repository::update_server (const Server_Info& info) +{ + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT (this->config_.get () != 0); + + ACE_Configuration& cfg = *this->config_; + + ACE_Configuration_Section_Key root; + ACE_Configuration_Section_Key key; + int err = cfg.open_section (cfg.root_section(), SERVERS_ROOT_KEY, 1, root); + if (err != 0) + { + ACE_ERROR ((LM_ERROR, "Unable to open config section:%s\n", SERVERS_ROOT_KEY)); + return err; + } + err = cfg.open_section (root, info.name.c_str (), 1, key); + if (err != 0) + { + ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", info.name.c_str())); + return err; + } + + ACE_CString envstr = ImR_Utils::envListToString(info.env_vars); + + cfg.set_string_value (key, ACTIVATOR, info.activator.c_str ()); + cfg.set_string_value (key, STARTUP_COMMAND, info.cmdline.c_str ()); + cfg.set_string_value (key, WORKING_DIR, info.dir.c_str ()); + cfg.set_string_value (key, ENVIRONMENT, envstr); + cfg.set_integer_value (key, ACTIVATION, info.activation_mode); + cfg.set_integer_value (key, START_LIMIT, info.start_limit); + cfg.set_string_value (key, PARTIAL_IOR, info.partial_ior.c_str ()); + cfg.set_string_value (key, IOR, info.ior.c_str()); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML (this->fname_, *this); + } + return 0; +} + +int +Locator_Repository::update_activator (const Activator_Info& info) +{ + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT(this->config_.get () != 0); + + ACE_Configuration& cfg = *this->config_; + + ACE_Configuration_Section_Key root; + ACE_Configuration_Section_Key key; + int err = cfg.open_section (cfg.root_section(), ACTIVATORS_ROOT_KEY, 1, root); + if (err != 0) + { + ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", ACTIVATORS_ROOT_KEY)); + return err; + } + err = cfg.open_section (root, info.name.c_str (), 1, key); + if (err != 0) + { + ACE_ERROR((LM_ERROR, "Unable to open config section:%s\n", info.name.c_str())); + return err; + } + + cfg.set_integer_value (key, TOKEN, info.token); + cfg.set_string_value (key, IOR, info.ior.c_str ()); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML( this->fname_, *this); + } + return 0; +} + +Server_Info_Ptr +Locator_Repository::get_server (const ACE_CString& name) +{ + Server_Info_Ptr server (0); + servers ().find (name, server); + return server; +} + +Activator_Info_Ptr +Locator_Repository::get_activator (const ACE_CString& name) +{ + Activator_Info_Ptr activator (0); + activators ().find (lcase (name), activator); + return activator; +} + +bool +Locator_Repository::has_activator (const ACE_CString& name) +{ + Activator_Info_Ptr activator (0); + return activators().find (lcase (name), activator) == 0; +} + +int +Locator_Repository::remove_server (const ACE_CString& name) +{ + int ret = this->servers().unbind (name); + if (ret != 0) + { + return ret; + } + + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT (this->config_.get() != 0); + ACE_Configuration& cfg = *this->config_; + ACE_Configuration_Section_Key root; + int err = cfg.open_section (cfg.root_section (), SERVERS_ROOT_KEY, 0, root); + if (err != 0) + { + return 0; // Already gone. + } + ret = cfg.remove_section (root, name.c_str (), 1); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML (this->fname_, *this); + } + return ret; +} + +int +Locator_Repository::remove_activator (const ACE_CString& name) +{ + int ret = activators().unbind (lcase(name)); + if (ret != 0) + { + return ret; + } + + if (rmode_ == Options::REPO_HEAP_FILE || rmode_ == Options::REPO_REGISTRY) + { + ACE_ASSERT (this->config_.get () != 0); + ACE_Configuration& cfg = *this->config_; + ACE_Configuration_Section_Key root; + int err = cfg.open_section (cfg.root_section (), ACTIVATORS_ROOT_KEY, 0, root); + if (err != 0) + { + return 0; // Already gone. + } + ret = cfg.remove_section (root, name.c_str (), 1); + } + else if (rmode_ == Options::REPO_XML_FILE) + { + saveAsXML (this->fname_, *this); + } + return ret; +} + +Locator_Repository::SIMap& +Locator_Repository::servers (void) +{ + return server_infos_; +} + +Locator_Repository::AIMap& +Locator_Repository::activators (void) +{ + return activator_infos_; +} + +const char* +Locator_Repository::repo_mode () +{ + switch (rmode_) + { + case Options::REPO_XML_FILE: + case Options::REPO_HEAP_FILE: + return fname_.c_str (); + case Options::REPO_REGISTRY: + return "Registry"; + case Options::REPO_NONE: + return "Disabled"; + } + return "Disabled"; +} diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.h b/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.h new file mode 100644 index 00000000000..2ef50b5753a --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_Repository.h @@ -0,0 +1,114 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** +* @file Locator_Repository.h +* +* $Id$ +* +* This class implements the Repository for the Implementation Repository. +* +* @author Darrell Brunsch <brunsch@cs.wustl.edu> +* @author Priyanka Gontla <gontla_p@ociweb.com> +*/ +//============================================================================= + +#ifndef REPOSITORY_H +#define REPOSITORY_H + +#include "Server_Info.h" +#include "Activator_Info.h" +#include "Locator_Options.h" + +#include "ace/Hash_Map_Manager.h" +#include "ace/Configuration.h" +#include "ace/Auto_Ptr.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** +* @class Locator_Repository +* +* @brief Database containing all ImR persistent information. +* +*/ +class Locator_Repository +{ +public: + typedef ACE_Hash_Map_Manager_Ex<ACE_CString, + Server_Info_Ptr, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> SIMap; + + typedef ACE_Hash_Map_Manager_Ex<ACE_CString, + Activator_Info_Ptr, + ACE_Hash<ACE_CString>, + ACE_Equal_To<ACE_CString>, + ACE_Null_Mutex> AIMap; + + Locator_Repository(); + + /// Initializes the Server Repository + int init (const Options& opts); + + /// Add a new server to the Repository + int add_server (const ACE_CString& name, + const ACE_CString& aname, + const ACE_CString& startup_command, + const ImplementationRepository::EnvironmentList& environment_vars, + const ACE_CString& working_dir, + ImplementationRepository::ActivationMode activation, + int start_limit, + const ACE_CString& partial_ior = ACE_CString(""), + const ACE_CString& ior = ACE_CString(""), + ImplementationRepository::ServerObject_ptr svrobj = ImplementationRepository::ServerObject::_nil() + ); + /// Add a new activator to the Repository + int add_activator (const ACE_CString& name, + const CORBA::Long token, + const ACE_CString& ior = ACE_CString(""), + ImplementationRepository::Activator_ptr act = ImplementationRepository::Activator::_nil() + ); + + /// Update the associated information. + int update_server (const Server_Info& info); + /// Update the associated information. + int update_activator (const Activator_Info& info); + + /// Returns information related to startup. + Server_Info_Ptr get_server (const ACE_CString& name); + /// Returns information related to startup. + Activator_Info_Ptr get_activator (const ACE_CString& name); + + bool has_activator(const ACE_CString& name); + + /// Removes the server from the Repository. + int remove_server (const ACE_CString& name); + /// Removes the activator from the Repository. + int remove_activator (const ACE_CString& name); + + /// Returns the internal hash map containing the server information. + SIMap& servers(void); + /// Returns the internal hash map containing the activator information. + AIMap& activators(void); + + const char* repo_mode(); + +private: + // Type mechanism to use for persistence. + Options::RepoMode rmode_; + // The in-memory list of the server information. + SIMap server_infos_; + // The in-memory list of the activator information. + AIMap activator_infos_; + // Several rmode_ values require this. + ACE_Auto_Ptr<ACE_Configuration> config_; + // XML requires the file name + ACE_CString fname_; +}; + + +#endif /* REPOSITORY_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_XMLHandler.cpp b/TAO/orbsvcs/ImplRepo_Service/Locator_XMLHandler.cpp new file mode 100644 index 00000000000..a1ddcf0b3d9 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_XMLHandler.cpp @@ -0,0 +1,97 @@ +// $Id$ + +#include "Locator_XMLHandler.h" +#include "ace/OS_NS_strings.h" + +ACE_RCSID (ImplRepo_Service,Locator_XMLHandler,"$Id$") + +const char* Locator_XMLHandler::ROOT_TAG = "ImplementationRepository"; +const char* Locator_XMLHandler::SERVER_INFO_TAG = "Servers"; +const char* Locator_XMLHandler::ACTIVATOR_INFO_TAG = "Activators"; +const char* Locator_XMLHandler::ENVIRONMENT_TAG = "EnvironmentVariables"; + +Locator_XMLHandler::Locator_XMLHandler (Callback& cb) +: callback_ (cb) +{ +} + +void +Locator_XMLHandler::startElement (const ACEXML_Char*, + const ACEXML_Char*, + const ACEXML_Char* qName, + ACEXML_Attributes* attrs ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + ACE_ASSERT (qName != 0); + if (ACE_OS::strcasecmp (qName, SERVER_INFO_TAG) == 0) + { + // We'll use this as a key to determine if we've got a valid record + this->server_name_ = ""; + this->env_vars_.clear(); + + if (attrs != 0 && attrs->getLength () == 8) + { + this->server_name_ = attrs->getValue ((size_t)0); + this->activator_name_ = attrs->getValue ((size_t)1); + this->command_line_ = attrs->getValue ((size_t)2); + this->working_dir_ = attrs->getValue ((size_t)3); + this->activation_ = attrs->getValue ((size_t)4); + this->env_vars_.clear (); + int limit = ACE_OS::atoi (attrs->getValue ((size_t)5)); + this->start_limit_ = limit; + this->partial_ior_ = attrs->getValue ((size_t)6); + this->server_object_ior_ = attrs->getValue ((size_t)7); + } + } + else if (ACE_OS::strcasecmp (qName, ACTIVATOR_INFO_TAG) == 0) + { + if (attrs != 0 && attrs->getLength () == 3) + { + ACE_CString aname = attrs->getValue ((size_t)0); + ACE_CString token_str = attrs->getValue ((size_t)1); + long token = ACE_OS::atoi (token_str.c_str ()); + ACE_CString ior = attrs->getValue ((size_t)2); + this->callback_.next_activator (aname, token, ior); + } + } + else if (ACE_OS::strcasecmp (qName, ENVIRONMENT_TAG) == 0) + { + if (attrs != 0 && attrs->getLength () == 2) + { + EnvVar ev; + ev.name = attrs->getValue ((size_t)0); + ev.value = attrs->getValue ((size_t)1); + this->env_vars_.push_back (ev); + } + } +} + +void +Locator_XMLHandler::endElement (const ACEXML_Char*, + const ACEXML_Char*, + const ACEXML_Char* qName ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + ACE_ASSERT(qName != 0); + if (ACE_OS::strcasecmp (qName, SERVER_INFO_TAG) == 0 + && this->server_name_.length () > 0) + { + this->callback_.next_server (this->server_name_, + this->activator_name_, this->command_line_, + this->env_vars_, this->working_dir_, this->activation_, + this->start_limit_, this->partial_ior_, this->server_object_ior_); + } + // activator info is handled in the startElement +} + +bool +Locator_XMLHandler::EnvVar::operator== (const EnvVar& rhs) const +{ + return name == rhs.name && value == rhs.value; +} +bool +Locator_XMLHandler::EnvVar::operator!= (const EnvVar& rhs) const +{ + return ! (rhs == *this); +} + diff --git a/TAO/orbsvcs/ImplRepo_Service/Locator_XMLHandler.h b/TAO/orbsvcs/ImplRepo_Service/Locator_XMLHandler.h new file mode 100644 index 00000000000..ff8691d0a78 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Locator_XMLHandler.h @@ -0,0 +1,88 @@ +// -*- C++ -*- +//============================================================================= +/** + * @file Locator_XMLHandler.h + * + * $Id$ + * + * @author Justin Michel <michel_j@ociweb.com> + */ +//============================================================================= + +#ifndef Locator_XMLHandler_H +#define Locator_XMLHandler_H + +#include "ACEXML/common/DefaultHandler.h" + +#include "ace/Vector_T.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** + * Callback SAX XML Handler for parsing XML. + */ +class Locator_XMLHandler : public ACEXML_DefaultHandler +{ +public: + + // XML ELEMENT names + static const char* ROOT_TAG; + static const char* SERVER_INFO_TAG; + static const char* ENVIRONMENT_TAG; + static const char* ACTIVATOR_INFO_TAG; + + struct EnvVar { + ACE_CString name; + ACE_CString value; + bool operator==(const EnvVar&) const; // To allow Vector explicit instantiation + bool operator!=(const EnvVar&) const; // To allow Vector explicit instantiation + }; + + typedef ACE_Vector<EnvVar> EnvList; + + struct Callback { + virtual ~Callback() {} + + virtual void next_server (const ACE_CString& server_name, + const ACE_CString& aname, const ACE_CString& startup_cmd, + const EnvList& env_vars, const ACE_CString& working_dir, + const ACE_CString& actmode, int start_limit, + const ACE_CString& partial_ior, const ACE_CString& ior) = 0; + + virtual void next_activator (const ACE_CString& activator_name, + long token, + const ACE_CString& ior) = 0; + }; + + Locator_XMLHandler (Callback& cb); + + virtual void startElement (const ACEXML_Char* namespaceURI, + const ACEXML_Char* localName, + const ACEXML_Char* qName, + ACEXML_Attributes* atts ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)); + + virtual void endElement (const ACEXML_Char* namespaceURI, + const ACEXML_Char* localName, + const ACEXML_Char* qName ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)); + + private: + + // callback on completion of an element + Callback& callback_; + + ACE_CString server_name_; + ACE_CString activator_name_; + ACE_CString command_line_; + ACE_CString activation_; + ACE_CString working_dir_; + ACE_CString server_object_ior_; + ACE_CString partial_ior_; + int start_limit_; + EnvList env_vars_; +}; + +#endif /* Locator_XMLHandler_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/Makefile.am b/TAO/orbsvcs/ImplRepo_Service/Makefile.am new file mode 100644 index 00000000000..166dacc12a0 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Makefile.am @@ -0,0 +1,391 @@ +## Process this file with automake to create Makefile.in +## +## $Id$ +## +## This file was generated by MPC. Any changes made directly to +## this file will be lost the next time it is generated. +## +## MPC Command: +## ../bin/mwc.pl -type automake -noreldefs TAO.mwc + +ACE_BUILDDIR = $(top_builddir)/.. +ACE_ROOT = $(top_srcdir)/.. +TAO_BUILDDIR = $(top_builddir) +TAO_IDL = ACE_ROOT=$(ACE_ROOT) TAO_ROOT=$(TAO_ROOT) $(TAO_BUILDDIR)/TAO_IDL/tao_idl +TAO_IDL_DEP = $(TAO_BUILDDIR)/TAO_IDL/tao_idl +TAO_IDLFLAGS = -Ge 1 -Wb,pre_include=ace/pre.h -Wb,post_include=ace/post.h -I$(TAO_ROOT) -I$(srcdir) -g $(ACE_BUILDDIR)/apps/gperf/src/gperf +TAO_ROOT = $(top_srcdir) + +bin_PROGRAMS = + +## Makefile.ImR_Activator_IDL.am + +BUILT_SOURCES = \ + ImR_ActivatorC.cpp \ + ImR_ActivatorC.h \ + ImR_ActivatorC.inl \ + ImR_ActivatorS.cpp \ + ImR_ActivatorS.h \ + ImR_ActivatorS.inl \ + ImR_ActivatorS_T.cpp \ + ImR_ActivatorS_T.h \ + ImR_ActivatorS_T.inl + +CLEANFILES = \ + ImR_Activator-stamp \ + ImR_ActivatorC.cpp \ + ImR_ActivatorC.h \ + ImR_ActivatorC.inl \ + ImR_ActivatorS.cpp \ + ImR_ActivatorS.h \ + ImR_ActivatorS.inl \ + ImR_ActivatorS_T.cpp \ + ImR_ActivatorS_T.h \ + ImR_ActivatorS_T.inl + +ImR_ActivatorC.cpp ImR_ActivatorC.h ImR_ActivatorC.inl ImR_ActivatorS.cpp ImR_ActivatorS.h ImR_ActivatorS.inl ImR_ActivatorS_T.cpp ImR_ActivatorS_T.h ImR_ActivatorS_T.inl: ImR_Activator-stamp + +ImR_Activator-stamp: $(srcdir)/ImR_Activator.idl $(TAO_IDL_DEP) + $(TAO_IDL) $(TAO_IDLFLAGS) -I$(TAO_ROOT)/orbsvcs -GT -Wb,versioning_begin=TAO_BEGIN_VERSIONED_NAMESPACE_DECL -Wb,versioning_end=TAO_END_VERSIONED_NAMESPACE_DECL -Wb,export_macro=ActivatorIDL_Export -Wb,export_include=activator_idl_export.h $(srcdir)/ImR_Activator.idl + @touch $@ + +noinst_LTLIBRARIES = libTAO_ImR_Activator_IDL.la + +libTAO_ImR_Activator_IDL_la_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs \ + -DACTIVATOR_IDL_BUILD_DLL + +libTAO_ImR_Activator_IDL_la_SOURCES = \ + ImR_ActivatorC.cpp \ + ImR_ActivatorS.cpp + +noinst_HEADERS = \ + ImR_Activator.idl \ + ImR_ActivatorC.h \ + ImR_ActivatorC.inl \ + ImR_ActivatorS.h \ + ImR_ActivatorS.inl \ + ImR_ActivatorS_T.cpp \ + ImR_ActivatorS_T.h \ + ImR_ActivatorS_T.inl \ + activator_idl_export.h + +## Makefile.ImR_Locator_IDL.am + +if BUILD_CORBA_MESSAGING + +BUILT_SOURCES += \ + ImR_LocatorC.cpp \ + ImR_LocatorC.h \ + ImR_LocatorC.inl \ + ImR_LocatorS.cpp \ + ImR_LocatorS.h \ + ImR_LocatorS.inl \ + ImR_LocatorS_T.cpp \ + ImR_LocatorS_T.h \ + ImR_LocatorS_T.inl + +CLEANFILES += \ + ImR_Locator-stamp \ + ImR_LocatorC.cpp \ + ImR_LocatorC.h \ + ImR_LocatorC.inl \ + ImR_LocatorS.cpp \ + ImR_LocatorS.h \ + ImR_LocatorS.inl \ + ImR_LocatorS_T.cpp \ + ImR_LocatorS_T.h \ + ImR_LocatorS_T.inl + +ImR_LocatorC.cpp ImR_LocatorC.h ImR_LocatorC.inl ImR_LocatorS.cpp ImR_LocatorS.h ImR_LocatorS.inl ImR_LocatorS_T.cpp ImR_LocatorS_T.h ImR_LocatorS_T.inl: ImR_Locator-stamp + +ImR_Locator-stamp: $(srcdir)/ImR_Locator.idl $(TAO_IDL_DEP) + $(TAO_IDL) $(TAO_IDLFLAGS) -I$(TAO_ROOT)/orbsvcs -GT -Wb,versioning_begin=TAO_BEGIN_VERSIONED_NAMESPACE_DECL -Wb,versioning_end=TAO_END_VERSIONED_NAMESPACE_DECL -Wb,export_macro=LocatorIDL_Export -Wb,export_include=locator_idl_export.h $(srcdir)/ImR_Locator.idl + @touch $@ + +BUILT_SOURCES += \ + AsyncStartupWaiterC.cpp \ + AsyncStartupWaiterC.h \ + AsyncStartupWaiterC.inl \ + AsyncStartupWaiterS.cpp \ + AsyncStartupWaiterS.h \ + AsyncStartupWaiterS.inl \ + AsyncStartupWaiterS_T.cpp \ + AsyncStartupWaiterS_T.h \ + AsyncStartupWaiterS_T.inl + +CLEANFILES += \ + AsyncStartupWaiter-stamp \ + AsyncStartupWaiterC.cpp \ + AsyncStartupWaiterC.h \ + AsyncStartupWaiterC.inl \ + AsyncStartupWaiterS.cpp \ + AsyncStartupWaiterS.h \ + AsyncStartupWaiterS.inl \ + AsyncStartupWaiterS_T.cpp \ + AsyncStartupWaiterS_T.h \ + AsyncStartupWaiterS_T.inl + +AsyncStartupWaiterC.cpp AsyncStartupWaiterC.h AsyncStartupWaiterC.inl AsyncStartupWaiterS.cpp AsyncStartupWaiterS.h AsyncStartupWaiterS.inl AsyncStartupWaiterS_T.cpp AsyncStartupWaiterS_T.h AsyncStartupWaiterS_T.inl: AsyncStartupWaiter-stamp + +AsyncStartupWaiter-stamp: $(srcdir)/AsyncStartupWaiter.idl $(TAO_IDL_DEP) + $(TAO_IDL) $(TAO_IDLFLAGS) -I$(TAO_ROOT)/orbsvcs -GT -Wb,versioning_begin=TAO_BEGIN_VERSIONED_NAMESPACE_DECL -Wb,versioning_end=TAO_END_VERSIONED_NAMESPACE_DECL -Wb,export_macro=LocatorIDL_Export -Wb,export_include=locator_idl_export.h -GH $(srcdir)/AsyncStartupWaiter.idl + @touch $@ + +noinst_LTLIBRARIES += libTAO_ImR_Locator_IDL.la + +libTAO_ImR_Locator_IDL_la_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs \ + -DLOCATOR_IDL_BUILD_DLL + +libTAO_ImR_Locator_IDL_la_SOURCES = \ + AsyncStartupWaiterC.cpp \ + AsyncStartupWaiterS.cpp \ + ImR_LocatorC.cpp \ + ImR_LocatorS.cpp + +noinst_HEADERS += \ + AsyncStartupWaiter.idl \ + AsyncStartupWaiterC.h \ + AsyncStartupWaiterC.inl \ + AsyncStartupWaiterS.h \ + AsyncStartupWaiterS.inl \ + AsyncStartupWaiterS_T.cpp \ + AsyncStartupWaiterS_T.h \ + AsyncStartupWaiterS_T.inl \ + ImR_Locator.idl \ + ImR_LocatorC.h \ + ImR_LocatorC.inl \ + ImR_LocatorS.h \ + ImR_LocatorS.inl \ + ImR_LocatorS_T.cpp \ + ImR_LocatorS_T.h \ + ImR_LocatorS_T.inl \ + locator_idl_export.h + +endif BUILD_CORBA_MESSAGING + +## Makefile.ImR_Activator.am + +if BUILD_ACEXML +if BUILD_CORBA_MESSAGING +if !BUILD_ACE_FOR_TAO +if !BUILD_MINIMUM_CORBA + +noinst_LTLIBRARIES += libTAO_ImR_Activator.la + +libTAO_ImR_Activator_la_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs \ + -I$(ACE_ROOT)/ACEXML/common \ + -DACTIVATOR_BUILD_DLL + +libTAO_ImR_Activator_la_SOURCES = \ + Activator_Loader.cpp \ + Activator_Options.cpp \ + ImR_Activator_i.cpp + +noinst_HEADERS += \ + Activator_Loader.h \ + Activator_Options.h \ + ImR_Activator_i.h \ + activator_export.h + +endif !BUILD_MINIMUM_CORBA +endif !BUILD_ACE_FOR_TAO +endif BUILD_CORBA_MESSAGING +endif BUILD_ACEXML + +## Makefile.ImR_Activator_Service.am + +if BUILD_ACEXML +if BUILD_CORBA_MESSAGING +if !BUILD_ACE_FOR_TAO +if !BUILD_MINIMUM_CORBA + +bin_PROGRAMS += ImR_Activator + +ImR_Activator_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(ACE_ROOT)/ACEXML/common \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs + +ImR_Activator_SOURCES = \ + Activator_NT_Service.cpp \ + ImR_Activator.cpp \ + Activator_NT_Service.h + +ImR_Activator_LDADD = \ + libTAO_ImR_Activator.la \ + libTAO_ImR_Activator_IDL.la \ + libTAO_ImR_Locator_IDL.la \ + $(TAO_BUILDDIR)/tao/libTAO_ImR_Client.la \ + $(TAO_BUILDDIR)/orbsvcs/orbsvcs/libTAO_Svc_Utils.la \ + $(TAO_BUILDDIR)/tao/libTAO_Messaging.la \ + $(TAO_BUILDDIR)/tao/libTAO_PI.la \ + $(TAO_BUILDDIR)/tao/libTAO_CodecFactory.la \ + $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \ + $(TAO_BUILDDIR)/tao/libTAO_Valuetype.la \ + $(ACE_BUILDDIR)/ACEXML/parser/parser/libACEXML_Parser.la \ + $(ACE_BUILDDIR)/ACEXML/common/libACEXML.la \ + $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \ + $(TAO_BUILDDIR)/tao/libTAO.la \ + $(ACE_BUILDDIR)/ace/libACE.la + +endif !BUILD_MINIMUM_CORBA +endif !BUILD_ACE_FOR_TAO +endif BUILD_CORBA_MESSAGING +endif BUILD_ACEXML + +## Makefile.ImR_Locator.am + +if BUILD_ACEXML +if BUILD_CORBA_MESSAGING +if !BUILD_ACE_FOR_TAO +if !BUILD_MINIMUM_CORBA + +noinst_LTLIBRARIES += libTAO_ImR_Locator.la + +libTAO_ImR_Locator_la_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs \ + -I$(ACE_ROOT)/ACEXML/common \ + -DLOCATOR_BUILD_DLL + +libTAO_ImR_Locator_la_SOURCES = \ + Activator_Info.cpp \ + Adapter_Activator.cpp \ + AsyncStartupWaiter_i.cpp \ + Forwarder.cpp \ + INS_Locator.cpp \ + ImR_Locator_i.cpp \ + Iterator.cpp \ + Locator_Loader.cpp \ + Locator_Options.cpp \ + Locator_Repository.cpp \ + Locator_XMLHandler.cpp \ + Server_Info.cpp + +noinst_HEADERS += \ + Activator_Info.h \ + Adapter_Activator.h \ + AsyncStartupWaiter_i.h \ + Forwarder.h \ + INS_Locator.h \ + ImR_Locator_i.h \ + Iterator.h \ + Locator_Loader.h \ + Locator_Options.h \ + Locator_Repository.h \ + Locator_XMLHandler.h \ + Server_Info.h \ + locator_export.h \ + utils.h + +endif !BUILD_MINIMUM_CORBA +endif !BUILD_ACE_FOR_TAO +endif BUILD_CORBA_MESSAGING +endif BUILD_ACEXML + +## Makefile.ImR_Locator_Service.am + +if BUILD_ACEXML +if BUILD_CORBA_MESSAGING +if !BUILD_ACE_FOR_TAO +if !BUILD_MINIMUM_CORBA + +bin_PROGRAMS += ImplRepo_Service + +ImplRepo_Service_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) \ + -I$(ACE_ROOT)/ACEXML/common \ + -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_BUILDDIR)/orbsvcs + +ImplRepo_Service_SOURCES = \ + ImR_Locator.cpp \ + Locator_NT_Service.cpp \ + Locator_NT_Service.h + +ImplRepo_Service_LDADD = \ + libTAO_ImR_Locator.la \ + libTAO_ImR_Activator_IDL.la \ + libTAO_ImR_Locator_IDL.la \ + $(TAO_BUILDDIR)/tao/libTAO_ImR_Client.la \ + $(TAO_BUILDDIR)/tao/libTAO_PI_Server.la \ + $(TAO_BUILDDIR)/orbsvcs/orbsvcs/libTAO_Svc_Utils.la \ + $(ACE_BUILDDIR)/ACEXML/parser/parser/libACEXML_Parser.la \ + $(ACE_BUILDDIR)/ACEXML/common/libACEXML.la \ + $(TAO_BUILDDIR)/tao/libTAO_Messaging.la \ + $(TAO_BUILDDIR)/tao/libTAO_PI.la \ + $(TAO_BUILDDIR)/tao/libTAO_CodecFactory.la \ + $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \ + $(TAO_BUILDDIR)/tao/libTAO_Valuetype.la \ + $(TAO_BUILDDIR)/tao/libTAO_IORTable.la \ + $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \ + $(TAO_BUILDDIR)/tao/libTAO.la \ + $(ACE_BUILDDIR)/ace/libACE.la + +endif !BUILD_MINIMUM_CORBA +endif !BUILD_ACE_FOR_TAO +endif BUILD_CORBA_MESSAGING +endif BUILD_ACEXML + +## Makefile.tao_imr.am + +if !BUILD_MINIMUM_CORBA + +bin_PROGRAMS += tao_imr + +tao_imr_CPPFLAGS = \ + -I$(ACE_ROOT) \ + -I$(ACE_BUILDDIR) \ + -I$(TAO_ROOT) \ + -I$(TAO_BUILDDIR) + +tao_imr_SOURCES = \ + tao_imr.cpp \ + tao_imr_i.cpp \ + tao_imr_i.h + +tao_imr_LDADD = \ + $(TAO_BUILDDIR)/tao/libTAO_ImR_Client.la \ + $(TAO_BUILDDIR)/tao/libTAO_PortableServer.la \ + $(TAO_BUILDDIR)/tao/libTAO_AnyTypeCode.la \ + $(TAO_BUILDDIR)/tao/libTAO.la \ + $(ACE_BUILDDIR)/ace/libACE.la + +endif !BUILD_MINIMUM_CORBA + +## Clean up template repositories, etc. +clean-local: + -rm -f *~ *.bak *.rpo *.sym lib*.*_pure_* core core.* + -rm -f gcctemp.c gcctemp so_locations *.ics + -rm -rf cxx_repository ptrepository ti_files + -rm -rf templateregistry ir.out + -rm -rf ptrepository SunWS_cache Templates.DB diff --git a/TAO/orbsvcs/ImplRepo_Service/README.txt b/TAO/orbsvcs/ImplRepo_Service/README.txt new file mode 100644 index 00000000000..f6f8082f21b --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/README.txt @@ -0,0 +1,590 @@ +/** -*- HTML-Helper -*- $Id$ + +@mainpage Implementation Repository + +@section intro Introduction + +The purpose of the Implementation Repository (ImR) in TAO is for the automatic +activation of a TAO server when a method is invoked but the server is not +running. It does this by working with the server to keep track of when it is +activated and stores information on how to reactivate it. Method +invocations on the server will actually be sent to the Implementation +Repository, which will then be able to start the server process if it is not +already running and forward the invocation to the real server. + +@section resources Resources + +The ImR in TAO was first based on a paper on the subject by +<a href="http://www.triodia.com/staff/michi-henning.html">Michi Henning</a> +called <a href="http://www.triodia.com/staff/michi/cacm.pdf">Binding, +Migration, and Scalability in CORBA</a>. Mr. Henning later went on to +coauthor the book +<a href="http://cseng.awl.com/bookdetail.qry?ISBN=0-201-37927-9&ptype=0"> +Advanced CORBA Programming in C++</a> and included a chapter on the +Implementation Repository. The description of the ImR in this chapter is used +as the specification for TAO's ImR. + +@ref usersguide - Overall documentation on how to use the ImR in your programs + +@ref future - Future Work + +@ref ntservice - Running the ImR as a NT Service + +@ref imrandnaming - Using the Naming Service with the Implmentation Repository + +@ref movefromoldImR - Moving from IMR as in TAO 1.2.2 to the present version. + +@section authors Authors + +The guy who first worked on ImR and provided a base for the current +ImR is Darrell Brunsch +@<<a href="mailto:brunsch@cs.wustl.edu">brunsch@cs.wustl.edu</a>@>. +The current version is developed by Priyanka Gontla +@<<a href="mailto:gontla_p@ociweb.com">gontla_p@ociweb.com</a>@>. +You can reach us by either email (which is better), or through the +<a href="http://www.cs.wustl.edu/~schmidt/ACE-mail.html">ACE mailing list</a> +@<<a href="mailto:ace-useres@cs.wustl.edu">ace-users@cs.wustl.edu</a>@>, +or through the <a href="news:comp.soft-sys.ace">comp.soft-sys.ace</a> +newsgroup. The newsgroup mirrors the mailing list, but not the other way. +Also, if you use the mailing list, it is best if you join it before sending +a question since responses are usually just replied back to the group. + +The NT Service part of the ImR was developed by Jeff Parsons @<<a +href="mailto:parsons@cs.wustl.edu">parsons@cs.wustl.edu</a>@>. He can +also be reached via the same channels. +It was later extended and enhanced by Justin Michel <michel_j@ociweb.com> + +*/ + +/** +@page future Future Work + +As with any program, there is always a wishlist of things to do. + +@subsection ort Use Object Reference Template (ORT) Features + + Use ORT so that the ImR-ified IORs doesnt have any information +about the ImR_Activators. Right now, even though, the ImplRepo_Service is +the one that is exposed to the client, the IOR will have a reference +to the ImR_Activator. By using ORT features, we want the IOR to refer +to the ImplRepo_Service rather than the underlying ImR_Activator. That way +the ImR_Activator is totally blocked from the client using the ImR +service. + +@subsection ort_design Design Considerations + + For the above mentioned purposes, we can say that the ImplRepo_Service +acts as the gateway which receives requests on behalf of the actual +ImR_Activator. + + The ImplRepo_Service will now need a new IDL method 'create_object'. The +create_object method will take the interface_repository_id of the +object that has to be gatewayed (ImR_Activator's) and the +CORBA::Object_ptr of the gatewayed object. And, using these two will +create an object which will point to the ImplRepo_Service and will also +know that the ultimate receiver is the ImR_Activator. + + So, this is how it works. + + As before, we will first run the ImplRepo_Service. And, then run an +ImR_Activator. We will use interceptors and in the post_init method, +we will add an ior interceptor which will have the ImplRepo_Service +object. By this, the IOR that is generated will actually point to the +ImplRepo_Service rather than ImR_Activator. So, the IOR which is visible to +the client will show that the IOR actually points to the ImplRepo_Service. + + When a client sends a request to the ImplRepo_Service, the request +will come to ImplRepo_Service which will send the request to the actual +ImR_Activator. + +@subsection AMH Use AMH Features + + Use the AMH features to improve the TAO IMR performance. + +@subsection logicalnames Logical Server names + +In the IDL interface, but not used on the server side or fully implemented in +tao_ImR. + +@subsection shutdown Server Shutdown + +Only cooperative shutdown implemented right now. Since we keep track of the +Process ID, then we could kill the server if it doesn't cooperate. + +@subsection optimization Client-side Optimizations + +Nothing yet. + +@subsection security Server Security + +Nothing really here. There is two main things I have in mind. + +First, the security service would be useful to restrict access to some +of the Administration methods + +Second, without a security service we should provide some sort of flag to +the ImR that disables the Administration methods. That way, the database +can be set up with the servers in a controlled run of the ImR. Then the +ImR could be run again reading in the database without Admin access. + +@subsection federations Federations + +Nothing yet. + +@subsection dllserver DLL servers + +Nothing yet. + +@subsection XML Database Support + + As of now, the support is only to be able to have the information + about a registered server written to an XML file. Have to support +retrieving information from the XML file to be able to do any actions +on the registered servers. + +@subsection Remove ImR_Activator + + We can now successfully register an ImR_Activator. But, we have to +yet provide support to gracefully unregister the ImR_Activator from +the ImplRepo_Service. The ImplRepo_Service then has to try to transfer the +servers that were registered with this instance to other activators. +*/ + +/** +@page usersguide Implementation Repository User's Guide + +In order for a server to make use of the Implementation Repository, it must +communicate with the ImR to keep it up to date on such things as the server's +running status. These functions now are contained within the POA, so when a +Persistent POA is used on a server that has -ORBUseImR specified, it will +communicate with an Implementation Repository, if one is available. + +@subsection description The New ImR + + The new ImR is based on the ImR in TAO 1.2.2 with added +features to help improve throughput and load balancing. The work to be +performed by the Implementation Repository is distributed between two +entities (ImplRepo_Service and ImR_Activator) to help achieve the goal of +better throughput and load balance. + +@subsection locator ImplRepo_Service + + The ImplRepo_Service acts as the main server which is visible to +the application intending to use the ImR. It receives requests sent +via tao_ImR and distributes the work to the registered ImR_Activators. +It is stateless and does not maintain any information except about the +ImR_Activators that are registered with it. Its job is to act as +a mediator between the application and the actual ImR_Activator that does +the real work. As of now, we only support one ImplRepo_Service to be running at +any time. ImplRepo_Service can be reached through the usual methods of +-ORBInitRef and -ORBDefaultInitRef and multicast. + +Commandline Arguments that can be passed to ImplRepo_Service + +-d debug information +-m support multicast discovery. +-o generate the ior. +-x support persistence to the ImplRepo_Service. We use XML to support + persistence. Names of the activators registered with the locator, + their IORs, and the servers registered with each of the activators are + saved to the xml file. Use this option to pass the name of the file + where the data has to be saved. + + And, ofcourse, the ORB Options. + + +@subsection activator ImR_Activator + + ImR_Activators, as you might have guessed, do the real work of +activating servers or shutting them down and maintaining the information +about servers related to them. Only one instance of an ImR_Activator +can be run on one host. The ImR_Activator is not exposed at all to the +application. Only the ImplRepo_Service needs to and it is the only one that +can contact the ImR_Activator. + + An instance of ImR_Activator first registers itself with the +ImplRepo_Service so that it can begin to receive requests. When registering +with the ImplRepo_Service, it passes the hostname where it is being run and +its IOR to the ImplRepo_Service. And, the ImplRepo_Service reaches it using the +same information. + +The Commandline paramters that are valid for ImR_Activator are + +-c: Run the Service command. +-d:number Debug Information +-l lock the database. +-o Generate the IOR to a file (just in case some one wants + to read the IOR) +-r Enable Win32 regsitry implementation. +-s Run as a service. +-t Set a timeout value. +-h Prints the help. + + When Persistence of an ImR_Activator is required, we will save +the information about the server's that this ImR_Activator is related +to in a file (being the easy form of a persistent database). The +information about each server include its startup options, location, +working directory which are needed to execute the requests that can +passed by tao_imr with regards to the server. + + There are two ways in which you can store data in the +file. One way is to use ACE_Configuration_Heap to save all +the information to the file. To do this, we have to pass the '-p' option. + +-p Pass the ImplRepo service a filename to use for the + backing store. Uses ACE_Configuration_Heap. + + The second way is to save in XML-ized format. + +-x Pass the filename where the repository information should + be saved. Use XML format. + + +@subsection work So how does the whole thing work? + + The first thing to do is to have an ImplRepo_Service running. Once +the ImplRepo_Service is running, we can instantiate one or more ImR_Activators +as needed per the application. As mentioned already, the +ImR_Activators, upon instantiation, register with the ImplRepo_Service to +be able to receive requests. + + When a new server has to be added or any change has to the +done to an existing server, a request is to be sent to the ImplRepo_Service +via the tao_imr utility. Startup commands, the working directory, the +host where the server should be started up and such other information +are passed to the ImplRepo_Service via the TAO_ImR commandline arguments. + + If the host where the server should be started up is passed +while adding a new server, the ImplRepo_Service chooses the ImR_Activator +that is running on that host to be responsible for the server's +activities. Otherwise, an ImR_Activator is chosen based on the Round +robin algorithm. We plan to use better algorithms based on the +existing load for the same purpose in future. Whatever way the +ImR_Activator is chosen for a server, once an ImR_Activator is chosen, +that ImR_Activator remains reponsible for the server throughout the +server's lifetime. + + After an ImR_Activator is chosen, the ImplRepo_Service passes the +request to the chosen ImR_Activator. The ImR_Activator acts on the request +and updates its database to reflect the new state of the server. + +@subsection run How is the ImR run? + +<ol> + <li>First run the <b>ImplRepo_Service</b> + <em>Example:<code> </code> </em><code> ImplRepo_Service -o locator.ior<br></code> + <li>Run the <b>Activator</b> + <em>Example:<code> </code> </em><code> ImR_Activator -ORBInitRef ImplRepoService=file://locator.ior<br></code> + +@subsection use How is the ImR used? + +The main steps for the lifetime of a server that uses the ImR are generally +the following: + +<ol> + <li>Register name and startup commands with the ImR using <b>tao_ImR<br> + </b><em>Example:<code> </code> </em><code> tao_ImR -ORBInitRef + ImplRepoService=file://locator.ior add plane -c "airplane_server -i + -ORBInitRef ImplRepoService=file://locator.ior"<br></code> + <br> + Note that the name used to register the server is the name of the POA + which the objects are created in. So in this example, the airplane_server + creates a POA called "plane" and activates its servants under + it.<br> + <li>Start the server once to generate an ImR-ified IOR<br> + <li>Start clients and pass them the above IOR<br> + <li>Clients will use the IOR, which will automatically go through the ImR<br> + <li>The ImR will start the server if it is not already running<br> + <li>At any time when the server is not currently in use by a client, it can be + shut down using <strong>tao_ImR<br></strong><em>Example:</em><code> tao_ImR + -ORBInitRef ImplRepoService=file://locator.ior shutdown plane<br> + </code> + <li>After the server isn't needed anymore, it can be removed from the ImR database + using <strong>tao_ImR<br></strong><em>Example:<code> </em>tao_ImR -ORBInitRef + ImplRepoService=file://locator.ior remove plane</code> +</ol> + +@subsection serverresponsibilities So what does the server need to do? + +As of TAO 1.0.9, the Implementation Repository support on the server-side has +been integrated into the POA. Previously, the IR_Helper class needed to be +used explicitly. Now only the "-ORBUseImR 1" command line +argument needs to be used. + +There are a couple of restrictions on the server though. Only objects within +a persistent POA will be supported by the ImR. Also the Implementation +Repository will key its entries on POA name. What this means for the server +is that each server must have unique persistent POA names. + +@subsection defaultinitref Use of -ORBDefaultInitRef with the ImR + +As mentioned in the INS documentation (in TAO/docs/INS.html), a base IOR +can be passed to the ORB. Then when resolve_initial_reference is called, +the ORB can append the service name to the base IOR to form a full IOR. + +When used with the ImR, this can be a powerful feature. If the ImR's endpoint +is used as the base IOR, then the ImR can be used to provide many services via +the resolve_initial_reference functionality. + +For example, let's say the ImR service is running on doriath on port 5555 and +the Name Service is already registered with the ImR (in that the ImR knows how +to start the Name Service). + +Now we should be able to run some client that uses the Name Service like this: + +<code>client -ORBDefaultInitRef corbaloc:iiop:doriath:5555/</code> + +When the client calls resolve_initial_reference("NameService"), the ORB will +resolve that to "corbaloc:iiop:doriath:5555/NameService". The ImR +recognizes this IOR as a pointer to the NameService, and will then +start it up if necessary. Finally, it will forward the client to the +Name Service. + +Services used in this way have two requirements: + +- The server must be registered as the request_initial_reference name. For + example, the Name Service is registered as the "NameService", and thus also + contains a POA with the name "NameService". +- The server must also be able to handle the INS name + "corbaloc:iiop:machine:port/poa_name", where the poa_name is the + same name as above. + +@subsection activationmodes What are activation modes + +Each server can have one of three different types of activation modes: + +<ul> + <li>NORMAL is the default. The server can be started via tao_ImR, + the command line, and with client requests. + <li>MANUAL specifies that the server shouldn't be activated with a + client request but can be activated through tao_ImR or via the + command line. + <li>PER_CLIENT specifies that each request to the ImplRepo will + result in a new server process started up. Because clients + cache the forwarded reference, there is one server per client + (more or less). There are some exceptions, such as if the + original IOR is used in different threads (each thread would get + a different server). <b>Note:</b> The Implementation Repository + doesn't store any information about the started servers in this + mode, so it cannot be used to shut down the servers. So the + servers must have an alternative way of shutting down. + <li>AUTO_START specifies that a server should be activated when the + Implementation Repository is started. tao_ImR also has an + autostart command to activate all servers marked AUTO_START. +</ul> + +@subsection taoImRior Using the tao_ImR ior command + +First, some background. + +For the longest time, there was no way with TAO's Implementation Repository +to register a server and then start using the client immediately. The server +had to be started once just for the purpose of creating an IOR for the client +to use. The problem was that it was very difficult to create an IOR without +running the server. + +It would be nice to be able to generate a valid IOR without requiring the +program to be run. A valid IOR in this case requires two major things. First +it requires the endpoint of the ImR. This is relatively easy to get, since it +is encoded in the ImR's IOR. Second it also requires an object key. At the +least, this involves both the POA hierarchy and the object name. + +So if we knew the POA and object names, then we should be able to create an +IOR for the server. One possibility would be to have tao_ImR ask for both the +POA and the object, and then create the POA hierarchy to generate an IOR. +Doing the generation is this manner (letting the POA create the reference) +shields us from changes in the IOR generation schemes. Since we are using +the same code that the server would use, our IORs would be up to date. + +It ends up there is an easier way to do this. The Interoperable Naming +Service is intended to be used in situations where an IOR could be created by +hand. Using the same information as above, it is not difficult to take the +endpoint information from the ImR and attach the POA name. For example, +let's say that we are running the ImR on ringil.ece.uci.edu at port 5000. +The endpoint would be +"corbaloc:iiop:1.2@ringil.ece.uci.edu:5000". If we are +creating an IOR for the nestea server, we'd just need to attach +"/nestea_server" to the end of the endpoint. Now we have an +IOR. + +So what does this mean for the server? + +The main issue here is that the server must be changed to support the +simplified name. This can be done by using the IORTable like this: + +<CODE> + CORBA::Object_var table_object = + this->orb_->resolve_initial_references ("IORTable", + ACE_TRY_ENV); + ACE_TRY_CHECK; + + IORTable::Table_var adapter = + IORTable::Table::_narrow (table_object.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + if (CORBA::is_nil (adapter.in ())) + { + ACE_ERROR ((LM_ERROR, "Nil IORTable\n")); + } + else + { + adapter->bind (poa_name, server_str.in (), ACE_TRY_ENV); + ACE_TRY_CHECK; + } +</CODE> + +These lines, as taken from the nestea_server example, just uses the same +poa_name as registered with the ImR and associates it with the server_obj +object in the IOR table. Because the ImR will be able to handle the +simplified name (if it uses the POA name scheme) then this IOR will work. + +Just one more thing, each object that needs an IOR needs to be registered +with the IOR table. But this raises the problem of uniqueness; they all +can't have the same name. The ImR will actually only look at the name part +of the simplified IOR up to the first "/". So both +"corbaloc:iiop:1.2@ringil:5000/nestea_server/foo" and +"corbaloc:iiop:1.2@ringil:5000/nestea_server/bar" will be treated by +the ImR as objects in the "nestea_server" server. + +@subsection persistence Persistent Implementation Repository + +Tao's Implementation Repository can be made persistent by doing two things: + +<ul> +<li> +Always start up the Implementation Repository on the same port. This ensures that +the Implementation Repository will not have to re-ImR-ify the IORs of every server +registered to it each time it starts up. The way to accomplish this is to add<br> +-ORBEndpoint iiop://(hostname):(portnumber)<br> + + to the ImR_Activator's startup command line. The host +name can be obtained portably in C++ code with the lines<br> + + ACE_INET_addr ad;<br> + char *hostname = ad.get_host_name ();<br> + +or in a Perl script by adding<br> + + use Sys::Hostname;<br> + $hostname = hostname();<br> + +There are even specific port numbers, assigned to the OMG by the IANA, +which can be used for this purpose. They are 683 (for IIOP) and 684 +(for IIOP over SSL). For more information about this, see +<a href="http://www.iana.org/">http://www.iana.org/</a> +and <a href="http://www.isi.edu/in-notes/iana/assignments/port-numbers"> +http://www.isi.edu/in-notes/iana/assignments/port-numbers</a>.<br><br> +<li> +Pass the ImR a filename to use for the backing store, specified by the +command line option<br> + +-p (filename)<br> + +This option must be used the first and every subsequent time the +persistent ImR is started up. + +</ul> +*/ + +/** +@page ntservice Running as an NT service + +The ImplRepo_Service.exe can now also function as a Windows NT +Service. The -c option can be used to install and remove the service +(this requires Administrator access on the machine). + +@note When using the ImplRepo_Service as a service, it must have all +of its required ACE/TAO DLL's in the path or in the same directory. +For example, the run_test.pl copies ImplRepo_Service.exe to the +ACE_wrappers@\bin directory before using "-c install". +Alternatively, You can set the usual ACE_ROOT, TAO_ROOT, and PATH environment +variables on a system wide basis. + +The service can be then started either from the Windows NT "Services" +Admin Tool or via the "net" program on the command line: + +<CODE>net start "TAO Implementation Repository Locator"</CODE> +<CODE>net start "TAO Implementation Repository Activator"</CODE> + +The Implementation Repository supports start and stop but not pause. + +When the Activator is installed using ImR_Activator -c install, it is added +with a dependency on a locator service. If you don't wish to also install +the locator on the same machine, then you must use the -c install_no_imr +option instead. + +@subsection serviceopts Service Options + +Any options that are specified along with -c install, will be saved in +the registry under +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TAOIMRActivator\Parameters and +HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TAOIMRLocator\Parameters. +For example: +ImR_Activator -c install -d 3 -l -m -o activator.ior -x persist.xml -t 30 -orbendpoint iiop://:9988 -orbdebuglevel 1 + +The order of arguments makes no difference, but you must run +-c remove and then -c install if you want to change the parameters. + +You can also manually change these using the typical regedit utility. + +*/ + +/** +@page imrandnaming Naming Service + +@subsection lowdown The Short Answer + +Register the Naming Service with an Implementation Repository using the +POA name "NameService". So for example: + +<CODE>tao_imr add NameService -c "Naming_Service -ORBUseIMR 1"</CODE> + +And then an IOR can be created by: + +<CODE>tao_imr ior NameService</CODE> + +The above commands depend on multicast (since the commands are shorter and +easier put in documents). You might need to add "-ORBInitRef +ImplRepoService=..." for a more robust solution. + +@subsection details Various Details + +The Naming Service in TAO contains one persistant POA named "NameService". +If -ORBUseIMR 1 is passed to it, it will communicate with the ImR as any +other persistent POA does. Also, the Naming Service recognizes the INS +object key "NameService". This allows you to use the "tao_imr ior" +command to create corbaloc IORs. + +NameService was chosen because resolve_initial_references () uses that +name. And that allows us to do interesting things with ORBDefaultInitRef +(as shown in the @ref defaultinitref section). + +*/ + +/** +@page movefromoldImR Transition from IMR in TAO 1.2.2 + + +While the previous version of ImR has a single focal point (ImplRepo_Service) +for performing all the jobs including receiving various requests, +maintaining the information about all the servers registered with it +and actually activating the servers as needed, in the new IMR, we +distribute the work load between two entities, ImplRepo_Service and +ImR_Activator, to help achieve the goal of better throughput and load +balance. + +<b>.</b> The added step that you would have to now do is run the +ImR_Activator. You can just run one instance of it to get the same +behaviour as you were getting before. + +If you run the ImplRepo_Service in multicast mode, the +ImR_Activator will be able to get access to it via +multicast. Otherwise, you would have to use one of the reference +initializing methods to give the ImR_Activator access to the +ImplRepo_Service. + +<b>.</b> As I mentioned before, the previous commandline parameters +that can be passed to ImplRepoService for the repository purposes will +now be passed to the ImR_Activator since that is the one that is +dealing with the database. + +*/ diff --git a/TAO/orbsvcs/ImplRepo_Service/Server_Info.cpp b/TAO/orbsvcs/ImplRepo_Service/Server_Info.cpp new file mode 100644 index 00000000000..91f8d7fa1be --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Server_Info.cpp @@ -0,0 +1,66 @@ +// $Id$ +#include "Server_Info.h" + +Server_Info::Server_Info +( + const ACE_CString& server_name, + const ACE_CString& aname, + const ACE_CString& cmdline, + const ImplementationRepository::EnvironmentList& env, + const ACE_CString& working_dir, + ImplementationRepository::ActivationMode amode, + int limit, + const ACE_CString& partial_ior, + const ACE_CString& server_ior, + ImplementationRepository::ServerObject_ptr svrobj + ) + : name (server_name) + , activator (aname) + , cmdline( cmdline) + , env_vars (env) + , dir (working_dir) + , activation_mode (amode) + , start_limit (limit) + , partial_ior (partial_ior) + , ior (server_ior) + , server(ImplementationRepository::ServerObject::_duplicate (svrobj)) + , start_count (0) + , waiting_clients (0) + , starting (false) +{ +} + +ImplementationRepository::ServerInformation* +Server_Info::createImRServerInfo (ACE_ENV_SINGLE_ARG_DECL) +{ + ImplementationRepository::ServerInformation* info; + ACE_NEW_THROW_EX (info, ImplementationRepository::ServerInformation, CORBA::NO_MEMORY ()); + + info->server = name.c_str (); + info->startup.command_line = cmdline.c_str (); + info->startup.environment = env_vars; + info->startup.working_directory = dir.c_str (); + info->startup.activation = activation_mode; + info->startup.activator = activator.c_str (); + if (start_count >= start_limit) + { + info->startup.start_limit = -start_limit; + } + else + { + info->startup.start_limit = start_limit; + } + info->partial_ior = partial_ior.c_str(); + + return info; +} + +void +Server_Info::reset (void) +{ + ior = ""; + partial_ior = ""; + last_ping = ACE_Time_Value::zero; + server = ImplementationRepository::ServerObject::_nil (); + // start_count = 0; Note : We can't do this, because it would be reset during startup. +} diff --git a/TAO/orbsvcs/ImplRepo_Service/Server_Info.h b/TAO/orbsvcs/ImplRepo_Service/Server_Info.h new file mode 100644 index 00000000000..e6c3a910f3b --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/Server_Info.h @@ -0,0 +1,77 @@ +//============================================================================= +/** + * @file Server_Info.h + * + * $Id$ + * + * This class implements the Server_Info for the Implementation Repository. + * + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + * @author Priyanka Gontla <gontla_p@ociweb.com> + */ +#ifndef SERVER_INFO_H +#define SERVER_INFO_H + +#include "ace/Bound_Ptr.h" + +#include "tao/ImR_Client/ImplRepoC.h" + +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +/** +* @brief Information about IMR registered servers. +*/ +struct Server_Info +{ + Server_Info (const ACE_CString& server_name, + const ACE_CString& aname, + const ACE_CString& cmdline, + const ImplementationRepository::EnvironmentList& env, + const ACE_CString& working_dir, + ImplementationRepository::ActivationMode amode, + int start_limit, + const ACE_CString& partial_ior = ACE_CString(""), + const ACE_CString& server_ior = ACE_CString(""), + ImplementationRepository::ServerObject_ptr svrobj = ImplementationRepository::ServerObject::_nil() + ); + + /// Convert to the corba type + ImplementationRepository::ServerInformation* createImRServerInfo(ACE_ENV_SINGLE_ARG_DECL); + + void reset(); + + /// The name of the server. + ACE_CString name; + /// The name of the activator in which this server runs + ACE_CString activator; + /// The command line startup command (program and arguments). + ACE_CString cmdline; + /// Environment Variables. + ImplementationRepository::EnvironmentList env_vars; + /// The working directory. + ACE_CString dir; + /// The type of activation this supports. + ImplementationRepository::ActivationMode activation_mode; + /// Limit of retries to start the server + int start_limit; + /// Current endpoint used by the server. + ACE_CString partial_ior; + /// IOR of the server object in the server. + ACE_CString ior; + /// The timestamp of the last time we verified the server is alive + ACE_Time_Value last_ping; + /// The cached server object + ImplementationRepository::ServerObject_var server; + int start_count; + int waiting_clients; + bool starting; +}; + +typedef ACE_Strong_Bound_Ptr<Server_Info, ACE_Null_Mutex> Server_Info_Ptr; + +#endif /* SERVER_INFO_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/activator_export.h b/TAO/orbsvcs/ImplRepo_Service/activator_export.h new file mode 100644 index 00000000000..fcd22f8ccde --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/activator_export.h @@ -0,0 +1,54 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s Activator +// ------------------------------ +#ifndef ACTIVATOR_EXPORT_H +#define ACTIVATOR_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (ACTIVATOR_HAS_DLL) +# define ACTIVATOR_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && ACTIVATOR_HAS_DLL */ + +#if !defined (ACTIVATOR_HAS_DLL) +# define ACTIVATOR_HAS_DLL 1 +#endif /* ! ACTIVATOR_HAS_DLL */ + +#if defined (ACTIVATOR_HAS_DLL) && (ACTIVATOR_HAS_DLL == 1) +# if defined (ACTIVATOR_BUILD_DLL) +# define Activator_Export ACE_Proper_Export_Flag +# define ACTIVATOR_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define ACTIVATOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* ACTIVATOR_BUILD_DLL */ +# define Activator_Export ACE_Proper_Import_Flag +# define ACTIVATOR_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define ACTIVATOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ACTIVATOR_BUILD_DLL */ +#else /* ACTIVATOR_HAS_DLL == 1 */ +# define Activator_Export +# define ACTIVATOR_SINGLETON_DECLARATION(T) +# define ACTIVATOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* ACTIVATOR_HAS_DLL == 1 */ + +// Set ACTIVATOR_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (ACTIVATOR_NTRACE) +# if (ACE_NTRACE == 1) +# define ACTIVATOR_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define ACTIVATOR_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !ACTIVATOR_NTRACE */ + +#if (ACTIVATOR_NTRACE == 1) +# define ACTIVATOR_TRACE(X) +#else /* (ACTIVATOR_NTRACE == 1) */ +# define ACTIVATOR_TRACE(X) ACE_TRACE_IMPL(X) +#endif /* (ACTIVATOR_NTRACE == 1) */ + +#endif /* ACTIVATOR_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/orbsvcs/ImplRepo_Service/activator_idl_export.h b/TAO/orbsvcs/ImplRepo_Service/activator_idl_export.h new file mode 100644 index 00000000000..5ae5cbc5e22 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/activator_idl_export.h @@ -0,0 +1,54 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s Activator +// ------------------------------ +#ifndef ACTIVATOR_IDL_EXPORT_H +#define ACTIVATOR_IDL_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (ACTIVATOR_IDL_HAS_DLL) +# define ACTIVATOR_IDL_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && ACTIVATOR_IDL_HAS_DLL */ + +#if !defined (ACTIVATOR_IDL_HAS_DLL) +# define ACTIVATOR_IDL_HAS_DLL 1 +#endif /* ! ACTIVATOR_IDL_HAS_DLL */ + +#if defined (ACTIVATOR_IDL_HAS_DLL) && (ACTIVATOR_IDL_HAS_DLL == 1) +# if defined (ACTIVATOR_IDL_BUILD_DLL) +# define ActivatorIDL_Export ACE_Proper_Export_Flag +# define ACTIVATOR_IDL_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define ACTIVATOR_IDL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* ACTIVATOR_IDL_BUILD_DLL */ +# define ActivatorIDL_Export ACE_Proper_Import_Flag +# define ACTIVATOR_IDL_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define ACTIVATOR_IDL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* ACTIVATOR_IDL_BUILD_DLL */ +#else /* ACTIVATOR_IDL_HAS_DLL == 1 */ +# define ActivatorIDL_Export +# define ACTIVATOR_IDL_SINGLETON_DECLARATION(T) +# define ACTIVATOR_IDL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* ACTIVATOR_IDL_HAS_DLL == 1 */ + +// Set ACTIVATOR_IDL_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (ACTIVATOR_IDL_NTRACE) +# if (ACE_NTRACE == 1) +# define ACTIVATOR_IDL_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define ACTIVATOR_IDL_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !ACTIVATOR_IDL_NTRACE */ + +#if (ACTIVATOR_IDL_NTRACE == 1) +# define ACTIVATOR_IDL_TRACE(X) +#else /* (ACTIVATOR_IDL_NTRACE == 1) */ +# define ACTIVATOR_IDL_TRACE(X) ACE_TRACE_IMPL(X) +#endif /* (ACTIVATOR_IDL_NTRACE == 1) */ + +#endif /* ACTIVATOR_IDL_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/orbsvcs/ImplRepo_Service/locator_export.h b/TAO/orbsvcs/ImplRepo_Service/locator_export.h new file mode 100644 index 00000000000..8a3584386f1 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/locator_export.h @@ -0,0 +1,54 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s Locator +// ------------------------------ +#ifndef LOCATOR_EXPORT_H +#define LOCATOR_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (LOCATOR_HAS_DLL) +# define LOCATOR_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && LOCATOR_HAS_DLL */ + +#if !defined (LOCATOR_HAS_DLL) +# define LOCATOR_HAS_DLL 1 +#endif /* ! LOCATOR_HAS_DLL */ + +#if defined (LOCATOR_HAS_DLL) && (LOCATOR_HAS_DLL == 1) +# if defined (LOCATOR_BUILD_DLL) +# define Locator_Export ACE_Proper_Export_Flag +# define LOCATOR_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define LOCATOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* LOCATOR_BUILD_DLL */ +# define Locator_Export ACE_Proper_Import_Flag +# define LOCATOR_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define LOCATOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* LOCATOR_BUILD_DLL */ +#else /* LOCATOR_HAS_DLL == 1 */ +# define Locator_Export +# define LOCATOR_SINGLETON_DECLARATION(T) +# define LOCATOR_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* LOCATOR_HAS_DLL == 1 */ + +// Set LOCATOR_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (LOCATOR_NTRACE) +# if (ACE_NTRACE == 1) +# define LOCATOR_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define LOCATOR_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !LOCATOR_NTRACE */ + +#if (LOCATOR_NTRACE == 1) +# define LOCATOR_TRACE(X) +#else /* (LOCATOR_NTRACE == 1) */ +# define LOCATOR_TRACE(X) ACE_TRACE_IMPL(X) +#endif /* (LOCATOR_NTRACE == 1) */ + +#endif /* LOCATOR_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/orbsvcs/ImplRepo_Service/locator_idl_export.h b/TAO/orbsvcs/ImplRepo_Service/locator_idl_export.h new file mode 100644 index 00000000000..3016cfc767b --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/locator_idl_export.h @@ -0,0 +1,54 @@ + +// -*- C++ -*- +// $Id$ +// Definition for Win32 Export directives. +// This file is generated automatically by generate_export_file.pl -s Locator +// ------------------------------ +#ifndef LOCATOR_IDL_EXPORT_H +#define LOCATOR_IDL_EXPORT_H + +#include "ace/config-all.h" + +#if defined (ACE_AS_STATIC_LIBS) && !defined (LOCATOR_IDL_HAS_DLL) +# define LOCATOR_IDL_HAS_DLL 0 +#endif /* ACE_AS_STATIC_LIBS && LOCATOR_IDL_HAS_DLL */ + +#if !defined (LOCATOR_IDL_HAS_DLL) +# define LOCATOR_IDL_HAS_DLL 1 +#endif /* ! LOCATOR_IDL_HAS_DLL */ + +#if defined (LOCATOR_IDL_HAS_DLL) && (LOCATOR_IDL_HAS_DLL == 1) +# if defined (LOCATOR_IDL_BUILD_DLL) +# define LocatorIDL_Export ACE_Proper_Export_Flag +# define LOCATOR_IDL_SINGLETON_DECLARATION(T) ACE_EXPORT_SINGLETON_DECLARATION (T) +# define LOCATOR_IDL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_EXPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# else /* LOCATOR_IDL_BUILD_DLL */ +# define LocatorIDL_Export ACE_Proper_Import_Flag +# define LOCATOR_IDL_SINGLETON_DECLARATION(T) ACE_IMPORT_SINGLETON_DECLARATION (T) +# define LOCATOR_IDL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) ACE_IMPORT_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +# endif /* LOCATOR_IDL_BUILD_DLL */ +#else /* LOCATOR_IDL_HAS_DLL == 1 */ +# define LocatorIDL_Export +# define LOCATOR_IDL_SINGLETON_DECLARATION(T) +# define LOCATOR_IDL_SINGLETON_DECLARE(SINGLETON_TYPE, CLASS, LOCK) +#endif /* LOCATOR_IDL_HAS_DLL == 1 */ + +// Set LOCATOR_IDL_NTRACE = 0 to turn on library specific tracing even if +// tracing is turned off for ACE. +#if !defined (LOCATOR_IDL_NTRACE) +# if (ACE_NTRACE == 1) +# define LOCATOR_IDL_NTRACE 1 +# else /* (ACE_NTRACE == 1) */ +# define LOCATOR_IDL_NTRACE 0 +# endif /* (ACE_NTRACE == 1) */ +#endif /* !LOCATOR_IDL_NTRACE */ + +#if (LOCATOR_IDL_NTRACE == 1) +# define LOCATOR_IDL_TRACE(X) +#else /* (LOCATOR_IDL_NTRACE == 1) */ +# define LOCATOR_IDL_TRACE(X) ACE_TRACE_IMPL(X) +#endif /* (LOCATOR_IDL_NTRACE == 1) */ + +#endif /* LOCATOR_IDL_EXPORT_H */ + +// End of auto generated file. diff --git a/TAO/orbsvcs/ImplRepo_Service/repository.xml b/TAO/orbsvcs/ImplRepo_Service/repository.xml new file mode 100644 index 00000000000..d6b5ab4638a --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/repository.xml @@ -0,0 +1,8 @@ +<?xml version="1.0"?> +<ImplementationRepository> + <Servers name="test" activator="MYHOST" command_line="mysrv" working_dir="mydir" activation_mode="NORMAL" start_limit="1" partial_ior="" ior=""> + </Servers> + <Servers name="test2" activator="MYHOST" command_line="" working_dir="" activation_mode="NORMAL" start_limit="1" partial_ior="" ior=""> + </Servers> + <Activators name="MYHOST" token="1610927480" ior="IOR:010000002b00000049444c3a496d706c656d656e746174696f6e5265706f7369746f72792f416374697661746f723a312e300000010000000000000090000000010102cd150000004a555354414c49454e2e6f63697765622e636f6d00cd1f083900000014010f004e555000000017000000000100000000496d525f416374697661746f7200000000000100000054414f496d52416374697661746f7200000002000000000000000800000001cdcdcd004f4154010000001400000001cdcdcd01000100000000000901010000000000"/> +</ImplementationRepository> diff --git a/TAO/orbsvcs/ImplRepo_Service/tao_imr.cpp b/TAO/orbsvcs/ImplRepo_Service/tao_imr.cpp new file mode 100644 index 00000000000..45b72a2790a --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/tao_imr.cpp @@ -0,0 +1,15 @@ +/* -*- C++ -*- */ +// $Id$ + +#include "tao_imr_i.h" + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + TAO_IMR_i tao_imr_i; + + if (tao_imr_i.init (argc, argv) != 0) + return 1; + + return tao_imr_i.run (); +} diff --git a/TAO/orbsvcs/ImplRepo_Service/tao_imr_i.cpp b/TAO/orbsvcs/ImplRepo_Service/tao_imr_i.cpp new file mode 100644 index 00000000000..9febb1ae406 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/tao_imr_i.cpp @@ -0,0 +1,1111 @@ +// $Id$ + +#include "tao_imr_i.h" + +#include "tao/PortableServer/PortableServer.h" +#include "tao/PortableServer/ForwardRequestC.h" + +#include "tao/Stub.h" +#include "tao/Profile.h" + +#include "ace/Get_Opt.h" +#include "ace/Read_Buffer.h" +#include "ace/OS_NS_strings.h" +#include "ace/OS.h" + +TAO_IMR_i::TAO_IMR_i (void) +: imr_ (ImplementationRepository::Administration::_nil ()) +{ + // Nothing +} + +TAO_IMR_i::~TAO_IMR_i (void) +{ +} + +int +TAO_IMR_i::run () +{ + if (this->op_.get () == 0) + { + ACE_ERROR ((LM_ERROR, "Unknown operation")); + return TAO_IMR_Op::UNKNOWN; + } + + return this->op_->run (); +} + +int +TAO_IMR_i::init (int argc, char **argv) +{ + this->argc_ = argc; + this->argv_ = argv; + + const char *exception_message = "Null Message"; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // Retrieve the ORB. + this->orb_ = CORBA::ORB_init (this->argc_, this->argv_, "tao_imr_i" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Parse command line and verify parameters. + if (this->parse_args () == -1) + return -1; + + // Get the ImplRepo object + CORBA::Object_var obj = + orb_->resolve_initial_references ("ImplRepoService" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (obj.in ())) + { + ACE_ERROR ((LM_ERROR, "Unable to resolve the ImR.\n")); + return -1; + } + + exception_message = "While narrowing ImR"; + + this->imr_ = + ImplementationRepository::Administration::_narrow (obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (CORBA::is_nil (imr_.in ())) + { + ACE_ERROR ((LM_ERROR, "Unable to narrow the ImR.\n")); + return -1; + } + + this->op_->set_imr (this->imr_.in ()); + } + ACE_CATCHANY + { + ACE_ERROR ((LM_ERROR, "TAO_IMR_i::init - %s\n", exception_message)); + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Exception"); + return -1; + } + ACE_ENDTRY; + + return 0; +} + + +// Go through and figure out which operation we should do. + +int +TAO_IMR_i::parse_args (void) +{ + // Make sure one command was given + if (this->argc_ < 2) + { + ACE_ERROR((LM_ERROR, "Error: No operation specified.\n")); + this->print_usage (); + return -1; + } + + this->op_.reset (TAO_IMR_Op::make_op (this->argv_[1])); + + // Check for unrecognized operation + + if (this->op_.get () == 0) + { + ACE_ERROR((LM_ERROR, "Error: Unknown operation '%s'.\n", this->argv_[1])); + this->print_usage (); + return -1; + } + + // Adjust argc and argv so only the command specific args are passed + return this->op_->parse (this->argc_ - 1, this->argv_ + 1); +} + + +// Print out information about all operations. + +void +TAO_IMR_i::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Usage: tao_imr [options] command [command-arguments]\n" + " where [options] are ORB options\n" + " where command is one of the following:\n" + " start Start a server through the ImR\n" + " add Add an entry to the ImR\n" + " autostart Activates all AUTO_START servers\n" + " ior Creates a simplified IOR\n" + " list List the entries in the ImR\n" + " remove Remove an entry from the ImR\n" + " shutdown Shut down a server through the ImR\n" + " shutdown-repo Shut down the ImR\n" + " update Update an entry in the ImR\n" + " where [command-arguments] depend on the command\n")); +} + + +// Factory for operations + +TAO_IMR_Op * +TAO_IMR_Op::make_op (const ACE_TCHAR *op_name) +{ + if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("activate")) == 0) + { + ACE_ERROR((LM_ERROR, "Warning: The activate option has been renamed to start.\n")); + return new TAO_IMR_Op_Activate (); + } + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("start")) == 0) + return new TAO_IMR_Op_Activate (); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("add")) == 0) + return new TAO_IMR_Op_Register (true); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("autostart")) == 0) + return new TAO_IMR_Op_Autostart(); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("ior")) == 0) + return new TAO_IMR_Op_IOR(); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("list")) == 0) + return new TAO_IMR_Op_List (); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("remove")) == 0) + return new TAO_IMR_Op_Remove (); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("shutdown")) == 0) + return new TAO_IMR_Op_Shutdown (); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("shutdown-repo")) == 0) + return new TAO_IMR_Op_ShutdownRepo (); + else if (ACE_OS::strcasecmp (op_name, ACE_TEXT ("update")) == 0) + return new TAO_IMR_Op_Register (false); + + return 0; +} + + +TAO_IMR_Op::~TAO_IMR_Op () +{ + // Nothing +} + +void +TAO_IMR_Op::set_imr (ImplementationRepository::Administration_ptr imr) +{ + this->imr_ = imr; +} + +void +TAO_IMR_Op::display_server_information (const ImplementationRepository::ServerInformation &info) +{ + // Figure out what the activation string is. + const char *act = "UNKNOWN STARTUP"; + if (info.startup.activation == ImplementationRepository::NORMAL) + act = "NORMAL"; + else if (info.startup.activation == ImplementationRepository::MANUAL) + act = "MANUAL"; + else if (info.startup.activation == ImplementationRepository::PER_CLIENT) + act = "PER_CLIENT"; + else if (info.startup.activation == ImplementationRepository::AUTO_START) + act = "AUTO_START"; + + // Print out information + ACE_DEBUG ((LM_DEBUG, "Server <%s>\n", info.server.in ())); + + const char * locked_out = ""; + + int limit = info.startup.start_limit; + if (info.startup.start_limit < 0) + { + limit = -limit; + locked_out = " Locked Out\n"; + } + + ACE_DEBUG ((LM_DEBUG, + " Activator: %s\n" + " Command Line: %s\n" + " Working Directory: %s\n" + " Activation Mode: %s\n" + " Number of retries: %d\n" + "%s", + info.startup.activator.in (), + info.startup.command_line.in (), + info.startup.working_directory.in (), + act, + limit - 1, + locked_out)); + for (CORBA::ULong i = 0; i < info.startup.environment.length (); ++i) + ACE_DEBUG ((LM_DEBUG, "Environment Variable: %s=%s \n", + info.startup.environment[i].name.in (), + info.startup.environment[i].value.in ())); + + if (info.startup.activation == ImplementationRepository::PER_CLIENT) + ACE_DEBUG ((LM_DEBUG, + " No running info available for PER_CLIENT mode\n")); + else if (ACE_OS::strlen (info.partial_ior.in ()) > 0) + ACE_DEBUG ((LM_DEBUG, + " Running at endpoint: %s\n", + info.partial_ior.in ())); + else // I am assuming that a blank partial_ior means currently not running. + ACE_DEBUG ((LM_DEBUG, + " Not currently running\n")); + + ACE_DEBUG ((LM_DEBUG, "\n")); +} + +TAO_IMR_Op_List::TAO_IMR_Op_List (void) +: verbose_server_information_ (0) +{ + // Nothing +} + +TAO_IMR_Op_Register::TAO_IMR_Op_Register (bool is_add) +: is_add_ (is_add) +, set_command_line_ (false) +, set_environment_vars_(false) +, set_working_dir_ (false) +, set_activation_ (false) +, activation_(ImplementationRepository::NORMAL) +, set_retry_count_(false) +, retry_count_ (0) +, set_activator_ (false) +{ + // Nothing +} + +void +TAO_IMR_Op_Activate::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Starts a server using its registered Activator.\n" + "\n" + "Usage: tao_imr [options] start <name>\n" + " where [options] are ORB options\n" + " where <name> is the name of a registered POA.\n" + " -h Displays this\n")); +} + +int +TAO_IMR_Op_Activate::parse (int argc, ACE_TCHAR **argv) +{ + // Check for enough arguments (we need at least one for the server name) + if (argc < 2) + { + this->print_usage (); + return -1; + } + + // Skip both the program name and the "activate" command + ACE_Get_Opt get_opts (argc, argv, "h"); + + this->server_name_ = argv[1]; + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'h': + this->print_usage (); + return -1; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + return 0; +} + +void +TAO_IMR_Op_Autostart::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Usage: tao_imr [options] autostart\n" + " where [options] are ORB options\n" + " -h Displays this\n")); +} + +int +TAO_IMR_Op_Autostart::parse (int argc, ACE_TCHAR **argv) +{ + // Skip the "autostart" command + ACE_Get_Opt get_opts (argc, argv, "h"); + + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'h': // display help + this->print_usage (); + return -1; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + return 0; +} + +void +TAO_IMR_Op_IOR::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Creates an IOR for a server that is registered with the IMR and uses\n" + "the InterOperable Naming Service. Please see the documentation for\n" + "more information on which server configurations work with this command.\n" + "\n" + "Usage: tao_imr [options] ior <object_key> [command-arguments]\n" + " where [options] are ORB options\n" + " where <object_key> matches the simple key bound in the server IORTable.\n" + " where [command-arguments] can be\n" + " -f filename filename to output the IOR to\n" + " -h Displays this\n")); +} + +int +TAO_IMR_Op_IOR::parse (int argc, ACE_TCHAR **argv) +{ + // Check for enough arguments (we need at least one for the server name) + if (argc < 2) + { + this->print_usage (); + return -1; + } + + // Skip both the program name and the "ior" command + ACE_Get_Opt get_opts (argc, argv, "hf:"); + + this->server_name_ = argv[1]; + if (this->server_name_.length() == 0 || this->server_name_[0] == '-') + { + ACE_ERROR((LM_ERROR, "ERROR : name is required.\n")); + this->print_usage (); + return -1; + } + + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'f': // File name + this->filename_ = get_opts.opt_arg (); + break; + case 'h': // display help + this->print_usage (); + return -1; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + return 0; +} + +void +TAO_IMR_Op_List::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Lists all or one of the servers in the Implementation Repository\n" + "\n" + "Usage: tao_imr [options] list [name] [command-arguments]\n" + " where [options] are ORB options\n" + " where [name] is the optional server name to search for\n" + " where [command-arguments] can be\n" + " -v Verbose: Displays more info for each server when\n" + " displaying more than one server\n" + " -h Displays this\n")); +} + +int +TAO_IMR_Op_List::parse (int argc, ACE_TCHAR **argv) +{ + int server_flag = 0; + + if (argc > 1 && argv[1][0] != '-') + { + this->server_name_ = argv[1]; + server_flag = 2; + } + + // Skip both the program name and the "list" command + ACE_Get_Opt get_opts (argc, argv, "vh", server_flag); + + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'v': // verbose server display + this->verbose_server_information_ = 1; + break; + case 'h': // display help + this->print_usage (); + return -1; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + return 0; +} + +void +TAO_IMR_Op_Remove::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Removes a server entry\n" + "\n" + "Usage: tao_imr [options] remove <name>\n" + " where [options] are ORB options\n" + " where <name> is the POA name used by the server object\n" + " -h Displays this\n")); +} + +int +TAO_IMR_Op_Remove::parse (int argc, ACE_TCHAR **argv) +{ + // Check for enough arguments (we need at least one for the server name) + if (argc < 2) + { + this->print_usage (); + return -1; + } + + // Skip both the program name and the "remove" command + ACE_Get_Opt get_opts (argc, argv, "h"); + + this->server_name_ = argv[1]; + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'h': + this->print_usage (); + return -1; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + return 0; +} + +void +TAO_IMR_Op_Shutdown::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Shuts down a server\n" + "\n" + "Usage: tao_imr [options] shutdown <name>\n" + " where [options] are ORB options\n" + " where <name> is the name of the server object\n" + " -h Displays this\n")); +} + +int +TAO_IMR_Op_Shutdown::parse (int argc, ACE_TCHAR **argv) +{ + // Check for enough arguments (we need at least one for the server name) + if (argc < 2) + { + this->print_usage (); + return -1; + } + + // Skip both the program name and the "shutdown" command + ACE_Get_Opt get_opts (argc, argv, "h"); + + this->server_name_ = argv[1]; + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'h': + this->print_usage (); + return -1; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + return 0; +} + +TAO_IMR_Op_ShutdownRepo::TAO_IMR_Op_ShutdownRepo() +: activators_(false) +{ +} + +void +TAO_IMR_Op_ShutdownRepo::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, "Shuts down the ImR\n" + "\n" + "Usage: tao_imr [options] shutdown-repo [-a]\n" + " where [options] are ORB options\n" + " Specify -a to also shutdown any registered ImR Activators.\n" + " -h Displays this\n")); +} + +int +TAO_IMR_Op_ShutdownRepo::parse (int argc, ACE_TCHAR **argv) +{ + // Check for enough arguments (we need at least one for the server name) + if (argc < 1) + { + this->print_usage (); + return -1; + } + + // Skip both the program name and the "shutdown-repo" command + ACE_Get_Opt get_opts (argc, argv, "ha"); + + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'h': + this->print_usage (); + return -1; + case 'a': + activators_ = true; + break; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + + return 0; +} + +void +TAO_IMR_Op_Register::addenv (ACE_TCHAR *opt) +{ + CORBA::ULong length = this->environment_vars_.length (); + // Increase the length of the sequence + this->environment_vars_.length (length + 1); + ACE_CString tokens (opt); + int index = tokens.find ("="); + // Insert at position length since that is our new element + this->environment_vars_ [length].name = + CORBA::string_dup (tokens.substr (0, index).c_str ()); + this->environment_vars_ [length].value = + CORBA::string_dup (tokens.substr (index + 1).c_str ()); +} + +void +TAO_IMR_Op_Register::print_usage (void) +{ + ACE_ERROR ((LM_ERROR, + "Adds/Updates a server entry\n" + "\n" + "Usage: tao_imr [options] <add|update> <name> [command-arguments]\n" + " where [options] are ORB options\n" + " where <name> is the POA name used by the server object\n" + " where [command-arguments] can be\n" + " -h Displays this\n" + " -l Activator name.\n" + " -c command Startup command\n" + " -w dir Working directory\n" + " -e name=value Set environment variables\n" + " -a mode Set activate mode (NORMAL|MANUAL|PER_CLIENT|AUTO_START)\n" + " -r count Set the startup/ping retry count to count\n")); +} + +int +TAO_IMR_Op_Register::parse (int argc, ACE_TCHAR **argv) +{ + // Check for enough arguments (we need at least one for the server name) + if (argc < 2) + { + ACE_ERROR((LM_ERROR, "Error: Must supply at least a server name.\n")); + this->print_usage (); + return -1; + } + + // Skip both the program name and the "update" command + ACE_Get_Opt get_opts (argc, argv, "hc:w:a:e:r:R:l:"); + + this->server_name_ = argv[1]; + int c; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'c': // Command line arguments + this->set_command_line_ = true; + this->command_line_ = get_opts.opt_arg (); + break; + case 'e': // set environment variables + this->set_environment_vars_ = true; + this->addenv( get_opts.opt_arg () ); + break; + case 'w': // Working Directory + this->set_working_dir_ = true; + this->working_dir_ = get_opts.opt_arg (); + break; + case 'a': // Activation Mode + this->set_activation_ = true; + if (ACE_OS::strcasecmp (get_opts.opt_arg (), "NORMAL") == 0) + this->activation_ = ImplementationRepository::NORMAL; + else if (ACE_OS::strcasecmp (get_opts.opt_arg (), "MANUAL") == 0) + this->activation_ = ImplementationRepository::MANUAL; + else if (ACE_OS::strcasecmp (get_opts.opt_arg (), "PER_CLIENT") == 0) + this->activation_ = ImplementationRepository::PER_CLIENT; + else if (ACE_OS::strcasecmp (get_opts.opt_arg (), "AUTO_START") == 0) + this->activation_ = ImplementationRepository::AUTO_START; + else + ACE_ERROR_RETURN ((LM_ERROR, + "Unknown Activation Mode <%s>.\n", + get_opts.opt_arg ()), + -1); + break; + case 'r': + case 'R': // startup/ping Retry Count + { + this->set_retry_count_ = true; + int rc = ACE_OS::atoi(get_opts.optarg); + if (rc > 0) + this->retry_count_ = rc; + } + break; + case 'l': /// hostname of the activator + this->activator_ = get_opts.optarg; + this->set_activator_ = true; + break; + case 'h': // display help + this->print_usage (); + return -1; + default: + ACE_ERROR((LM_ERROR, "ERROR : Unknown option '%c'\n", (char) c)); + this->print_usage (); + return -1; + } + } + return 0; +} + + +// ============================================================================ +// = Run methods + + +int +TAO_IMR_Op_Activate::run (void) +{ + ACE_ASSERT(! CORBA::is_nil(imr_)); + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->imr_->activate_server (this->server_name_.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + ACE_DEBUG ((LM_DEBUG, + "Successfully Activated server <%s>\n", + this->server_name_.c_str ())); + } + ACE_CATCH (ImplementationRepository::CannotActivate, ex) + { + ACE_ERROR ((LM_ERROR, "Cannot activate server <%s>, reason: <%s>\n", + this->server_name_.c_str (), + ex.reason.in ())); + return TAO_IMR_Op::CANNOT_ACTIVATE; + } + ACE_CATCH (ImplementationRepository::NotFound, ex) + { + ACE_ERROR ((LM_ERROR, "Could not find server <%s>.\n", this->server_name_.c_str ())); + return TAO_IMR_Op::NOT_FOUND; + } + ACE_CATCH (PortableServer::ForwardRequest, ex) + { + ACE_RE_THROW; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Activating Server"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +int +TAO_IMR_Op_Autostart::run (void) +{ + ACE_ASSERT(! CORBA::is_nil (imr_)); + + ImplementationRepository::ServerInformationList_var server_list; + ImplementationRepository::ServerInformationIterator_var server_iter; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->imr_->list (0, + server_list, + server_iter + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_ASSERT(CORBA::is_nil (server_iter.in ())); + + CORBA::ULong len = server_list->length (); + for (CORBA::ULong i = 0; i < len; ++i) + { + ACE_TRY_EX (inside) + { + this->imr_->activate_server (server_list[i].server.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK_EX (inside); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, server_list[i].server.in ()); + // Ignore exception + } + ACE_ENDTRY; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "autostart"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +int +TAO_IMR_Op_IOR::run (void) +{ + ACE_ASSERT (! CORBA::is_nil(imr_)); + + // Create a corbaloc string + // Todo : Most of this logic duplicates that in the POA.cpp + ACE_TRY_NEW_ENV + { + if (CORBA::is_nil (this->imr_) + || !this->imr_->_stubobj () + || !this->imr_->_stubobj ()->profile_in_use ()) + { + ACE_ERROR_RETURN (( + LM_ERROR, + ACE_TEXT ("Invalid ImR IOR.\n") + ), -1); + } + + CORBA::String_var imr_str = + this->imr_->_stubobj ()-> + profile_in_use ()->to_string (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Search for "corbaloc:" alone, without the protocol. This code + // should be protocol neutral. + const char corbaloc[] = "corbaloc:"; + char *pos = ACE_OS::strstr (imr_str.inout (), corbaloc); + + if (pos == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, "Could not parse IMR IOR.\n"), -1); + } + else + { + pos = ACE_OS::strchr (pos + sizeof (corbaloc), ':'); + pos = ACE_OS::strchr (pos + 1, + this->imr_->_stubobj ()->profile_in_use ()->object_key_delimiter ()); + + if (pos) + { + *(pos + 1) = 0; // Crop the string + } + else + { + ACE_ERROR_RETURN ((LM_ERROR, "Could not parse IMR IOR.\n"), -1); + } + } + ACE_CString ior (imr_str.in ()); + + // Add the key + ior += this->server_name_; + + ACE_DEBUG ((LM_DEBUG, "%s\n", ior.c_str ())); + + if (this->filename_.length () > 0) + { + FILE *file = ACE_OS::fopen (this->filename_.c_str (), "w"); + + if (file == 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Error: Unable to open %s for writing: %p\n", + this->filename_.c_str ()), + -1); + } + + ACE_OS::fprintf (file, "%s", ior.c_str ()); + ACE_OS::fclose (file); + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "IOR"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +int +TAO_IMR_Op_List::run (void) +{ + ACE_ASSERT (! CORBA::is_nil(imr_)); + + ImplementationRepository::ServerInformationList_var server_list; + ImplementationRepository::ServerInformationIterator_var server_iter; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // If there is a server name, list only that server. Otherwise, look + // at all of them. + if (this->server_name_.length () == 0) + { + this->imr_->list (0, + server_list.out(), + server_iter.out() + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (server_list->length() == 0) + { + ACE_DEBUG((LM_DEBUG, "No servers found.\n")); + return TAO_IMR_Op::NORMAL; + } + + for (CORBA::ULong i = 0; i < server_list->length (); i++) + this->display_server_information (server_list[i]); + + ACE_ASSERT (CORBA::is_nil (server_iter.in ())); + } + else + { + ImplementationRepository::ServerInformation_var si; + + this->imr_->find (this->server_name_.c_str (), si ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + this->verbose_server_information_ = 1; + + this->display_server_information (si.in ()); + } + } + ACE_CATCH (ImplementationRepository::NotFound, ex) + { + ACE_ERROR ((LM_ERROR, "Could not find server <%s>.\n", this->server_name_.c_str ())); + return TAO_IMR_Op::NOT_FOUND; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "List"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +int +TAO_IMR_Op_Remove::run (void) +{ + ACE_ASSERT (! CORBA::is_nil(imr_)); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->imr_->remove_server (this->server_name_.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "Successfully removed server <%s>\n", + this->server_name_.c_str ())); + } + ACE_CATCH (ImplementationRepository::NotFound, ex) + { + ACE_ERROR ((LM_ERROR, "Could not find server <%s>.\n", + this->server_name_.c_str ())); + return TAO_IMR_Op::NOT_FOUND; + } + ACE_CATCH (CORBA::NO_PERMISSION, ex) + { + ACE_ERROR ((LM_ERROR, "No Permission: ImplRepo is in Locked mode\n")); + return TAO_IMR_Op::NO_PERMISSION; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Removing Server"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +int +TAO_IMR_Op_Shutdown::run (void) +{ + ACE_ASSERT (! CORBA::is_nil(imr_)); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->imr_->shutdown_server (this->server_name_.c_str () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "Successfully shut down server <%s>\n", + this->server_name_.c_str ())); + } + ACE_CATCH (ImplementationRepository::NotFound, ex) + { + ACE_ERROR ((LM_ERROR, "Server <%s> already shut down.\n", this->server_name_.c_str ())); + return TAO_IMR_Op::NOT_FOUND; + } + ACE_CATCH(CORBA::TIMEOUT, ex) + { + ACE_DEBUG ((LM_DEBUG, "Timeout waiting for <%s> to shutdown.\n", + this->server_name_.c_str ())); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Shutting Down Server"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +int +TAO_IMR_Op_ShutdownRepo::run (void) +{ + ACE_ASSERT(! CORBA::is_nil(imr_)); + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + bool servers = false; // not implemented yet, if ever + this->imr_->shutdown (activators_, servers ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "ImR shutdown initiated.\n")); + } + ACE_CATCH(CORBA::TIMEOUT, ex) + { + ACE_DEBUG ((LM_DEBUG, "Timeout waiting for ImR shutdown.\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Shutting Down ImR"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +int +TAO_IMR_Op_Register::run (void) +{ + ACE_ASSERT (! CORBA::is_nil(imr_)); + + ImplementationRepository::ServerInformation_var server_information; + ImplementationRepository::StartupOptions local; + ImplementationRepository::StartupOptions* options = NULL; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->imr_->find(this->server_name_.c_str (), + server_information.out() ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (server_name_ == server_information->server.in()) + { + if (is_add_) + { + ACE_DEBUG((LM_DEBUG, "Server <%s> already registered.\n", this->server_name_.c_str ())); + return ALREADY_REGISTERED; + } + options = &server_information->startup; + } + else // not found + { + if (!is_add_) + { + ACE_DEBUG((LM_DEBUG, "Adding Server <%s> on update command.\n", this->server_name_.c_str ())); + is_add_ = true; + } + options = &local; + } + + if (this->set_command_line_) + options->command_line = CORBA::string_dup (this->command_line_.c_str ()); + + if (this->set_environment_vars_) + options->environment = this->environment_vars_; + + if (this->set_working_dir_) + options->working_directory = CORBA::string_dup (this->working_dir_.c_str ()); + + if (this->set_activation_ || is_add_) + options->activation = this->activation_; + + if (this->set_retry_count_ || is_add_) + options->start_limit = this->retry_count_ + 1; + + if (this->set_activator_) + options->activator = CORBA::string_dup(this->activator_.c_str ()); + // If the command line is set, we must have an activator + else if (this->set_command_line_ && + (options->activator.in () == 0 || *options->activator.in () == 0)) + { + char host_name[MAXHOSTNAMELEN + 1]; + ACE_OS::hostname (host_name, MAXHOSTNAMELEN); + options->activator = CORBA::string_dup (host_name); + ACE_DEBUG ((LM_DEBUG, "Updating Server <%s> with default activator of <%s>.\n", + this->server_name_.c_str (), options->activator.in ())); + } + + this->imr_->add_or_update_server (this->server_name_.c_str (), *options ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG((LM_DEBUG, "Successfully registered <%s>.\n", this->server_name_.c_str ())); + } + ACE_CATCH (CORBA::NO_PERMISSION, ex) + { + ACE_ERROR ((LM_ERROR, "No Permission: ImplRepo is in Locked mode\n")); + return TAO_IMR_Op::NO_PERMISSION; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Updating server"); + return TAO_IMR_Op::UNKNOWN; + } + ACE_ENDTRY; + + return TAO_IMR_Op::NORMAL; +} + +// ============================================================================ +// = Display Server Information methods + +void +TAO_IMR_Op_List::display_server_information (const ImplementationRepository::ServerInformation &info) +{ + if (this->verbose_server_information_) + TAO_IMR_Op::display_server_information (info); + else + ACE_DEBUG ((LM_DEBUG, "<%s>\n", info.server.in ())); +} diff --git a/TAO/orbsvcs/ImplRepo_Service/tao_imr_i.h b/TAO/orbsvcs/ImplRepo_Service/tao_imr_i.h new file mode 100644 index 00000000000..df728e7002e --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/tao_imr_i.h @@ -0,0 +1,322 @@ +/* -*- C++ -*- */ + +//============================================================================= +/** + * @file tao_imr_i.h + * + * $Id$ + * + * This class implements the Implementation Repository helper application. + * + * + * @author Darrell Brunsch <brunsch@cs.wustl.edu> + */ +//============================================================================= +#ifndef TAO_IMR_I_H +#define TAO_IMR_I_H + +#include "tao/ImR_Client/ImplRepoC.h" +#include "tao/corba.h" +#include "ace/SString.h" +#include "ace/Auto_Ptr.h" + +// Forward Declaration +class TAO_IMR_Op; + +/** + * @class TAO_IMR_i + * + * @brief TAO's command line helper application + * + * This class talks to the IMR and registers/lists/etc. + */ +class TAO_IMR_i +{ +public: + + // = Constructor and destructor. + TAO_IMR_i (void); + ~TAO_IMR_i (void); + + /// Execute client code. + int run (void); + + /// Initialize the client communication endpoint with server. + int init (int argc, char **argv); + +private: + /// Print out information about all operations. + void print_usage (void); + + /// Parses the arguments passed on the command line. + int parse_args (void); + + /// # of arguments on the command line. + int argc_; + + /// Arguments from command line. + ACE_TCHAR **argv_; + + /// Remember our orb. + CORBA::ORB_var orb_; + + /// Reference to our Locator interface of + /// implementation repository. + ImplementationRepository::Administration_var imr_; + + /// What we need to do. + ACE_Auto_Ptr<TAO_IMR_Op> op_; +}; + + +/** + * @class TAO_IMR_Op + * + * @brief IMR Operation Base Class + * + * Provides a base class with virtual methods for each operation strategy. + */ +class TAO_IMR_Op +{ +public: + enum RETURN_CODES { + NORMAL = 0, + UNKNOWN, + NO_PERMISSION, + ALREADY_REGISTERED, + CANNOT_ACTIVATE, + NOT_FOUND + }; + + /// Factory. + static TAO_IMR_Op *make_op (const ACE_TCHAR *op_name); + + /// Destructor. + virtual ~TAO_IMR_Op (void); + + /// Parse arguments. + virtual int parse (int argc, ACE_TCHAR **argv) = 0; + + /// Do the work. + virtual int run (void) = 0; + + /// Sets the implrepo locator pointer + void set_imr (ImplementationRepository::Administration_ptr imr); + +protected: + /// Reference to our implementation repository. + ImplementationRepository::Administration_ptr imr_; + + // = Helper methods + + /// Prints out the information contained in a ServerInformation structure. + void display_server_information (const ImplementationRepository::ServerInformation &info); +}; + + +/** + * @class TAO_IMR_Op_Activate + * + * @brief Activation Operation + * + * Activation is used to start servers via the Implementation Repository + */ +class TAO_IMR_Op_Activate : public TAO_IMR_Op +{ +public: + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + /// Prints a message about the usage + void print_usage (void); + + /// POA server name. + ACE_CString server_name_; +}; + +/** + * @class TAO_IMR_Op_Autostart + * + * @brief Autostart Operation + * + * Autostart is used to activate all servers with the AUTO_START activation + * mode. + */ +class TAO_IMR_Op_Autostart : public TAO_IMR_Op +{ +public: + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + /// Prints a message about the usage + void print_usage (void); +}; + + +/** + * @class TAO_IMR_Op_IOR + * + * @brief IOR Operation + * + * IOR is used to create a simple IOR for a server that uses the + * IMR and the Interoperable Naming Service. + */ +class TAO_IMR_Op_IOR : public TAO_IMR_Op +{ +public: + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + /// Prints a message about the usage + void print_usage (void); + + /// POA server name. + ACE_CString server_name_; + + /// Filename to output to. + ACE_CString filename_; +}; + + +/** + * @class TAO_IMR_Op_List + * + * @brief List Operation + * + * List is used to either list all the servers registered in the IMR or just + * look at one of them. + */ +class TAO_IMR_Op_List : public TAO_IMR_Op +{ +public: + TAO_IMR_Op_List (void); + + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + /// Prints a message about the usage + void print_usage (void); + + /// POA server name. + ACE_CString server_name_; + + /// If true, more server information is displayed. + int verbose_server_information_; + + /// Prints out the information contained in a ServerInformation structure. + /// Specialized to only print server information + void display_server_information (const ImplementationRepository::ServerInformation &info); +}; + + +/** + * @class TAO_IMR_Op_Remove + * + * @brief Remove Operation + * + * Remove is used to unregister a server in the IMR. + */ +class TAO_IMR_Op_Remove : public TAO_IMR_Op +{ +public: + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + /// Prints a message about the usage + void print_usage (void); + + ACE_CString server_name_; +}; + + +/** + * @class TAO_IMR_Op_Shutdown + * + * @brief Shutdown Operation + * + * Shutdown is used to shutdown a server through the IMR. + */ +class TAO_IMR_Op_Shutdown : public TAO_IMR_Op +{ +public: + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + /// Prints a message about the usage + void print_usage (void); + + ACE_CString server_name_; +}; + +/** + * Shutdown the ImR and optionally any registered activators. + */ +class TAO_IMR_Op_ShutdownRepo : public TAO_IMR_Op +{ +public: + TAO_IMR_Op_ShutdownRepo(); + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + void print_usage (void); + + bool activators_; +}; + +/** + * @class TAO_IMR_Op_Register + * + * @brief Register Operation + * + * Register is used to update/add information for a server + * with the IMR. + */ +class TAO_IMR_Op_Register : public TAO_IMR_Op +{ +public: + TAO_IMR_Op_Register(bool is_add); + + virtual int parse (int argc, ACE_TCHAR **argv); + virtual int run (void); + +protected: + + /// Enables pre-registration checks + bool is_add_; + + /// Sets one environment variable. + void addenv (ACE_TCHAR *opt); + + /// Prints a message about the usage. + void print_usage (void); + + /// POA server name. + ACE_CString server_name_; + + bool set_command_line_; + ACE_CString command_line_; + + bool set_environment_vars_; + ImplementationRepository::EnvironmentList environment_vars_; + + bool set_working_dir_; + ACE_CString working_dir_; + + bool set_activation_; + ImplementationRepository::ActivationMode activation_; + + bool set_retry_count_; + int retry_count_; + + bool set_activator_; + ACE_CString activator_; +}; + +#endif /* TAO_IMR_I_H */ diff --git a/TAO/orbsvcs/ImplRepo_Service/utils.h b/TAO/orbsvcs/ImplRepo_Service/utils.h new file mode 100644 index 00000000000..2e4effd55b9 --- /dev/null +++ b/TAO/orbsvcs/ImplRepo_Service/utils.h @@ -0,0 +1,98 @@ +//$Id$ +#ifndef TAO_IMR_UTILS_H +#define TAO_IMR_UTILS_H + +#include "tao/ImR_Client/ImplRepoC.h" + +#include "ace/SString.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class ImR_Utils { +public: + static ACE_CString activationModeToString(ImplementationRepository::ActivationMode mode) + { + switch (mode ) + { + case ImplementationRepository::NORMAL: + return "NORMAL"; + case ImplementationRepository::MANUAL: + return "MANUAL"; + case ImplementationRepository::PER_CLIENT: + return "PER_CLIENT"; + case ImplementationRepository::AUTO_START: + return "AUTO_START"; + default: + ACE_ASSERT(mode == ImplementationRepository::NORMAL); + return ""; + } + } + static ImplementationRepository::ActivationMode parseActivationMode(const ACE_CString& s) + { + if (s == "NORMAL") + return ImplementationRepository::NORMAL; + if (s == "MANUAL") + return ImplementationRepository::MANUAL; + if (s == "PER_CLIENT") + return ImplementationRepository::PER_CLIENT; + if (s == "AUTO_START") + return ImplementationRepository::AUTO_START; + + return ImplementationRepository::NORMAL; + } + static ACE_CString envListToString(const ImplementationRepository::EnvironmentList& lst) + { + ACE_CString ret; + for (CORBA::ULong n = 0; n < lst.length(); ++n) + { + ret += "name=\""; + ret += lst[n].name.in(); + ret += "\" value=\""; + ret += lst[n].value.in(); + ret += "\"\n"; + } + return ret; + } + static ImplementationRepository::EnvironmentList parseEnvList(const ACE_CString& s) + { + ImplementationRepository::EnvironmentList ret(10); + + const ACE_CString NAMETAG = "name=\""; + const ACE_CString VALTAG = "value=\""; + const ACE_CString ENDTAG = "\""; + + ACE_CString::size_type i = 0; + + for (CORBA::ULong idx = 0; ; ++idx) + { + // find name + ACE_CString::size_type j = s.find(NAMETAG, i); + if (j == ACE_CString::npos) break; + j += NAMETAG.length(); + ACE_CString::size_type k = s.find(ENDTAG, j + 1); + if (k == ACE_CString::npos) break; + ACE_CString name = s.substr(j, k - j); + + i = k + 1; + + // find value + j = s.find(VALTAG, i); + if (j == ACE_CString::npos) break; + j += VALTAG.length(); + k = s.find(ENDTAG, j + 1); + if (k == ACE_CString::npos) break; + ACE_CString value = s.substr(j, k - j); + + i = k + 1; + + ret.length(idx + 1); + ret[idx].name = name.c_str(); + ret[idx].value = value.c_str(); + } + return ret; + } +}; + +#endif |