diff options
Diffstat (limited to 'trunk/TAO/orbsvcs/LoadBalancer/LoadManager.cpp')
-rw-r--r-- | trunk/TAO/orbsvcs/LoadBalancer/LoadManager.cpp | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/trunk/TAO/orbsvcs/LoadBalancer/LoadManager.cpp b/trunk/TAO/orbsvcs/LoadBalancer/LoadManager.cpp new file mode 100644 index 00000000000..b95c5ca9c6b --- /dev/null +++ b/trunk/TAO/orbsvcs/LoadBalancer/LoadManager.cpp @@ -0,0 +1,310 @@ +#include "Signal_Handler.h" + +#include "orbsvcs/LoadBalancing/LB_LoadManager.h" + +#include "tao/ORB_Core.h" + +#include "ace/Get_Opt.h" +#include "ace/OS_main.h" +#include "ace/OS_NS_strings.h" + +#include "tao/IORTable/IORTable.h" + +#if defined (linux) && defined (ACE_HAS_THREADS) +# include "ace/Signal.h" +#endif /* linux && ACE_HAS_THREADS */ + + +ACE_RCSID (LoadBalancer, + LoadBalancer, + "$Id$") + + +static const char * lm_ior_file = "lm.ior"; + +void +usage (const ACE_TCHAR * cmd) +{ + ACE_DEBUG ((LM_INFO, + ACE_TEXT ("Usage:\n") + ACE_TEXT (" %s\n") + ACE_TEXT (" -o <ior_output_file>\n") + ACE_TEXT (" -s <RoundRobin | Random | LeastLoaded>\n") + ACE_TEXT (" -h\n") + ACE_TEXT ("\n") + ACE_TEXT (" NOTE: Standard default values will be used ") + ACE_TEXT ("for \"LeastLoaded\" strategy.\n"), + cmd)); +} + +void +parse_args (int argc, + ACE_TCHAR *argv[], + int & default_strategy + ACE_ENV_ARG_DECL) +{ + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT ("o:s:h")); + + int c = 0; + + while ((c = get_opts ()) != -1) + { + switch (c) + { + case 'o': + ::lm_ior_file = get_opts.opt_arg (); + break; + + case 's': + if (ACE_OS::strcasecmp (get_opts.opt_arg (), + "RoundRobin") == 0) + default_strategy = 0; + else if (ACE_OS::strcasecmp (get_opts.opt_arg (), + "Random") == 0) + default_strategy = 1; + else if (ACE_OS::strcasecmp (get_opts.opt_arg (), + "LeastLoaded") == 0) + default_strategy = 2; + else + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Unknown strategy, using RoundRobin\n"))); + break; + + case 'h': + ::usage (argv[0]); + ACE_OS::exit (0); + break; + + default: + ::usage (argv[0]); + ACE_THROW (CORBA::BAD_PARAM ()); + } + } +} + +#if defined (linux) && defined (ACE_HAS_THREADS) +// Only the main thread can handle signals in Linux. Run the +// LoadManager in thread other than main(). +extern "C" +void * +TAO_LB_run_load_manager (void * orb_arg) +{ + CORBA::ORB_ptr orb = static_cast<CORBA::ORB_ptr> (orb_arg); + + // Only the main thread should handle signals. + // + // @@ This is probably unnecessary since no signals should be + // delivered to this thread on Linux. + ACE_Sig_Guard signal_guard; + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + orb->run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO Load Manager"); + + return reinterpret_cast<void *> (-1); + } + ACE_ENDTRY; + ACE_CHECK_RETURN (reinterpret_cast<void *> (-1)); + + return 0; +} +#endif /* linux && ACE_HAS_THREADS */ + +int +ACE_TMAIN (int argc, ACE_TCHAR *argv[]) +{ + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // The usual server side boilerplate code. + + CORBA::ORB_var orb = CORBA::ORB_init (argc, + argv, + "" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::Object_var obj = + orb->resolve_initial_references ("RootPOA" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (obj.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + PortableServer::POAManager_var poa_manager = + root_poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // "built-in" strategies are the following: + // 0 = RoundRobin + // 1 = Random + // 2 = LeastLoaded + int default_strategy = 1; + + // Check the non-ORB arguments. + ::parse_args (argc, + argv, + default_strategy + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + TAO_LB_LoadManager * lm = 0; + ACE_NEW_THROW_EX (lm, + TAO_LB_LoadManager, + CORBA::NO_MEMORY ( + CORBA::SystemException::_tao_minor_code ( + TAO::VMCID, + ENOMEM), + CORBA::COMPLETED_NO)); + ACE_TRY_CHECK; + + PortableServer::ServantBase_var safe_lm = lm; + + // Initalize the LoadManager servant. + lm->init (orb->orb_core ()->reactor (), + orb.in (), + root_poa.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + PortableGroup::Properties props (1); + props.length (1); + props[0].nam.length (1); + props[0].nam[0].id = + CORBA::string_dup ("org.omg.CosLoadBalancing.StrategyInfo"); + + CosLoadBalancing::StrategyInfo strategy_info; + + switch (default_strategy) + { + case 0: + strategy_info.name = CORBA::string_dup ("RoundRobin"); + break; + case 1: + strategy_info.name = CORBA::string_dup ("Random"); + break; + case 2: + strategy_info.name = CORBA::string_dup ("LeastLoaded"); + break; + default: + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("ERROR: LoadBalancer internal error.\n") + ACE_TEXT (" Unknown built-in strategy.\n")), + -1); + } + + props[0].val <<= strategy_info; + + lm->set_default_properties (props + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CosLoadBalancing::LoadManager_var load_manager = + lm->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::String_var str = + orb->object_to_string (load_manager.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // to support corbaloc + // Get a reference to the IOR table. + CORBA::Object_var tobj = orb->resolve_initial_references ("IORTable" + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + IORTable::Table_var table = IORTable::Table::_narrow (tobj.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // bind your stringified IOR in the IOR table + table->bind ("LoadManager", str.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + FILE * lm_ior = ACE_OS::fopen (lm_ior_file, "w"); + ACE_OS::fprintf (lm_ior, "%s", str.in ()); + ACE_OS::fclose (lm_ior); + +#if defined (linux) && defined (ACE_HAS_THREADS) + if (ACE_Thread_Manager::instance ()->spawn (::TAO_LB_run_load_manager, + orb.in ()) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "ERROR: Unable to spawn TAO LoadManager's " + "ORB thread.\n"), + -1); + } + + ACE_Sig_Set sigset; + sigset.sig_add (SIGINT); + sigset.sig_add (SIGTERM); + + int signum = -1; + + // Block waiting for the registered signals. + if (ACE_OS::sigwait (sigset, &signum) == -1) + { + ACE_ERROR_RETURN ((LM_ERROR, + "(%P|%t) %p\n", + "ERROR waiting on signal"), + -1); + } + + ACE_ASSERT (signum == SIGINT || signum == SIGTERM); +#else + // Activate/register the signal handler that (attempts) to + // ensure graceful shutdown of the LoadManager so that remote + // resources created by the LoadManager can be cleaned up. + TAO_LB_Signal_Handler signal_handler (orb.in (), root_poa.in ()); + + if (signal_handler.activate () != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Error: can't activate LB signal handler, exiting.\n"), + -1); + } + + // @@ There is a subtle race condition here. If the signal + // handler thread shuts down the ORB before it is run, the + // below call to ORB::run() will throw a CORBA::BAD_INV_ORDER + // exception. + orb->run (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Wait for the signal handler thread to finish + // before the process exits. + signal_handler.wait (); +#endif /* linux && ACE_HAS_THREADS */ + + orb->destroy (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } +// ACE_CATCH (PortableGroup::InvalidProperty, ex) +// { +// ACE_DEBUG ((LM_DEBUG, "Property ----> %s\n", ex.nam[0].id.in ())); +// } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, + "TAO Load Manager"); + + return -1; + } + ACE_ENDTRY; + + return 0; +} |