1 #include "orbsvcs/Log_Macros.h"
2 #include "Push_Handler.h"
3 #include "Monitor_Signal_Handler.h"
5 #include "orbsvcs/LoadBalancing/LB_CPU_Load_Average_Monitor.h"
6 #include "orbsvcs/LoadBalancing/LB_conf.h"
8 #include "tao/ORB_Core.h"
10 #include "ace/Reactor.h"
11 #include "ace/Get_Opt.h"
12 #include "ace/OS_main.h"
13 #include "ace/OS_NS_strings.h"
15 static const ACE_TCHAR
* location_id
= 0;
16 static const ACE_TCHAR
* location_kind
= 0;
17 static const ACE_TCHAR
* mtype
= ACE_TEXT("CPU");
18 static const ACE_TCHAR
* mstyle
= ACE_TEXT("PUSH");
19 static const ACE_TCHAR
* custom_monitor_ior
= 0;
21 // For the sake of consistency, make default push monitoring interval
22 // the same as the pull monitoring interval.
23 static long push_interval
= TAO_LB_PULL_HANDLER_INTERVAL
;
26 usage (const ACE_TCHAR
* cmd
)
28 ORBSVCS_DEBUG ((LM_INFO
,
31 ACE_TEXT (" -l <location_id>\n")
32 ACE_TEXT (" -k <location_kind>\n")
33 ACE_TEXT (" -t <CPU | Disk | Memory | Network>\n")
34 ACE_TEXT (" -s <PULL | PUSH>\n")
35 ACE_TEXT (" -i <push_interval> (in seconds,")
36 ACE_TEXT (" and requires \"PUSH\" style monitoring)\n")
37 ACE_TEXT (" -m <custom_monitor_ior>")
38 ACE_TEXT (" (overrides \"-t\", \"-l\" and \"-k\")\n")
45 parse_args (int argc
, ACE_TCHAR
*argv
[])
47 ACE_Get_Opt
get_opts (argc
, argv
, ACE_TEXT ("l:k:t:s:i:m:h"));
50 const ACE_TCHAR
* s
= 0;
52 while ((c
= get_opts ()) != -1)
57 ::custom_monitor_ior
= get_opts
.opt_arg ();
61 ::location_id
= get_opts
.opt_arg ();
65 ::location_kind
= get_opts
.opt_arg ();
69 ::mtype
= get_opts
.opt_arg ();
73 ::mstyle
= get_opts
.opt_arg ();
77 s
= get_opts
.opt_arg ();
78 push_interval
= ACE_OS::atoi (s
);
79 if (push_interval
< 1)
81 ORBSVCS_ERROR ((LM_ERROR
,
82 ACE_TEXT ("ERROR: Invalid push interval: %s\n"),
85 throw CORBA::BAD_PARAM ();
96 throw CORBA::BAD_PARAM ();
101 #if defined (ACE_LINUX) && defined (ACE_HAS_THREADS)
102 // Only the main thread can handle signals in Linux. Run the
103 // LoadManager in thread other than main().
106 TAO_LB_run_load_monitor (void * orb_arg
)
108 CORBA::ORB_ptr orb
= static_cast<CORBA::ORB_ptr
> (orb_arg
);
110 // Only the main thread should handle signals.
112 // @@ This is probably unnecessary since no signals should be
113 // delivered to this thread on Linux.
114 ACE_Sig_Guard signal_guard
;
120 catch (const CORBA::Exception
& ex
)
122 ex
._tao_print_exception ("TAO Load Monitor");
124 return reinterpret_cast<void *> (-1);
129 #endif /* linux && ACE_HAS_THREADS */
132 CosLoadBalancing::LoadMonitor_ptr
133 get_load_monitor (CORBA::ORB_ptr orb
,
134 PortableServer::POA_ptr root_poa
)
136 if (::custom_monitor_ior
!= 0)
138 CORBA::Object_var obj
=
139 orb
->string_to_object (::custom_monitor_ior
);
141 return CosLoadBalancing::LoadMonitor::_narrow (obj
.in ());
145 // The POA is only needed for the built-in load monitors since
146 // they must be activated.
147 PortableServer::POAManager_var poa_manager
=
148 root_poa
->the_POAManager ();
150 poa_manager
->activate ();
152 if (ACE_OS::strcasecmp (::mtype
, ACE_TEXT("CPU")) == 0)
154 TAO_LB_CPU_Load_Average_Monitor
* monitor
= 0;
155 ACE_NEW_THROW_EX (monitor
,
156 TAO_LB_CPU_Load_Average_Monitor (::location_id
,
158 CORBA::NO_MEMORY ());
160 // Transfer ownership to the POA.
161 PortableServer::ServantBase_var s
= monitor
;
163 return monitor
->_this ();
165 else if (ACE_OS::strcasecmp (::mtype
, ACE_TEXT("Disk")) == 0
166 || ACE_OS::strcasecmp (::mtype
, ACE_TEXT("Memory")) == 0
167 || ACE_OS::strcasecmp (::mtype
, ACE_TEXT("Network")) == 0)
169 ORBSVCS_ERROR ((LM_ERROR
,
170 ACE_TEXT ("ERROR: \"%s\" load monitor currently ")
171 ACE_TEXT ("unimplemented.\n"),
174 throw CORBA::NO_IMPLEMENT ();
178 ORBSVCS_ERROR ((LM_ERROR
,
179 ACE_TEXT ("ERROR: Unrecognized built-in load monitor ")
180 ACE_TEXT ("type: <%s>.\n"),
183 throw CORBA::BAD_PARAM ();
189 register_load_monitor (CosLoadBalancing::LoadManager_ptr manager
,
190 CosLoadBalancing::LoadMonitor_ptr monitor
,
191 TAO_LB_Push_Handler
* handler
,
192 ACE_Reactor
* reactor
,
195 if (ACE_OS::strcasecmp (::mstyle
, ACE_TEXT("PULL")) == 0)
197 PortableGroup::Location_var location
=
198 monitor
->the_location ();
200 manager
->register_load_monitor (location
.in (),
203 else if (ACE_OS::strcasecmp (::mstyle
, ACE_TEXT("PUSH")) == 0)
205 ACE_Time_Value
interval (::push_interval
, 0);
206 ACE_Time_Value
restart (::push_interval
, 0);
207 timer_id
= reactor
->schedule_timer (handler
,
214 ORBSVCS_ERROR ((LM_ERROR
,
215 ACE_TEXT ("ERROR: Unable to schedule timer for ")
216 ACE_TEXT ("\"PUSH\" style load monitoring.\n")));
218 throw CORBA::INTERNAL ();
223 ORBSVCS_ERROR ((LM_ERROR
,
224 ACE_TEXT ("ERROR: Unrecognized load monitoring ")
225 ACE_TEXT ("style: <%s>.\n"),
228 throw CORBA::BAD_PARAM ();
233 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
237 // The usual server side boilerplate code.
239 CORBA::ORB_var orb
= CORBA::ORB_init (argc
, argv
);
241 // Check the non-ORB arguments.
245 CORBA::Object_var obj
=
246 orb
->resolve_initial_references ("RootPOA");
248 PortableServer::POA_var root_poa
=
249 PortableServer::POA::_narrow (obj
.in ());
251 CosLoadBalancing::LoadMonitor_var load_monitor
=
252 ::get_load_monitor (orb
.in (),
255 PortableGroup::Location_var location
=
256 load_monitor
->the_location ();
258 // The "LoadManager" reference should have already been
259 // registered with the ORB by its ORBInitializer.
260 obj
= orb
->resolve_initial_references ("LoadManager");
262 CosLoadBalancing::LoadManager_var load_manager
=
263 CosLoadBalancing::LoadManager::_narrow (obj
.in ());
265 // This "push" handler will only be used if the load monitor
267 TAO_LB_Push_Handler
push_handler (load_monitor
.in (),
271 ACE_Reactor
* reactor
= orb
->orb_core ()->reactor ();
275 ::register_load_monitor (load_manager
.in (),
281 #if defined (ACE_LINUX) && defined (ACE_HAS_THREADS)
282 if (ACE_Thread_Manager::instance ()->spawn (::TAO_LB_run_load_monitor
,
285 ORBSVCS_ERROR_RETURN ((LM_ERROR
,
286 "ERROR: Unable to spawn TAO LoadMonitor's "
292 sigset
.sig_add (SIGINT
);
293 sigset
.sig_add (SIGTERM
);
297 // Block waiting for the registered signals.
298 if (ACE_OS::sigwait (sigset
, &signum
) == -1)
300 ORBSVCS_ERROR_RETURN ((LM_ERROR
,
302 "ERROR waiting on signal"),
306 ACE_ASSERT (signum
== SIGINT
|| signum
== SIGTERM
);
308 // Deregister the LoadMonitor from the LoadManager in the PULL
309 // load monitoring case.
312 load_manager
->remove_load_monitor (location
.in ());
315 // Activate/register the signal handler that (attempts) to
316 // ensure graceful shutdown of the LoadMonitor so that
317 // LoadMonitors registered with the LoadManager can be
319 CosLoadBalancing::LoadManager_ptr tmp
;
322 tmp
= load_manager
.in (); // PULL monitoring
324 tmp
= CosLoadBalancing::LoadManager::_nil (); // PUSH
326 TAO_LB_Monitor_Signal_Handler
signal_handler (
332 if (signal_handler
.activate () != 0)
335 // @@ There is a subtle race condition here. If the signal
336 // handler thread shuts down the ORB before it is run, the
337 // below call to ORB::run() will throw a CORBA::BAD_INV_ORDER
341 // Wait for the signal handler thread to finish
342 // before the process exits.
343 signal_handler
.wait ();
344 #endif /* linux && ACE_HAS_THREADS */
346 if (timer_id
!= -1 && reactor
->cancel_timer (timer_id
) == 0)
348 ORBSVCS_ERROR ((LM_ERROR
,
349 ACE_TEXT ("ERROR: Unable to cancel \"push\" load ")
350 ACE_TEXT ("monitoring timer.\n")));
352 // Just keep going. We're shutting down anyway.
357 catch (const CORBA::Exception
& ex
)
359 ex
._tao_print_exception ("TAO Load Monitor");