1 #include "orbsvcs/Log_Macros.h"
2 #include "Signal_Handler.h"
3 #include "orbsvcs/LoadBalancing/LB_LoadManager.h"
4 #include "tao/ORB_Core.h"
5 #include "ace/Get_Opt.h"
6 #include "ace/OS_main.h"
7 #include "ace/OS_NS_strings.h"
9 #include "tao/IORTable/IORTable.h"
11 #if defined (linux) && defined (ACE_HAS_THREADS)
12 # include "ace/Signal.h"
13 #endif /* linux && ACE_HAS_THREADS */
15 static const ACE_TCHAR
*lm_ior_file
= ACE_TEXT("lm.ior");
16 static int ping_timeout_milliseconds
= 2000;
17 static int ping_interval_seconds
= 0;
20 usage (const ACE_TCHAR
* cmd
)
22 ORBSVCS_DEBUG ((LM_INFO
,
25 ACE_TEXT (" -o <ior_output_file>\n")
26 ACE_TEXT (" -s <RoundRobin | Random | LeastLoaded>\n")
27 ACE_TEXT (" -i <ping_interval_seconds>\n")
28 ACE_TEXT (" -t <ping_timeout_milliseconds>\n")
31 ACE_TEXT (" NOTE: Standard default values will be used ")
32 ACE_TEXT ("for \"LeastLoaded\" strategy.\n"),
39 int & default_strategy
)
41 ACE_Get_Opt
get_opts (argc
, argv
, ACE_TEXT ("o:s:i:t:h"));
45 while ((c
= get_opts ()) != -1)
50 ::lm_ior_file
= get_opts
.opt_arg ();
54 if (ACE_OS::strcasecmp (get_opts
.opt_arg (),
55 ACE_TEXT("RoundRobin")) == 0)
57 else if (ACE_OS::strcasecmp (get_opts
.opt_arg (),
58 ACE_TEXT("Random")) == 0)
60 else if (ACE_OS::strcasecmp (get_opts
.opt_arg (),
61 ACE_TEXT("LeastLoaded")) == 0)
64 ORBSVCS_DEBUG ((LM_DEBUG
,
65 ACE_TEXT ("Unknown strategy, using RoundRobin\n")));
68 ::ping_interval_seconds
= ACE_OS::atoi (get_opts
.opt_arg ());
71 ::ping_timeout_milliseconds
= ACE_OS::atoi (get_opts
.opt_arg ());
81 throw CORBA::BAD_PARAM ();
86 #if defined (linux) && defined (ACE_HAS_THREADS)
87 // Only the main thread can handle signals in Linux. Run the
88 // LoadManager in thread other than main().
91 TAO_LB_run_load_manager (void * orb_arg
)
93 CORBA::ORB_ptr orb
= static_cast<CORBA::ORB_ptr
> (orb_arg
);
95 // Only the main thread should handle signals.
97 // @@ This is probably unnecessary since no signals should be
98 // delivered to this thread on Linux.
99 ACE_Sig_Guard signal_guard
;
105 catch (const CORBA::Exception
& ex
)
107 ex
._tao_print_exception ("TAO Load Manager");
109 return reinterpret_cast<void *> (-1);
114 #endif /* linux && ACE_HAS_THREADS */
117 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
121 // The usual server side boilerplate code.
123 CORBA::ORB_var orb
= CORBA::ORB_init (argc
, argv
);
125 CORBA::Object_var obj
=
126 orb
->resolve_initial_references ("RootPOA");
128 PortableServer::POA_var root_poa
=
129 PortableServer::POA::_narrow (obj
.in ());
131 PortableServer::POAManager_var poa_manager
=
132 root_poa
->the_POAManager ();
134 poa_manager
->activate ();
136 // "built-in" strategies are the following:
140 int default_strategy
= 1;
142 // Check the non-ORB arguments.
147 TAO_LB_LoadManager
* lm
= 0;
148 ACE_NEW_THROW_EX (lm
,
149 TAO_LB_LoadManager(::ping_timeout_milliseconds
,
150 ::ping_interval_seconds
),
152 CORBA::SystemException::_tao_minor_code (
155 CORBA::COMPLETED_NO
));
157 PortableServer::ServantBase_var safe_lm
= lm
;
159 // Initalize the LoadManager servant.
160 lm
->initialize (orb
->orb_core ()->reactor (),
164 PortableGroup::Properties
props (1);
166 props
[0].nam
.length (1);
168 CORBA::string_dup ("org.omg.CosLoadBalancing.StrategyInfo");
170 CosLoadBalancing::StrategyInfo strategy_info
;
172 switch (default_strategy
)
175 strategy_info
.name
= CORBA::string_dup ("RoundRobin");
178 strategy_info
.name
= CORBA::string_dup ("Random");
181 strategy_info
.name
= CORBA::string_dup ("LeastLoaded");
184 ORBSVCS_ERROR_RETURN ((LM_ERROR
,
185 ACE_TEXT ("ERROR: LoadBalancer internal error.\n")
186 ACE_TEXT (" Unknown built-in strategy.\n")),
190 props
[0].val
<<= strategy_info
;
192 lm
->set_default_properties (props
);
194 CosLoadBalancing::LoadManager_var load_manager
=
197 CORBA::String_var str
=
198 orb
->object_to_string (load_manager
.in ());
200 // to support corbaloc
201 // Get a reference to the IOR table.
202 CORBA::Object_var tobj
= orb
->resolve_initial_references ("IORTable");
204 IORTable::Table_var table
= IORTable::Table::_narrow (tobj
.in ());
206 // bind your stringified IOR in the IOR table
207 table
->bind ("LoadManager", str
.in ());
209 FILE * lm_ior
= ACE_OS::fopen (lm_ior_file
, "w");
210 ACE_OS::fprintf (lm_ior
, "%s", str
.in ());
211 ACE_OS::fclose (lm_ior
);
213 #if defined (linux) && defined (ACE_HAS_THREADS)
214 if (ACE_Thread_Manager::instance ()->spawn (::TAO_LB_run_load_manager
,
217 ORBSVCS_ERROR_RETURN ((LM_ERROR
,
218 "ERROR: Unable to spawn TAO LoadManager's "
224 sigset
.sig_add (SIGINT
);
225 sigset
.sig_add (SIGTERM
);
229 // Block waiting for the registered signals.
230 if (ACE_OS::sigwait (sigset
, &signum
) == -1)
232 ORBSVCS_ERROR_RETURN ((LM_ERROR
,
234 "ERROR waiting on signal"),
238 ACE_ASSERT (signum
== SIGINT
|| signum
== SIGTERM
);
240 // Activate/register the signal handler that (attempts) to
241 // ensure graceful shutdown of the LoadManager so that remote
242 // resources created by the LoadManager can be cleaned up.
243 TAO_LB_Signal_Handler
signal_handler (orb
.in (), root_poa
.in ());
245 if (signal_handler
.activate () != 0)
247 ORBSVCS_ERROR_RETURN ((LM_ERROR
,
248 "Error: can't activate LB signal handler, exiting.\n"),
252 // @@ There is a subtle race condition here. If the signal
253 // handler thread shuts down the ORB before it is run, the
254 // below call to ORB::run() will throw a CORBA::BAD_INV_ORDER
258 // Wait for the signal handler thread to finish
259 // before the process exits.
260 signal_handler
.wait ();
261 #endif /* linux && ACE_HAS_THREADS */
265 // catch (const PortableGroup::InvalidProperty& ex)
267 // ORBSVCS_DEBUG ((LM_DEBUG, "Property ----> %s\n", ex.nam[0].id.in ()));
269 catch (const CORBA::Exception
& ex
)
271 ex
._tao_print_exception ("TAO Load Manager");