Merge pull request #1844 from jrw972/monterey
[ACE_TAO.git] / TAO / orbsvcs / LoadBalancer / LoadManager.cpp
blob85fb39b8d56fce4fcf3d606f2bb52164166ff82e
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;
19 void
20 usage (const ACE_TCHAR * cmd)
22 ORBSVCS_DEBUG ((LM_INFO,
23 ACE_TEXT ("Usage:\n")
24 ACE_TEXT (" %s\n")
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")
29 ACE_TEXT (" -h\n")
30 ACE_TEXT ("\n")
31 ACE_TEXT (" NOTE: Standard default values will be used ")
32 ACE_TEXT ("for \"LeastLoaded\" strategy.\n"),
33 cmd));
36 void
37 parse_args (int argc,
38 ACE_TCHAR *argv[],
39 int & default_strategy)
41 ACE_Get_Opt get_opts (argc, argv, ACE_TEXT ("o:s:i:t:h"));
43 int c = 0;
45 while ((c = get_opts ()) != -1)
47 switch (c)
49 case 'o':
50 ::lm_ior_file = get_opts.opt_arg ();
51 break;
53 case 's':
54 if (ACE_OS::strcasecmp (get_opts.opt_arg (),
55 ACE_TEXT("RoundRobin")) == 0)
56 default_strategy = 0;
57 else if (ACE_OS::strcasecmp (get_opts.opt_arg (),
58 ACE_TEXT("Random")) == 0)
59 default_strategy = 1;
60 else if (ACE_OS::strcasecmp (get_opts.opt_arg (),
61 ACE_TEXT("LeastLoaded")) == 0)
62 default_strategy = 2;
63 else
64 ORBSVCS_DEBUG ((LM_DEBUG,
65 ACE_TEXT ("Unknown strategy, using RoundRobin\n")));
66 break;
67 case 'i':
68 ::ping_interval_seconds = ACE_OS::atoi (get_opts.opt_arg ());
69 break;
70 case 't':
71 ::ping_timeout_milliseconds = ACE_OS::atoi (get_opts.opt_arg ());
72 break;
74 case 'h':
75 ::usage (argv[0]);
76 ACE_OS::exit (0);
77 break;
79 default:
80 ::usage (argv[0]);
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().
89 extern "C"
90 void *
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;
103 orb->run ();
105 catch (const CORBA::Exception& ex)
107 ex._tao_print_exception ("TAO Load Manager");
109 return reinterpret_cast<void *> (-1);
112 return 0;
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:
137 // 0 = RoundRobin
138 // 1 = Random
139 // 2 = LeastLoaded
140 int default_strategy = 1;
142 // Check the non-ORB arguments.
143 ::parse_args (argc,
144 argv,
145 default_strategy);
147 TAO_LB_LoadManager * lm = 0;
148 ACE_NEW_THROW_EX (lm,
149 TAO_LB_LoadManager(::ping_timeout_milliseconds,
150 ::ping_interval_seconds),
151 CORBA::NO_MEMORY (
152 CORBA::SystemException::_tao_minor_code (
153 TAO::VMCID,
154 ENOMEM),
155 CORBA::COMPLETED_NO));
157 PortableServer::ServantBase_var safe_lm = lm;
159 // Initalize the LoadManager servant.
160 lm->initialize (orb->orb_core ()->reactor (),
161 orb.in (),
162 root_poa.in ());
164 PortableGroup::Properties props (1);
165 props.length (1);
166 props[0].nam.length (1);
167 props[0].nam[0].id =
168 CORBA::string_dup ("org.omg.CosLoadBalancing.StrategyInfo");
170 CosLoadBalancing::StrategyInfo strategy_info;
172 switch (default_strategy)
174 case 0:
175 strategy_info.name = CORBA::string_dup ("RoundRobin");
176 break;
177 case 1:
178 strategy_info.name = CORBA::string_dup ("Random");
179 break;
180 case 2:
181 strategy_info.name = CORBA::string_dup ("LeastLoaded");
182 break;
183 default:
184 ORBSVCS_ERROR_RETURN ((LM_ERROR,
185 ACE_TEXT ("ERROR: LoadBalancer internal error.\n")
186 ACE_TEXT (" Unknown built-in strategy.\n")),
187 -1);
190 props[0].val <<= strategy_info;
192 lm->set_default_properties (props);
194 CosLoadBalancing::LoadManager_var load_manager =
195 lm->_this ();
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,
215 orb.in ()) == -1)
217 ORBSVCS_ERROR_RETURN ((LM_ERROR,
218 "ERROR: Unable to spawn TAO LoadManager's "
219 "ORB thread.\n"),
220 -1);
223 ACE_Sig_Set sigset;
224 sigset.sig_add (SIGINT);
225 sigset.sig_add (SIGTERM);
227 int signum = -1;
229 // Block waiting for the registered signals.
230 if (ACE_OS::sigwait (sigset, &signum) == -1)
232 ORBSVCS_ERROR_RETURN ((LM_ERROR,
233 "(%P|%t) %p\n",
234 "ERROR waiting on signal"),
235 -1);
238 ACE_ASSERT (signum == SIGINT || signum == SIGTERM);
239 #else
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"),
249 -1);
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
255 // exception.
256 orb->run ();
258 // Wait for the signal handler thread to finish
259 // before the process exits.
260 signal_handler.wait ();
261 #endif /* linux && ACE_HAS_THREADS */
263 orb->destroy ();
265 // catch (const PortableGroup::InvalidProperty& ex)
266 // {
267 // ORBSVCS_DEBUG ((LM_DEBUG, "Property ----> %s\n", ex.nam[0].id.in ()));
268 // }
269 catch (const CORBA::Exception& ex)
271 ex._tao_print_exception ("TAO Load Manager");
273 return -1;
276 return 0;