1 #include "orbsvcs/Sched/Reconfig_Scheduler.h"
2 #include "orbsvcs/Runtime_Scheduler.h"
3 //#include "orbsvcs/Event/Module_Factory.h"
4 //#include "orbsvcs/Event/Event_Channel.h"
5 #include "orbsvcs/Event_Service_Constants.h"
6 #include "orbsvcs/Event_Utilities.h"
7 #include "orbsvcs/Scheduler_Factory.h"
8 #include "orbsvcs/Event/EC_Event_Channel.h"
9 #include "orbsvcs/Event/EC_Default_Factory.h"
10 #include "orbsvcs/Event/EC_Kokyu_Factory.h"
15 #include "ace/Get_Opt.h"
16 #include "ace/Sched_Params.h"
18 #include "ace/SString.h"
19 #include "ace/OS_NS_strings.h"
20 #include "ace/Thread.h"
26 ACE_CString sched_type
="rms";
29 inline RtecScheduler::Period_t
time_val_to_period (const ACE_Time_Value
&tv
)
32 return static_cast<RtecScheduler::Period_t
> (tv
.sec () * 1000000 + tv
.usec ())*10;
35 int parse_args (int argc
, ACE_TCHAR
*argv
[]);
37 typedef TAO_Reconfig_Scheduler
<TAO_RMS_FAIR_Reconfig_Sched_Strategy
, TAO_SYNCH_MUTEX
> RECONFIG_RMS_SCHED_TYPE
;
39 typedef TAO_Reconfig_Scheduler
<TAO_MUF_FAIR_Reconfig_Sched_Strategy
, TAO_SYNCH_MUTEX
> RECONFIG_MUF_SCHED_TYPE
;
42 ACE_TMAIN(int argc
, ACE_TCHAR
*argv
[])
44 ACE_UNUSED_ARG (config_run
);
46 //TAO_EC_Default_Factory::init_svcs ();
48 TAO_EC_Kokyu_Factory::init_svcs ();
53 // ORB initialization boiler plate...
55 CORBA::ORB_init (argc
, argv
);
57 if (parse_args (argc
, argv
) == -1)
60 "Usage: Service [-o IOR_file_name]\n"));
64 CORBA::Object_var object
=
65 orb
->resolve_initial_references ("RootPOA");
66 PortableServer::POA_var poa
=
67 PortableServer::POA::_narrow (object
.in ());
68 PortableServer::POAManager_var poa_manager
=
69 poa
->the_POAManager ();
70 poa_manager
->activate ();
72 // ****************************************************************
74 // Create an scheduling service
75 POA_RtecScheduler::Scheduler
* sched_impl
= 0;
77 if (ACE_OS::strcasecmp(sched_type
.c_str(), "rms") == 0)
79 ACE_DEBUG ((LM_DEBUG
, "Creating RMS scheduler\n"));
80 ACE_NEW_RETURN (sched_impl
,
81 RECONFIG_RMS_SCHED_TYPE
,
84 else if (ACE_OS::strcasecmp(sched_type
.c_str(), "muf") == 0)
86 ACE_DEBUG ((LM_DEBUG
, "Creating MUF scheduler\n"));
87 ACE_NEW_RETURN (sched_impl
,
88 RECONFIG_MUF_SCHED_TYPE
,
92 RtecScheduler::Scheduler_var scheduler
=
95 // ****************************************************************
96 TAO_EC_Event_Channel_Attributes
attributes (poa
.in (),
98 attributes
.scheduler
= scheduler
.in (); // no need to dup
100 TAO_EC_Event_Channel
ec_impl (attributes
);
101 RtecEventChannelAdmin::EventChannel_var event_channel
=
103 // ****************************************************************
105 // Create a consumer, intialize its RT_Info structures, and
106 // connnect to the event channel....
108 Consumer consumer_impl1
, consumer_impl2
;
110 RtecScheduler::handle_t consumer1_rt_info
=
111 scheduler
->create ("consumer1");
113 RtecScheduler::handle_t consumer2_rt_info
=
114 scheduler
->create ("consumer2");
116 //consumer's rate will get propagated from the supplier.
117 //so no need to specify a period here. Specifying
118 //criticality is crucial since it propagates from
119 //consumer to supplier.
120 ACE_Time_Value
tv (0,0);
122 ORBSVCS_Time::Time_Value_to_TimeT (tmp
, tv
);
123 scheduler
->set (consumer1_rt_info
,
124 RtecScheduler::VERY_LOW_CRITICALITY
,
126 time_val_to_period (tv
),
127 RtecScheduler::VERY_LOW_IMPORTANCE
,
130 RtecScheduler::OPERATION
);
132 scheduler
->set (consumer2_rt_info
,
133 RtecScheduler::VERY_HIGH_CRITICALITY
,
135 time_val_to_period (tv
),
136 RtecScheduler::VERY_HIGH_IMPORTANCE
,
139 RtecScheduler::OPERATION
);
141 ACE_ConsumerQOS_Factory consumer_qos1
, consumer_qos2
;
142 //consumer_qos.start_disjunction_group ();
143 // The types int the range [0,ACE_ES_EVENT_UNDEFINED) are
144 // reserved for the EC...
145 consumer_qos1
.insert_type (ACE_ES_EVENT_UNDEFINED
,
148 RtecEventChannelAdmin::ConsumerQOS qos
=
149 consumer_qos1
.get_ConsumerQOS ();
151 for (int i=0;i<qos.dependencies.length (); ++i)
153 ACE_DEBUG ((LM_DEBUG,
154 "consumer_qos1[%d] event.header.type = %d, "
155 "consumer_qos1[%d] rt_info = %d, "
156 "consumer_qos1[%d] event.header.source = %d\n",
157 i,qos.dependencies[i].event.header.type,
158 i,qos.dependencies[i].rt_info,
159 i,qos.dependencies[i].event.header.source));
163 consumer_qos2
.insert_type (ACE_ES_EVENT_UNDEFINED
+ 1,
166 // The canonical protocol to connect to the EC
167 RtecEventChannelAdmin::ConsumerAdmin_var consumer_admin
=
168 event_channel
->for_consumers ();
170 RtecEventChannelAdmin::ProxyPushSupplier_var supplier_proxy1
=
171 consumer_admin
->obtain_push_supplier ();
173 RtecEventChannelAdmin::ProxyPushSupplier_var supplier_proxy2
=
174 consumer_admin
->obtain_push_supplier ();
176 RtecEventComm::PushConsumer_var consumer1
=
177 consumer_impl1
._this ();
179 RtecEventComm::PushConsumer_var consumer2
=
180 consumer_impl2
._this ();
182 ACE_DEBUG ((LM_DEBUG
, "connecting consumers\n"));
183 ACE_DEBUG ((LM_DEBUG
, "connecting consumer1\n"));
184 supplier_proxy1
->connect_push_consumer (consumer1
.in (),
185 consumer_qos1
.get_ConsumerQOS ());
187 ACE_DEBUG ((LM_DEBUG
, "connecting consumer2\n"));
188 supplier_proxy2
->connect_push_consumer (consumer2
.in (),
189 consumer_qos2
.get_ConsumerQOS ());
191 ACE_DEBUG ((LM_DEBUG
, "consumers connected\n"));
193 // ****************************************************************
195 RtecScheduler::handle_t supplier1_rt_info
=
196 scheduler
->create ("supplier1");
198 RtecScheduler::handle_t supplier2_rt_info
=
199 scheduler
->create ("supplier2");
201 RtecEventComm::EventSourceID supplier_id1
= 1, supplier_id2
= 2;
202 ACE_SupplierQOS_Factory supplier_qos1
, supplier_qos2
;
203 supplier_qos1
.insert (supplier_id1
,
204 ACE_ES_EVENT_UNDEFINED
,
206 1 /* number of calls, but what does that mean? */);
207 supplier_qos2
.insert (supplier_id2
,
208 ACE_ES_EVENT_UNDEFINED
+ 1,
210 1 /* number of calls, but what does that mean? */);
212 // The canonical protocol to connect to the EC
213 RtecEventChannelAdmin::SupplierAdmin_var supplier_admin
=
214 event_channel
->for_suppliers ();
216 RtecEventChannelAdmin::ProxyPushConsumer_var consumer_proxy1
=
217 supplier_admin
->obtain_push_consumer ();
219 RtecEventChannelAdmin::ProxyPushConsumer_var consumer_proxy2
=
220 supplier_admin
->obtain_push_consumer ();
222 Supplier
supplier_impl1(supplier_id1
, consumer_proxy1
.in ());
223 Supplier
supplier_impl2(supplier_id2
, consumer_proxy2
.in ());
225 RtecEventComm::PushSupplier_var supplier1
=
226 supplier_impl1
._this ();
228 RtecEventComm::PushSupplier_var supplier2
=
229 supplier_impl2
._this ();
231 ACE_DEBUG ((LM_DEBUG
, "connecting suppliers\n"));
232 ACE_DEBUG ((LM_DEBUG
, "connecting supplier1\n"));
233 consumer_proxy1
->connect_push_supplier (supplier1
.in (),
234 supplier_qos1
.get_SupplierQOS ());
236 ACE_DEBUG ((LM_DEBUG
, "connecting supplier2\n"));
237 consumer_proxy2
->connect_push_supplier (supplier2
.in (),
238 supplier_qos2
.get_SupplierQOS ());
239 ACE_DEBUG ((LM_DEBUG
, "suppliers connected\n"));
241 // ****************************************************************
243 //Timer Registration part
245 //Timeout consumers for the two suppliers.
246 Timeout_Consumer
timeout_consumer_impl1(&supplier_impl1
);
247 Timeout_Consumer
timeout_consumer_impl2(&supplier_impl2
);
249 RtecScheduler::handle_t supplier1_timeout_consumer_rt_info
=
250 scheduler
->create ("supplier1_timeout_consumer");
254 ORBSVCS_Time::Time_Value_to_TimeT (tmp
, tv
);
256 scheduler
->set (supplier1_timeout_consumer_rt_info
,
257 RtecScheduler::VERY_LOW_CRITICALITY
,
259 time_val_to_period (tv
),
260 RtecScheduler::VERY_LOW_IMPORTANCE
,
263 RtecScheduler::OPERATION
);
265 RtecScheduler::handle_t supplier2_timeout_consumer_rt_info
=
266 scheduler
->create ("supplier2_timeout_consumer");
270 ORBSVCS_Time::Time_Value_to_TimeT (tmp
, tv
);
272 scheduler
->set (supplier2_timeout_consumer_rt_info
,
273 RtecScheduler::VERY_HIGH_CRITICALITY
,
275 time_val_to_period (tv
),
276 RtecScheduler::VERY_HIGH_IMPORTANCE
,
279 RtecScheduler::OPERATION
);
281 ACE_ConsumerQOS_Factory timer_qos1
, timer_qos2
;
282 timer_qos1
.insert_time (ACE_ES_EVENT_INTERVAL_TIMEOUT
,
283 10000000, //in 100s of nanosec
284 supplier1_timeout_consumer_rt_info
);
285 timer_qos2
.insert_time (ACE_ES_EVENT_INTERVAL_TIMEOUT
,
286 30000000, //in 100s of nanosec
287 supplier2_timeout_consumer_rt_info
);
289 RtecEventChannelAdmin::ProxyPushSupplier_var timeout_supplier_proxy1
=
290 consumer_admin
->obtain_push_supplier ();
292 RtecEventChannelAdmin::ProxyPushSupplier_var timeout_supplier_proxy2
=
293 consumer_admin
->obtain_push_supplier ();
295 RtecEventComm::PushConsumer_var safe_timeout_consumer1
=
296 timeout_consumer_impl1
._this ();
298 RtecEventComm::PushConsumer_var safe_timeout_consumer2
=
299 timeout_consumer_impl2
._this ();
301 ACE_DEBUG ((LM_DEBUG
, "connecting timeout consumers\n"));
302 timeout_supplier_proxy1
->
303 connect_push_consumer (safe_timeout_consumer1
.in (),
304 timer_qos1
.get_ConsumerQOS ());
306 timeout_supplier_proxy2
->
307 connect_push_consumer (safe_timeout_consumer2
.in (),
308 timer_qos2
.get_ConsumerQOS ());
310 ACE_DEBUG ((LM_DEBUG
, "timeout consumers connected\n"));
312 // ****************************************************************
313 //Registering dependency between timeout consumers and our suppliers
316 scheduler
->add_dependency (supplier1_timeout_consumer_rt_info
,
319 RtecBase::TWO_WAY_CALL
);
321 scheduler
->add_dependency (supplier2_timeout_consumer_rt_info
,
324 RtecBase::TWO_WAY_CALL
);
326 // ****************************************************************
328 // At this point the consumer and supplier are connected to the
329 // EC, they have provided their QoS info to the Scheduling
330 // Service and the EC has informed the Scheduler about the
331 // dependencies between them.
332 // We can now compute the schedule for this configuration...
334 // The schedule is returned in this variables....
336 ACE_DEBUG ((LM_DEBUG
, "Computing schedule\n"));
337 RtecScheduler::RT_Info_Set_var infos
;
338 RtecScheduler::Config_Info_Set_var configs
;
339 RtecScheduler::Dependency_Set_var dependencies
;
340 RtecScheduler::Scheduling_Anomaly_Set unsafe_anomalies
;
341 RtecScheduler::Scheduling_Anomaly_Set_var anomalies
;
343 scheduler
->get_rt_info_set (infos
.out() );
344 scheduler
->get_dependency_set (dependencies
.out() );
345 scheduler
->get_config_info_set (configs
.out() );
347 ACE_DEBUG ((LM_DEBUG
, "Printing intermediate results\n"));
348 ACE_Scheduler_Factory::dump_schedule (infos
.in (),
352 ACE_TEXT("schedule.out"));
354 // Obtain the range of valid priorities in the current
355 // platform, the scheduler hard-code this values in the
356 // generated file, but in the future we may just use the
357 // "logical" priorities and define the mapping to OS
358 // priorities at run-time.
359 int min_os_priority
=
360 ACE_Sched_Params::priority_min (ACE_SCHED_FIFO
,
362 int max_os_priority
=
363 ACE_Sched_Params::priority_max (ACE_SCHED_FIFO
,
365 scheduler
->compute_scheduling (min_os_priority
,
372 // Dump the schedule to a file..
373 ACE_Scheduler_Factory::dump_schedule (infos
.in (),
377 ACE_TEXT("schedule.out"));
379 // ****************************************************************
380 ACE_DEBUG ((LM_DEBUG
, "Pushing events\n"));
382 ACE_hthread_t thr_handle
;
383 ACE_Thread::self (thr_handle
);
385 int prio
= ACE_Sched_Params::priority_max (ACE_SCHED_FIFO
);
386 ACE_OS::thr_setprio (thr_handle
, prio
);
388 // // Generate a few events....
389 // RtecEventComm::EventSet event1 (1);
390 // event1.length (1);
391 // event1[0].header.type = ACE_ES_EVENT_UNDEFINED;
392 // event1[0].header.source = supplier_id1;
393 // event1[0].header.ttl = 1;
395 // RtecEventComm::EventSet event2 (1);
396 // event2.length (1);
397 // event2[0].header.type = ACE_ES_EVENT_UNDEFINED + 1;
398 // event2[0].header.source = supplier_id2;
399 // event2[0].header.ttl = 1;
401 // for (int i = 0; i != 200; ++i)
405 // consumer_proxy1->push (event1);
409 // consumer_proxy2->push (event2);
412 // ACE_Time_Value rate (0, 10000);
413 // ACE_OS::sleep (rate);
416 ACE_DEBUG ((LM_DEBUG
, "(%t) activating EC\n"));
418 ACE_DEBUG ((LM_DEBUG
, "EC activated\n"));
422 // ****************************************************************
424 // We should do a lot of cleanup (disconnect from the EC,
425 // deactivate all the objects with the POA, etc.) but this is
426 // just a simple demo so we are going to be lazy.
429 catch (const CORBA::Exception
& ex
)
431 ex
._tao_print_exception ("Service");
437 // ****************************************************************
439 int parse_args (int argc
, ACE_TCHAR
*argv
[])
441 ACE_Get_Opt
get_opts (argc
, argv
, ACE_TEXT("cs:"));
444 while ((c
= get_opts ()) != -1)
448 sched_type
= ACE_TEXT_ALWAYS_CHAR(get_opts
.opt_arg ());
453 ACE_ERROR_RETURN ((LM_ERROR
,
460 // Indicates successful parsing of the command line