diff options
author | thrall <thrall@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-06-20 20:07:25 +0000 |
---|---|---|
committer | thrall <thrall@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-06-20 20:07:25 +0000 |
commit | f1b7ed6a57f2ccbcf6cf8f122817b04b1c6199df (patch) | |
tree | c142c5bc22f73c490579ac270a06fe430809c774 | |
parent | 71261c34a13b1107ca134eb97f3478cf97e4fbdf (diff) | |
download | ATCD-f1b7ed6a57f2ccbcf6cf8f122817b04b1c6199df.tar.gz |
Initial commit of module. EC_Config is intended as a generic interface for configuring the EC and other communication channels (such as Distributable Threads). An abstract factory in the tradition of EC_Factory is provided for generating implementations behind the generic TestConfig interface. An application (Test.cpp) is provided which has partial implementation (Test_Handler.*) of using the ACEXML_Parser to automatically configure the EC from XML files (test.xml is an example, using the DTD file testconfig.dtd)
19 files changed, 2314 insertions, 0 deletions
diff --git a/TAO/orbsvcs/tests/EC_Config/Config_Factory.cpp b/TAO/orbsvcs/tests/EC_Config/Config_Factory.cpp new file mode 100644 index 00000000000..d2712ef3daa --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Config_Factory.cpp @@ -0,0 +1,119 @@ +// $Id$ + +#include "ace/Arg_Shifter.h" +#include "orbsvcs/Sched/Reconfig_Scheduler.h" + +#include "Config_Factory.h" +#include "ECConfig.h" + +using namespace ConfigFactory; + +//ACE_RCSID(DOA03, Default_Config_Factory, "$Id$") + +typedef TAO_Reconfig_Scheduler<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> MUF_SCHED_TYPE; +typedef TAO_Reconfig_Scheduler<TAO_RMS_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> RMS_SCHED_TYPE; + +Default_Config_Factory::Default_Config_Factory (void) + : Config_Factory (), + test_config_(0) //default to ECConfig +{ +} + +Default_Config_Factory::~Default_Config_Factory (void) +{ +} + +int +Default_Config_Factory::init_svcs (void) +{ + /* + return ACE_Service_Config::static_svcs ()-> + insert (&ace_svc_desc_Default_Config_Factory); + */ + return 0; +} + +int +Default_Config_Factory::init (int argc, ACE_TCHAR* argv[]) +{ + ACE_Arg_Shifter arg_shifter (argc, argv); + + while (arg_shifter.is_anything_left ()) + { + const ACE_TCHAR *arg = arg_shifter.get_current (); + + if (ACE_OS::strcasecmp (arg, ACE_LIB_TEXT("-ECConfig")) == 0) + { + arg_shifter.consume_arg (); + test_config_ = 0; + + if (arg_shifter.is_parameter_next ()) + { + const ACE_TCHAR* opt = arg_shifter.get_current (); + if ((ACE_OS::strcasecmp (opt, ACE_LIB_TEXT("null")) == 0) + || (ACE_OS::strcasecmp (opt, ACE_LIB_TEXT("rms")) == 0)) + { + this->sched_type_ = RMS; //default + ACE_DEBUG ((LM_DEBUG, + "Default_Config_Factory: Scheduling type is RMS\n")); + } + else if (ACE_OS::strcasecmp (opt, ACE_LIB_TEXT("muf")) == 0) + { + this->sched_type_ = MUF; + ACE_DEBUG ((LM_DEBUG, + "Default_Config_Factory: Scheduling type is MUF\n")); + } + else + ACE_ERROR ((LM_ERROR, + "Default_Config_Factory - " + "unsupported scheduling type <%s>\n", + opt)); + arg_shifter.consume_arg (); + } + } + else + { + arg_shifter.consume_arg (); + ACE_DEBUG ((LM_DEBUG, + "Default_Config_Factory - " + "ignoring option <%s>\n", + arg)); + } + } + return 0; +} + +int +Default_Config_Factory::fini (void) +{ + return 0; +} + +TestConfig::Test_Config* +Default_Config_Factory::create_testconfig () +{ + if (this->test_config_ == 0) + { + switch (this->sched_type_) { + case MUF: + return new TestConfig::ECConfig<MUF_SCHED_TYPE>(); + break; + case RMS: + return new TestConfig::ECConfig<RMS_SCHED_TYPE>(); + break; + default: + ACE_ERROR ((LM_ERROR, + "Default_Config_Factory - " + "unknown scheduling type <%d>\n", + this->sched_type_)); + return 0; + }; + } //else... + return 0; +} + +void +Default_Config_Factory::destroy_testconfig (TestConfig::Test_Config *x) +{ + delete x; +} diff --git a/TAO/orbsvcs/tests/EC_Config/Config_Factory.h b/TAO/orbsvcs/tests/EC_Config/Config_Factory.h new file mode 100644 index 00000000000..af65de85aac --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Config_Factory.h @@ -0,0 +1,100 @@ +/* -*- C++ -*- */ +// $Id$ +// +// ============================================================================ +// +// = FILENAME +// Config_Factory +// +// = AUTHOR +// Bryan Thrall (thrall@cse.wustl.edu) +// +// ============================================================================ + +#ifndef CONFIGFACTORY_H +#define CONFIGFACTORY_H + +#include "TestConfig.h" +#include "ace/Service_Object.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +namespace ConfigFactory { + +/** + * @class Config_Factory + * + * @brief Abstract base factory for Test Configurators. + * + * Defines the Config_Factory interface. + * + * <H2>Memory Management</H2> + * The objects it creates are owned by this class, the client must + * invoke the corresponding destroy() method to release them. + */ +class Config_Factory : ACE_Service_Object +{ +public: + virtual ~Config_Factory (void) {} + + /// Create and destroy the TestConfig module. + virtual TestConfig::Test_Config* create_testconfig () = 0; + virtual void destroy_testconfig (TestConfig::Test_Config *) = 0; + +}; + +/** Enumerates the different scheduling strategies certain + * Test_Configs generated by Config_Factories can use. + */ +enum Sched_Type { + RMS, + MUF, + EDF, + RMSMLF, + MIF +}; + +/** + * @class Default_Config_Factory + * + * @brief A generic factory for TestConfigs. + * + * This class allows the user to experiment with different TestConfig + * implementations. Using a command-line like interface the user + * can specify which strategies will this factory generate. + * Since the class can be dynamically loaded the strategies can be + * set in the service configurator file. + */ +class Default_Config_Factory : public Config_Factory +{ +public: + /// Constructor + Default_Config_Factory (void); + + /// destructor... + virtual ~Default_Config_Factory (void); + + /// Helper function to register the default factory into the service + /// configurator. + static int init_svcs (void); + + // = The Service_Object entry points + virtual int init (int argc, ACE_TCHAR* argv[]); + virtual int fini (void); + + virtual TestConfig::Test_Config* create_testconfig (); + + virtual void destroy_testconfig (TestConfig::Test_Config *); +protected: + int test_config_; + Sched_Type sched_type_; +}; + +} /* namespace ConfigFactory */ + +//ACE_STATIC_SVC_DECLARE (Default_Config_Factory) +//ACE_FACTORY_DECLARE (TestConfig, Default_Config_Factory) + +#endif /* CONFIGFACTORY_H */ diff --git a/TAO/orbsvcs/tests/EC_Config/Consumer.cpp b/TAO/orbsvcs/tests/EC_Config/Consumer.cpp new file mode 100644 index 00000000000..78d35d206de --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Consumer.cpp @@ -0,0 +1,49 @@ +// $Id$ + +//#include "ace/Thread.h" +#include "Consumer.h" + +ACE_RCSID(EC_Examples, Consumer, "$Id$") + +Consumer::Consumer (void) + : _ordinal(-1) +{ +} + +Consumer::Consumer(int ord) + : _ordinal(ord) +{ +} + +void +Consumer::push (const RtecEventComm::EventSet& events + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (events.length () == 0) + { + ACE_DEBUG ((LM_DEBUG, + "Consumer (%P|%t) no events\n")); + return; + } + + int prio = -1; + ACE_hthread_t handle; + ACE_Thread::self(handle); + ACE_Thread::getprio(handle,prio); + //ACE_thread_t tid = ACE_Thread::self(); + ACE_DEBUG ((LM_DEBUG, "Consumer #%d @%d (%P|%t) we received event type %d\n", + _ordinal,prio,events[0].header.type)); +} + +void +Consumer::disconnect_push_consumer (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +// **************************************************************** + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/EC_Config/Consumer.h b/TAO/orbsvcs/tests/EC_Config/Consumer.h new file mode 100644 index 00000000000..d92e461fd20 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Consumer.h @@ -0,0 +1,60 @@ +/* -*- C++ -*- */ +// $Id$ +// +// ============================================================================ +// +// = LIBRARY +// ORBSVCS Real-time Event Channel examples +// +// = FILENAME +// Consumer +// +// = AUTHOR +// Carlos O'Ryan (coryan@cs.wustl.edu) +// +// ============================================================================ + +#ifndef CONSUMER_H +#define CONSUMER_H + +#include "orbsvcs/RtecEventCommS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class Consumer : public POA_RtecEventComm::PushConsumer +{ + // = TITLE + // Simple consumer object + // + // = DESCRIPTION + // This class is a consumer of events. + // It simply register for two event typesone event type + // The class is just a helper to simplify common tasks in EC + // tests, such as subscribing for a range of events, disconnecting + // from the EC, informing the driver of shutdown messages, etc. + // + // There are several ways to connect and disconnect this class, + // and it is up to the driver program to use the right one. + // +public: + Consumer (void); + // Constructor + + Consumer(int ord); + + // = The RtecEventComm::PushConsumer methods + + virtual void push (const RtecEventComm::EventSet& events + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + virtual void disconnect_push_consumer (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)); + // The skeleton methods. + +private: + int _ordinal; +}; + +#endif /* CONSUMER_H */ diff --git a/TAO/orbsvcs/tests/EC_Config/ECConfig.cpp b/TAO/orbsvcs/tests/EC_Config/ECConfig.cpp new file mode 100644 index 00000000000..9a0b356ebe9 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/ECConfig.cpp @@ -0,0 +1,501 @@ +// $Id$ + +#ifndef ECCONFIG_C +#define ECCONFIG_C + +#include <sstream> //for ostringstream + +#include "ace/Array.h" +#include "ace/Bound_Ptr.h" +#include "orbsvcs/Scheduler_Factory.h" +#include "orbsvcs/Event_Utilities.h" +#include "orbsvcs/Event_Service_Constants.h" +#include "orbsvcs/Event/EC_Event_Channel.h" +#include "orbsvcs/Event/EC_Kokyu_Factory.h" + +#include "ECConfig.h" + +namespace TestConfig { + +template <class SCHED_STRAT> +ECConfig<SCHED_STRAT>::ECConfig (void) + : Test_Config (), + configured (false) +{ +} + +template <class SCHED_STRAT> +ECConfig<SCHED_STRAT>::~ECConfig (void) +{ + this->reset(); +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::reset (void) +{ + // We should do a lot of cleanup (disconnect from the EC, + // deactivate all the objects with the POA, etc.). + + delete this->ec_impl; + + delete this->sched_impl; + + for(size_t i=0; i<consumers.size(); ++i) { + delete this->consumers[i]; + } + + for(size_t i=0; i<suppliers.size(); ++i) { + delete this->suppliers[i]; + } + + configured = false; +} + +template <class SCHED_STRAT> int +ECConfig<SCHED_STRAT>::configure (TCFG_SET_WPTR testconfigs) +{ + if (configured) { + this->reset(); //delete memory used by previous configuration + } + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->initEC(); + + ////////////////// EC ready; do config //////////////////// + size_t tsize = testconfigs->size(); + supplier_cfgs.size(tsize); + consumer_cfgs.size(tsize); + testcfgs.size(tsize); + consumers.size(tsize); + suppliers.size(tsize); + for (size_t i=0; i<tsize; ++i) + { + //ACE_Weak_Bound_Ptr doesn't have operator*()! ?? + //test_config_t *curcfg = (*testconfigs)[i]; + test_config_t *curcfg = (*testconfigs.unsafe_get())[i]; + testcfgs[i] = curcfg; + + RtecScheduler::Criticality_t criticality; + switch (curcfg->criticality) { + case VERY_LOW_CRITICALITY : + criticality = RtecScheduler::VERY_LOW_CRITICALITY; + break; + case LOW_CRITICALITY : + criticality = RtecScheduler::LOW_CRITICALITY; + break; + case MEDIUM_CRITICALITY : + criticality = RtecScheduler::MEDIUM_CRITICALITY; + break; + case HIGH_CRITICALITY : + criticality = RtecScheduler::HIGH_CRITICALITY; + break; + case VERY_HIGH_CRITICALITY : + criticality = RtecScheduler::VERY_HIGH_CRITICALITY; + break; + } + + RtecScheduler::Importance_t importance; + switch (curcfg->importance) { + case VERY_LOW_IMPORTANCE : + importance = RtecScheduler::VERY_LOW_IMPORTANCE; + break; + case LOW_IMPORTANCE : + importance = RtecScheduler::LOW_IMPORTANCE; + break; + case MEDIUM_IMPORTANCE : + importance = RtecScheduler::MEDIUM_IMPORTANCE; + break; + case HIGH_IMPORTANCE : + importance = RtecScheduler::HIGH_IMPORTANCE; + break; + case VERY_HIGH_IMPORTANCE : + importance = RtecScheduler::VERY_HIGH_IMPORTANCE; + break; + } + + //create supplier RT_Info + std::ostringstream supp_entry_pt; + supp_entry_pt << "Supplier Event Class " << i; //unique RT_Info entry point + RtecScheduler::handle_t rt_info = + this->scheduler->create (supp_entry_pt.str().c_str() ACE_ENV_ARG_PARAMETER); + ACE_Time_Value tv (0, curcfg->period); + TimeBase::TimeT time; + ORBSVCS_Time::Time_Value_to_TimeT (time, tv); + this->scheduler->set (rt_info, + criticality, + time, time, time, + time, + importance, + time, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (this->supplier_cfgs.set(rt_info,i) != 0) { + ACE_DEBUG((LM_DEBUG, "Could not set supplier RT_Info into config: %d of %d\n", + i,consumer_cfgs.max_size())); + return 1; + } + + //create consumer RT_Info + std::ostringstream cons_entry_pt; + cons_entry_pt << "Consumer Event Class " << i; //unique RT_Info entry point + rt_info = + this->scheduler->create (cons_entry_pt.str().c_str() ACE_ENV_ARG_PARAMETER); + tv.set (0, curcfg->period); + ORBSVCS_Time::Time_Value_to_TimeT (time, tv); + this->scheduler->set (rt_info, + criticality, + time, time, time, + time, + importance, + time, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (this->consumer_cfgs.set(rt_info,i) != 0) { + ACE_DEBUG((LM_DEBUG, "Could not set consumer RT_Info into config: %d of %d\n", + i,consumer_cfgs.max_size())); + return 1; + } + } + + this->connectConsumers(); + this->connectSuppliers(); + + ACE_DEBUG ((LM_DEBUG, "Consumer RT_Infos:\n")); + print_RT_Infos (this->consumer_cfgs); + ACE_DEBUG ((LM_DEBUG, "\nSupplier RT_Infos:\n")); + print_RT_Infos (this->supplier_cfgs); + + ////////////////// Configured; compute schedule /////////// + ACE_DEBUG ((LM_DEBUG, "Computing schedule\n")); + RtecScheduler::RT_Info_Set_var infos; + RtecScheduler::Config_Info_Set_var configs; + RtecScheduler::Scheduling_Anomaly_Set_var anomalies; + + // Obtain the range of valid priorities in the current + // platform, the scheduler hard-code this values in the + // generated file, but in the future we may just use the + // "logical" priorities and define the mapping to OS + // priorities at run-time. + int min_os_priority = + ACE_Sched_Params::priority_min (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD); + int max_os_priority = + ACE_Sched_Params::priority_max (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD); + this->scheduler->compute_scheduling (min_os_priority, + max_os_priority, + infos.out (), + configs.out (), + anomalies.out () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Dump the schedule to a file.. + ACE_Scheduler_Factory::dump_schedule (infos.in (), + configs.in (), + anomalies.in (), + "ecconfig.out"); + + ///////////// Activate the EC ///////////////// + ACE_DEBUG ((LM_DEBUG, "activating EC\n")); + this->ec_impl->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + ACE_DEBUG ((LM_DEBUG, "EC activated\n")); + + configured = true; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ECConfig"); + return 1; + } + ACE_ENDTRY; + return 0; //successful config +} + +template <class SCHED_STRAT> int +ECConfig<SCHED_STRAT>::run (void) +{ + ACE_DEBUG ((LM_DEBUG, "Running ECConfig\n")); + if (!this->configured) { + ACE_DEBUG ((LM_DEBUG, "Tried to run before configured\n")); + return 1; + } + + ACE_TRY + { + RtecEventComm::EventSet event (1); + event.length (1); + + ACE_Array<int> evt_counts(this->testcfgs.size()); + for(size_t i=0; i<this->testcfgs.size(); ++i) + { + //copy over total number of events per test_config_t to send + evt_counts[i] = this->testcfgs[i]->num_entities; + } + + size_t num_done = 0; //total number of testcfgs which have no more events to push + while (num_done<this->testcfgs.size()) + { + //for each consumer, push an event + for(size_t i=0; i<this->testcfgs.size() && i<this->consumer_proxys.size(); ++i) + { + if (evt_counts[i]<=0) + { + if (evt_counts[i]==0) + { + //just finished + ++num_done; + evt_counts[i]--; //indicate accounted for in num_done + } //else already incr num_done for this one + continue; //no more events of this to push + } //else... + test_config_t *tcfg = this->testcfgs[i]; + ProxyList::TYPE curproxy = this->consumer_proxys[i]; + + event[0].header.type = ACE_ES_EVENT_UNDEFINED+tcfg->type; + event[0].header.source = supplier_ids[i]; + event[0].header.ttl = 1; + + curproxy->push (event ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + //event pushed, so decr corresponding evt_count + evt_counts[i]--; + + // BT TODO sleep until next period expires + ACE_Time_Value rate (0, 10000); + ACE_OS::sleep (rate); + + } + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ECConfig"); + return 1; + } + ACE_ENDTRY; + + return 0; //successful run +} + +template <class SCHED_STRAT> int +ECConfig<SCHED_STRAT>::initEC() +{ + TAO_EC_Kokyu_Factory::init_svcs (); + + ACE_DEBUG ((LM_DEBUG, "Initializing event channel\n")); + ACE_TRY + { + // ORB initialization boiler plate... + int argc = 0; + char** argv = 0; + this->orb = + CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CORBA::Object_var object = + orb->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + this->poa = + PortableServer::POA::_narrow (object.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + this->poa_manager = + poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + // DO these need to remain in scope beyond this function? + + // Create a scheduling service + ACE_NEW_RETURN (this->sched_impl,SCHED_STRAT,1); + + this->scheduler = sched_impl->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Create an event channel implementation... + TAO_EC_Event_Channel_Attributes attributes (poa.in (), + poa.in ()); + attributes.scheduler = scheduler.in (); // no need to dup + + ACE_NEW_RETURN (this->ec_impl,TAO_EC_Event_Channel (attributes),1); + + this->event_channel = + this->ec_impl->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ECConfig"); + return 1; + } + ACE_ENDTRY; + + return 0; +} + +template <class SCHED_STRAT> int +ECConfig<SCHED_STRAT>::connectConsumers() +{ + ACE_TRY + { + // The canonical protocol to connect to the EC + RtecEventChannelAdmin::ConsumerAdmin_var consumer_admin = + this->event_channel->for_consumers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "connecting consumers\n")); + for (size_t i=0; i<this->consumer_cfgs.size() && i<this->testcfgs.size(); ++i) + { + ACE_NEW_RETURN(this->consumers[i],Consumer(i),1); + + RtecScheduler::handle_t hndl = this->consumer_cfgs[i]; + test_config_t *tcfg = this->testcfgs[i]; + + ACE_ConsumerQOS_Factory consumer_qos; + //consumer_qos.start_disjunction_group (); + // The types in the range [0,ACE_ES_EVENT_UNDEFINED) are + // reserved for the EC... + consumer_qos.insert_type (ACE_ES_EVENT_UNDEFINED+tcfg->type, + hndl); + + RtecEventChannelAdmin::ProxyPushSupplier_var supplier_proxy = + consumer_admin->obtain_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventComm::PushConsumer_var consumerv = + consumers[i]->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + supplier_proxy->connect_push_consumer (consumerv.in (), + consumer_qos.get_ConsumerQOS () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ECConfig"); + return 1; + } + ACE_ENDTRY; + + return 0; //successful run +} + +template <class SCHED_STRAT> int +ECConfig<SCHED_STRAT>::connectSuppliers() +{ + ACE_TRY + { + // The canonical protocol to connect to the EC + RtecEventChannelAdmin::SupplierAdmin_var supplier_admin = + event_channel->for_suppliers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "connecting suppliers\n")); + supplier_ids.size(supplier_cfgs.size()); + consumer_proxys.size(supplier_cfgs.size()); + for (size_t i=0; i<supplier_cfgs.size() && i<this->testcfgs.size(); ++i) + { + ACE_NEW_RETURN(this->suppliers[i],Supplier(),1); + + RtecScheduler::handle_t hndl = this->supplier_cfgs[i]; + test_config_t *tcfg = this->testcfgs[i]; + + RtecEventComm::EventSourceID supplier_id = i; + this->supplier_ids[i] = supplier_id; + + ACE_SupplierQOS_Factory supplier_qos; + supplier_qos.insert (supplier_id, + ACE_ES_EVENT_UNDEFINED+tcfg->type, + hndl, + 1); // number of calls, but what does that mean? + + consumer_proxys[i] = + supplier_admin->obtain_push_consumer (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventComm::PushSupplier_var supplier = + suppliers[i]->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + //PROBLEM: Occasional segfault here: + consumer_proxys[i]->connect_push_supplier (supplier.in (), + supplier_qos.get_SupplierQOS () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + + ACE_DEBUG ((LM_DEBUG, "suppliers connected\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ECConfig"); + return 1; + } + ACE_ENDTRY; + + return 0; +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::print_RT_Infos (ACE_Array<RtecScheduler::handle_t> cfg_set) +{ + char *rt_info_format = "{%20s, %10d, %10d, %10d, " + "%10d, %10d, " + "(RtecScheduler::Criticality_t) %d, " + "(RtecScheduler::Importance_t) %d, " + "%10d, %10d, %10d, %10d, %10d, " + "(RtecScheduler::Info_Type_t) %d }"; + ACE_TRY + { + for (size_t i=0; i<cfg_set.size(); ++i) { + RtecScheduler::handle_t hndl = cfg_set[i]; + RtecScheduler::RT_Info info = *(this->scheduler->get(hndl)); + ACE_TRY_CHECK; + + if (i!=0) + { + //finish previous line + ACE_DEBUG ((LM_DEBUG, "\n")); + } + ACE_DEBUG ((LM_DEBUG, rt_info_format, + (const char *) info.entry_point, + info.handle, + ACE_CU64_TO_CU32 (info.worst_case_execution_time), + ACE_CU64_TO_CU32 (info.typical_execution_time), + ACE_CU64_TO_CU32 (info.cached_execution_time), + info.period, + info.criticality, + info.importance, + ACE_CU64_TO_CU32 (info.quantum), + info.threads, + info.priority, + info.preemption_subpriority, + info.preemption_priority, + info.info_type)); + } + //finish last line + ACE_DEBUG ((LM_DEBUG, "\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ECConfig"); + } + ACE_ENDTRY; + +} + +} /* namespace TestConfig */ + +#endif /* ECCONFIG_C */ diff --git a/TAO/orbsvcs/tests/EC_Config/ECConfig.h b/TAO/orbsvcs/tests/EC_Config/ECConfig.h new file mode 100644 index 00000000000..365943b7bcb --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/ECConfig.h @@ -0,0 +1,127 @@ +/* -*- C++ -*- */ +// $Id$ +// +// ============================================================================ +// +// = FILENAME +// ECConfig +// +// = AUTHOR +// Bryan Thrall (thrall@cse.wustl.edu) +// +// ============================================================================ + +#ifndef ECCONFIG_H +#define ECCONFIG_H + +#include "ace/Array.h" +#include "ace/Synch.h" +#include "orbsvcs/RtecSchedulerS.h" //for POA_RtecScheduler +#include "orbsvcs/RtecSchedulerC.h" +#include "orbsvcs/RtecEventChannelAdminC.h" +#include "orbsvcs/Event/EC_Event_Channel.h" + +#include "TestConfig.h" +#include "Consumer.h" +#include "Supplier.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +namespace TestConfig { + +typedef ACE_Array<RtecEventChannelAdmin::ProxyPushConsumer_var> ProxyList; +typedef ACE_Array<RtecScheduler::handle_t> ConfigList; +typedef ACE_Array<RtecEventComm::EventSourceID> SupplierIDList; + +typedef ACE_Array<Consumer*> ConsumerList; +typedef ACE_Array<Supplier*> SupplierList; + +template <class SCHED_STRAT> +class ECConfig : public Test_Config { +public: + ECConfig (void); + + virtual ~ECConfig (void); + + virtual int configure (TCFG_SET_WPTR configs); + //does not take ownership of the Test_Config_Set but + //needs to use the test_config_t in that set until + //the ECConfig goes out of scope + + virtual int run (void); + //If we try to distinguish between final-push and final-receipt, + //that might be tracked in the Consumer (which would be easy as long + //as filtering and correlation isn't used -- in that case, there + //might be more than one receiver of an event, so you might get + //multiple receipt-notices). There could also be a race-condition + //problem between the various threads when reporting the receipt of + //events. + +protected: + virtual int initEC (void); + + virtual int connectConsumers (void); + + virtual int connectSuppliers (void); + + virtual void reset (void); + // + +private: + + void print_RT_Infos (ACE_Array<RtecScheduler::handle_t> cfg_set); + + Test_Config_Set testcfgs; + //copy of the currently configured Test_Config_Set + //using the same test_config_t objects + + CORBA::ORB_var orb; + + PortableServer::POA_var poa; + + PortableServer::POAManager_var poa_manager; + + RtecEventChannelAdmin::EventChannel_var event_channel; + + RtecScheduler::Scheduler_var scheduler; + /* + ACE_Strong_Bound_Ptr<TAO_EC_Event_Channel,ACE_Null_Mutex> ec_impl; + + ACE_Strong_Bound_Ptr<POA_RtecScheduler::Scheduler,ACE_Null_Mutex> sched_impl; + */ + TAO_EC_Event_Channel *ec_impl; + + POA_RtecScheduler::Scheduler *sched_impl; + + ProxyList consumer_proxys; + //proxy objects for pushing events to consumers + + ConfigList supplier_cfgs; + //RT_Infos generated by configure() for suppliers. + + ConfigList consumer_cfgs; + //RT_Infos generated by configure() for consumers. + + SupplierIDList supplier_ids; + //IDs of the suppliers + + ConsumerList consumers; + + SupplierList suppliers; + + bool configured; +}; + +} /* namespace TestConfig */ + +#if defined (ACE_TEMPLATES_REQUIRE_SOURCE) +#include "ECConfig.cpp" +#endif /* ACE_TEMPLATES_REQUIRE_SOURCE */ + +#if defined (ACE_TEMPLATES_REQUIRE_PRAGMA) +#pragma implementation ("ECConfig.cpp") +#endif /* ACE_TEMPLATES_REQUIRE_PRAGMA */ + +#endif /* ECCONFIG_H */ diff --git a/TAO/orbsvcs/tests/EC_Config/Makefile b/TAO/orbsvcs/tests/EC_Config/Makefile new file mode 100644 index 00000000000..9bf027a7b07 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Makefile @@ -0,0 +1,69 @@ +#---------------------------------------------------------------------------- +# +# $Id$ +# +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Local macros +#---------------------------------------------------------------------------- + +ifndef TAO_ROOT + TAO_ROOT = $(ACE_ROOT)/TAO +endif # ! TAO_ROOT + +BIN2 = Test + +#### If the orbsvcs library wasn't built with all components, don't +#### try to build certain tests. +TAO_ORBSVCS := $(shell sh $(ACE_ROOT)/bin/ace_components --orbsvcs) +ifeq (Event,$(findstring Event,$(TAO_ORBSVCS))) + ifeq (Sched,$(findstring Sched,$(TAO_ORBSVCS))) + BIN = $(BIN2) + endif # Sched +endif # Event + +PSRC= Test.cpp Supplier.cpp Consumer.cpp ECConfig.cpp Service.cpp Config_Factory.cpp Test_Handler.cpp +LDLIBS = -lTAO_RTOLDEvent -lTAO_RTEvent -lTAO_RTSched -lTAO_CosNaming -lTAO_Svc_Utils -lTAO_IORTable -lTAO_Messaging -lTAO_PortableServer -lTAO -lTAO_RTKokyuEvent -lACEXML_Parser + +# The complete path to orbsvcs/orbsvcs/Sched is required for DU/CXX +# automatic template instantiation magic. +CPPFLAGS += -I$(TAO_ROOT) -I$(TAO_ROOT)/orbsvcs \ + -I$(TAO_ROOT)/orbsvcs/orbsvcs/Sched \ + $(foreach svc, $(TAO_ORBSVCS), -DTAO_ORBSVCS_HAS_$(svc)) + +Test_OBJS=$(addsuffix .o, Test Supplier Consumer ECConfig Config_Factory Test_Handler) +Service_OBJS=$(addsuffix .o, Service Supplier Consumer ECConfig) + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +include $(ACE_ROOT)/include/makeinclude/wrapper_macros.GNU +include $(ACE_ROOT)/include/makeinclude/macros.GNU +include $(TAO_ROOT)/rules.tao.GNU +include $(ACE_ROOT)/include/makeinclude/rules.common.GNU +include $(ACE_ROOT)/include/makeinclude/rules.nonested.GNU +include $(ACE_ROOT)/include/makeinclude/rules.local.GNU + +# To build multiple executables in the same directory on AIX, it works +# best to wipe out any previously-created tempinc directory. +# The compiler/linker isn't too smart about instantiating templates... +ifdef TEMPINCDIR +COMPILE.cc := $(RM) -rf tempinc; $(COMPILE.cc) +endif + +#---------------------------------------------------------------------------- +# Local targets +#---------------------------------------------------------------------------- + +Test: $(addprefix $(VDIR),$(Test_OBJS)) + $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK) + +Service: $(addprefix $(VDIR),$(Service_OBJS)) + $(LINK.cc) $(LDFLAGS) -o $@ $^ $(VLDLIBS) $(POSTLINK) + +#---------------------------------------------------------------------------- +# Dependencies +#---------------------------------------------------------------------------- +# DO NOT DELETE THIS LINE -- g++dep uses it. diff --git a/TAO/orbsvcs/tests/EC_Config/Schedule.h b/TAO/orbsvcs/tests/EC_Config/Schedule.h new file mode 100644 index 00000000000..55fab809258 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Schedule.h @@ -0,0 +1,42 @@ +// $Id$ + +// This file was automatically generated by the Scheduler_Factory. +// Before editing the file please consider generating it again. + +#include "orbsvcs/Scheduler_Factory.h" + + +// There were no scheduling anomalies. + + +static ACE_Scheduler_Factory::POD_RT_Info infos[] = { +{"Dispatching_Task-250000.us", 1, 0, 0, 0, 250000, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 1, 58, 4, 1, (RtecScheduler::Info_Type_t) 0 }, +{"Dispatching_Task-500000.us", 2, 0, 0, 0, 500000, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 1, 58, 5, 1, (RtecScheduler::Info_Type_t) 0 }, +{"Dispatching_Task-1000000.us", 3, 0, 0, 0, 1000000, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 1, 58, 6, 1, (RtecScheduler::Info_Type_t) 0 }, +{"Dispatching_Task-2000000.us", 4, 0, 0, 0, 2000000, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 1, 58, 7, 1, (RtecScheduler::Info_Type_t) 0 }, +{"Dispatching_Task-10000000.us", 5, 0, 0, 0, 10000000, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 1, 58, 8, 1, (RtecScheduler::Info_Type_t) 0 }, +{ "consumer_event_1", 6, 20000, 20000, 20000, 0, (RtecScheduler::Criticality_t) 4, (RtecScheduler::Importance_t) 0, 20000, 0, 59, 0, 0, (RtecScheduler::Info_Type_t) 0 }, +{ "consumer_event_2", 7, 10000, 10000, 10000, 0, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 10000, 0, 58, 1, 1, (RtecScheduler::Info_Type_t) 0 }, +{"(consumer_event_1#rep||consumer_event_2#rep)", 8, 0, 0, 0, 0, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 0, 58, 3, 1, (RtecScheduler::Info_Type_t) 2 }, +{"consumer_event_1#rep", 9, 0, 0, 0, 0, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 0, 58, 0, 1, (RtecScheduler::Info_Type_t) 0 }, +{"consumer_event_2#rep", 10, 0, 0, 0, 0, (RtecScheduler::Criticality_t) 0, (RtecScheduler::Importance_t) 0, 0, 0, 58, 2, 1, (RtecScheduler::Info_Type_t) 0 }, +{ "supplier_event_1", 11, 0, 0, 0, 100000, (RtecScheduler::Criticality_t) 4, (RtecScheduler::Importance_t) 0, 0, 1, 59, 1, 0, (RtecScheduler::Info_Type_t) 0 }, +{ "supplier_event_2", 12, 0, 0, 0, 200000, (RtecScheduler::Criticality_t) 4, (RtecScheduler::Importance_t) 0, 0, 1, 59, 2, 0, (RtecScheduler::Info_Type_t) 0 } +}; + +static int infos_size = sizeof(infos)/sizeof(infos[0]); + + +static ACE_Scheduler_Factory::POD_Config_Info configs[] = { + { 0, 59, (RtecScheduler::Dispatching_Type_t) 2 }, + { 1, 58, (RtecScheduler::Dispatching_Type_t) 2 } +}; + +static int configs_size = sizeof(configs)/sizeof(configs[0]); + + +// This sets up Scheduler_Factory to use the runtime version. +int scheduler_factory_setup = + ACE_Scheduler_Factory::use_runtime (configs_size, configs, infos_size, infos); + +// EOF diff --git a/TAO/orbsvcs/tests/EC_Config/Service.cpp b/TAO/orbsvcs/tests/EC_Config/Service.cpp new file mode 100644 index 00000000000..cf9926708a9 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Service.cpp @@ -0,0 +1,531 @@ +// $Id$ + +#include "orbsvcs/Sched/Reconfig_Scheduler.h" +#include "orbsvcs/Runtime_Scheduler.h" +#include "orbsvcs/Event/Module_Factory.h" +#include "orbsvcs/Event_Service_Constants.h" +#include "orbsvcs/Event_Utilities.h" +#include "orbsvcs/Event/EC_Event_Channel.h" +#include "orbsvcs/Event/EC_Default_Factory.h" +#include "orbsvcs/Event/EC_Kokyu_Factory.h" +#include "Consumer.h" +#include "Supplier.h" + +#include "Schedule.h" + +#include "ace/Get_Opt.h" +#include "ace/Sched_Params.h" +#include "ace/Auto_Ptr.h" + +ACE_RCSID(EC_Examples, Service, "$Id$") + +#define EVENT1TYPE ACE_ES_EVENT_UNDEFINED +#define EVENT2TYPE ACE_ES_EVENT_UNDEFINED+1 + +int config_run = 0; + +int parse_args (int argc, char *argv[]); + +typedef TAO_Reconfig_Scheduler<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> MUF_SCHED_TYPE; + +int +main (int argc, char* argv[]) +{ + TAO_EC_Kokyu_Factory::init_svcs (); + + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + // ORB initialization boiler plate... + CORBA::ORB_var orb = + CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + if (parse_args (argc, argv) == -1) + { + ACE_ERROR ((LM_ERROR, + "Usage: Service [-o IOR_file_name]\n")); + return 1; + } + + CORBA::Object_var object = + orb->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + PortableServer::POA_var poa = + PortableServer::POA::_narrow (object.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + PortableServer::POAManager_var poa_manager = + poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + // **************************************************************** + +#if 0 + // Obtain a reference to the naming service... + CORBA::Object_var naming_obj = + orb->resolve_initial_references ("NameService" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + CosNaming::NamingContext_var naming_context = + CosNaming::NamingContext::_narrow (naming_obj.in () ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#endif /* 0 */ + + // **************************************************************** + + // Create an scheduling service + POA_RtecScheduler::Scheduler* sched_impl = 0; + if (config_run) + { + ACE_NEW_RETURN (sched_impl, + MUF_SCHED_TYPE, + 1); + } + else + { + ACE_NEW_RETURN (sched_impl, + MUF_SCHED_TYPE (configs_size, + configs, + infos_size, + infos, + 0, 0, + 0), + 1); + } + + RtecScheduler::Scheduler_var scheduler = + sched_impl->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + +#if 0 + // Bind the scheduler with the naming service so clients + // (consumers and suppliers) can resolve it, some (old) + // implementations of the EC will try to do the same thing + // (yikes!) + CosNaming::Name schedule_name (1); + schedule_name.length (1); + schedule_name[0].id = CORBA::string_dup ("ScheduleService"); + // Register the servant with the Naming Context.... + naming_context->rebind (schedule_name, scheduler.in () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; +#endif /* 0 */ + + // **************************************************************** + +#if 0 + // Create an event channel implementation... + TAO_Default_Module_Factory module_factory; + ACE_EventChannel event_channel_impl (scheduler.in (), + 1, + ACE_DEFAULT_EVENT_CHANNEL_TYPE, + &module_factory); + + RtecEventChannelAdmin::EventChannel_var event_channel = + event_channel_impl._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; +#else + + TAO_EC_Event_Channel_Attributes attributes (poa.in (), + poa.in ()); + attributes.scheduler = scheduler.in (); // no need to dup + + TAO_EC_Event_Channel ec_impl (attributes); + + RtecEventChannelAdmin::EventChannel_var event_channel = + ec_impl._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; +#endif /* 0 */ + + // **************************************************************** + + // Create consumers, intialize their RT_Info structures, and + // connect to the event channel.... + + Consumer consumer_high(0),consumer_low(1); + + /* + There is 1 HIGH criticality event and one LOW criticality + event. The period of the LOW event will vary each run to + push events at a certain rate. The idea is to measure + the effect of greater LOW throughput on the HIGH throughput. + */ + + RtecScheduler::handle_t consumer_rt_info_hi = scheduler->create ("Consumer Event Class 0" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + RtecScheduler::handle_t consumer_rt_info_lo = scheduler->create ("Consumer Event Class 1" ACE_ENV_ARG_PARAMETER); + + // Let's say that the execution time for the HIGH event is 1 + // milliseconds... + ACE_Time_Value tv (0, 1000); + TimeBase::TimeT time; + ORBSVCS_Time::Time_Value_to_TimeT (time, tv); + scheduler->set (consumer_rt_info_hi, + RtecScheduler::HIGH_CRITICALITY, + time, time, time, + time, + RtecScheduler::VERY_LOW_IMPORTANCE, + time, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The execution time and period of the LOW event is set by + // command line... + tv.set (0, 2000); + ORBSVCS_Time::Time_Value_to_TimeT (time, tv); + scheduler->set (consumer_rt_info_lo, + RtecScheduler::LOW_CRITICALITY, + time, time, time, + time, + RtecScheduler::VERY_LOW_IMPORTANCE, + time, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_ConsumerQOS_Factory consumer_qos1, consumer_qos2; + //consumer_qos.start_disjunction_group (); + // The types in the range [0,ACE_ES_EVENT_UNDEFINED) are + // reserved for the EC... + consumer_qos1.insert_type (EVENT1TYPE, + consumer_rt_info_hi); + consumer_qos2.insert_type (EVENT2TYPE, + consumer_rt_info_lo); + + // The canonical protocol to connect to the EC + RtecEventChannelAdmin::ConsumerAdmin_var consumer_admin = + event_channel->for_consumers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventChannelAdmin::ProxyPushSupplier_var supplier_proxy1 = + consumer_admin->obtain_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventChannelAdmin::ProxyPushSupplier_var supplier_proxy2 = + consumer_admin->obtain_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventComm::PushConsumer_var consumer1 = + consumer_high._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventComm::PushConsumer_var consumer2 = + consumer_low._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "connecting consumers\n")); + supplier_proxy1->connect_push_consumer (consumer1.in (), + consumer_qos1.get_ConsumerQOS () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + supplier_proxy2->connect_push_consumer (consumer2.in (), + consumer_qos2.get_ConsumerQOS () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "consumers connected\n")); + + // **************************************************************** + + Supplier supplier_impl1, supplier_impl2; + + RtecScheduler::handle_t supplier_rt_info1 = + scheduler->create ("Supplier Event Class 0" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The execution times are set to reasonable values, but + // actually they are changed on the real execution, i.e. we + // lie to the scheduler to obtain right priorities; but we + // don't care if the set is schedulable. + tv.set (0, 1000); + TimeBase::TimeT tmp; + ORBSVCS_Time::Time_Value_to_TimeT (tmp, tv); + RtecScheduler::Period_t rate = ACE_U64_TO_U32(tmp); + + scheduler->set (supplier_rt_info1, + RtecScheduler::HIGH_CRITICALITY, + tmp, tmp, tmp, + tmp, + RtecScheduler::VERY_LOW_IMPORTANCE, + tmp, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecScheduler::handle_t supplier_rt_info2 = + scheduler->create ("Supplier Event Class 1" ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // The execution times are set to reasonable values, but + // actually they are changed on the real execution, i.e. we + // lie to the scheduler to obtain right priorities; but we + // don't care if the set is schedulable. + tv.set (0, 2000); + ORBSVCS_Time::Time_Value_to_TimeT (tmp, tv); + rate = ACE_U64_TO_U32(tmp); + + scheduler->set (supplier_rt_info2, + RtecScheduler::LOW_CRITICALITY, + tmp, tmp, tmp, + tmp, + RtecScheduler::VERY_LOW_IMPORTANCE, + tmp, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventComm::EventSourceID supplier_id1 = 1, supplier_id2 = 2; + ACE_SupplierQOS_Factory supplier_qos1, supplier_qos2; + supplier_qos1.insert (supplier_id1, + EVENT1TYPE, + supplier_rt_info1, + 1); // number of calls, but what does that mean? + supplier_qos2.insert (supplier_id2, + EVENT2TYPE, + supplier_rt_info2, + 1); // number of calls, but what does that mean? + + // The canonical protocol to connect to the EC + RtecEventChannelAdmin::SupplierAdmin_var supplier_admin = + event_channel->for_suppliers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventChannelAdmin::ProxyPushConsumer_var consumer_proxy1 = + supplier_admin->obtain_push_consumer (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventChannelAdmin::ProxyPushConsumer_var consumer_proxy2 = + supplier_admin->obtain_push_consumer (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventComm::PushSupplier_var supplier1 = + supplier_impl1._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + RtecEventComm::PushSupplier_var supplier2 = + supplier_impl2._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "connecting suppliers\n")); + consumer_proxy1->connect_push_supplier (supplier1.in (), + supplier_qos1.get_SupplierQOS () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + consumer_proxy2->connect_push_supplier (supplier2.in (), + supplier_qos2.get_SupplierQOS () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + ACE_DEBUG ((LM_DEBUG, "suppliers connected\n")); + + // **************************************************************** + + // At this point the consumer and supplier are connected to the + // EC, they have provided their QoS info to the Scheduling + // Service and the EC has informed the Scheduler about the + // dependencies between them. + // We can now compute the schedule for this configuration... + + // The schedule is returned in this variables.... + + if (config_run) + { + ACE_DEBUG ((LM_DEBUG, "Computing schedule\n")); + RtecScheduler::RT_Info_Set_var infos; + RtecScheduler::Config_Info_Set_var configs; + RtecScheduler::Scheduling_Anomaly_Set_var anomalies; + + // Obtain the range of valid priorities in the current + // platform, the scheduler hard-code this values in the + // generated file, but in the future we may just use the + // "logical" priorities and define the mapping to OS + // priorities at run-time. + int min_os_priority = + ACE_Sched_Params::priority_min (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD); + int max_os_priority = + ACE_Sched_Params::priority_max (ACE_SCHED_FIFO, + ACE_SCOPE_THREAD); + scheduler->compute_scheduling (min_os_priority, + max_os_priority, + infos.out (), + configs.out (), + anomalies.out () + ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + + // Dump the schedule to a file.. + ACE_Scheduler_Factory::dump_schedule (infos.in (), + configs.in (), + anomalies.in (), + "schedule.out"); + } + + // **************************************************************** + + ACE_DEBUG ((LM_DEBUG, "activating EC\n")); + ec_impl.activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_TRY_CHECK; + ACE_DEBUG ((LM_DEBUG, "EC activated\n")); + + ACE_DEBUG ((LM_DEBUG, "Pushing events\n")); + + // Generate a few events.... + + RtecEventComm::EventSet event1 (1); + event1.length (1); + event1[0].header.type = EVENT1TYPE; + event1[0].header.source = supplier_id1; + event1[0].header.ttl = 1; + + RtecEventComm::EventSet event2 (1); + event2.length (1); + event2[0].header.type = EVENT2TYPE; + event2[0].header.source = supplier_id2; + event2[0].header.ttl = 1; + + for (int i=0; i!=20;++i) + { + if (i%2 == 0) + { + consumer_proxy1->push (event1 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + else if (i%2 == 1) + { + consumer_proxy2->push (event2 ACE_ENV_ARG_PARAMETER); + ACE_TRY_CHECK; + } + ACE_Time_Value rate (0, 10000); + ACE_OS::sleep (rate); + } + + // **************************************************************** + + // We should do a lot of cleanup (disconnect from the EC, + // deactivate all the objects with the POA, etc.) but this is + // just a simple demo so we are going to be lazy. + + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "Service"); + return 1; + } + ACE_ENDTRY; + return 0; +} + +// **************************************************************** + +int parse_args (int argc, char *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, "c"); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'c': + config_run = 1; + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-c (config run) " + "\n", + argv [0]), + -1); + } + // Indicates sucessful parsing of the command line + return 0; +} + +// **************************************************************** + +// Instantiate the templates used by the Reconfig scheduler above + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +template class auto_ptr<RtecScheduler::Config_Info>; +template class auto_ptr<RtecScheduler::RT_Info>; +template class auto_ptr<TAO_Reconfig_Scheduler_Entry>; +template class ACE_Auto_Basic_Ptr<RtecScheduler::Config_Info>; +template class ACE_Auto_Basic_Ptr<RtecScheduler::RT_Info>; +template class ACE_Auto_Basic_Ptr<TAO_Reconfig_Scheduler_Entry>; +template class ACE_Hash_Map_Manager_Ex<int, RtecScheduler::Config_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Manager_Ex<int, RtecScheduler::Dependency_Set *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Manager_Ex<int, RtecScheduler::RT_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Iterator_Base_Ex<int, RtecScheduler::Config_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Iterator_Base_Ex<int, RtecScheduler::Dependency_Set *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Iterator_Base_Ex<int, RtecScheduler::RT_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Iterator_Ex<int,RtecScheduler::Config_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Iterator_Ex<int,RtecScheduler::Dependency_Set*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Iterator_Ex<int,RtecScheduler::RT_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<int,RtecScheduler::Config_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<int,RtecScheduler::Dependency_Set*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Reverse_Iterator_Ex<int,RtecScheduler::RT_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX>; +template class ACE_Hash_Map_Entry<int, RtecScheduler::Config_Info *>; +template class ACE_Hash_Map_Entry<int, RtecScheduler::Dependency_Set *>; +template class ACE_Hash_Map_Entry<int, RtecScheduler::RT_Info *>; +template class ACE_RB_Tree<const char *, RtecScheduler::RT_Info *, ACE_Less_Than<const char *>, TAO_SYNCH_MUTEX>; +template class ACE_RB_Tree_Node<const char *, RtecScheduler::RT_Info *>; +template class ACE_RB_Tree_Iterator<const char *, RtecScheduler::RT_Info *, ACE_Less_Than<const char *>, TAO_SYNCH_MUTEX>; +template class ACE_RB_Tree_Iterator_Base<char const *, RtecScheduler::RT_Info *, ACE_Less_Than<char const *>, TAO_SYNCH_MUTEX>; +template class ACE_RB_Tree_Reverse_Iterator<const char *, RtecScheduler::RT_Info *, ACE_Less_Than<const char *>, TAO_SYNCH_MUTEX>; +template class TAO_Reconfig_Scheduler<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX>; +template class TAO_RSE_Dependency_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX>; +template class TAO_RSE_DFS_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX>; +template class TAO_RSE_Priority_Visitor<TAO_MUF_Reconfig_Sched_Strategy>; +template class TAO_RSE_Propagation_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX>; +template class TAO_RSE_SCC_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX>; +template class TAO_RSE_Utilization_Visitor<TAO_MUF_Reconfig_Sched_Strategy>; + +#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) + +#pragma instantiate auto_ptr<RtecScheduler::Config_Info> +#pragma instantiate auto_ptr<RtecScheduler::RT_Info> +#pragma instantiate auto_ptr<TAO_Reconfig_Scheduler_Entry> +#pragma instantiate ACE_Auto_Basic_Ptr<RtecScheduler::Config_Info> +#pragma instantiate ACE_Auto_Basic_Ptr<RtecScheduler::RT_Info> +#pragma instantiate ACE_Auto_Basic_Ptr<TAO_Reconfig_Scheduler_Entry> +#pragma instantiate ACE_Hash_Map_Manager_Ex<int, RtecScheduler::Config_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Manager_Ex<int, RtecScheduler::Dependency_Set *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Manager_Ex<int, RtecScheduler::RT_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<int, RtecScheduler::Config_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<int, RtecScheduler::Dependency_Set *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Iterator_Base_Ex<int, RtecScheduler::RT_Info *, ACE_Hash<int>, ACE_Equal_To<int>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<int,RtecScheduler::Config_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<int,RtecScheduler::Dependency_Set*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Iterator_Ex<int,RtecScheduler::RT_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<int,RtecScheduler::Config_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<int,RtecScheduler::Dependency_Set*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Reverse_Iterator_Ex<int,RtecScheduler::RT_Info*,ACE_Hash<int>,ACE_Equal_To<int>,TAO_SYNCH_MUTEX> +#pragma instantiate ACE_Hash_Map_Entry<int, RtecScheduler::Config_Info *> +#pragma instantiate ACE_Hash_Map_Entry<int, RtecScheduler::Dependency_Set *> +#pragma instantiate ACE_Hash_Map_Entry<int, RtecScheduler::RT_Info *> +#pragma instantiate ACE_RB_Tree<const char *, RtecScheduler::RT_Info *, ACE_Less_Than<const char *>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_RB_Tree_Node<const char *, RtecScheduler::RT_Info *> +#pragma instantiate ACE_RB_Tree_Iterator<const char *, RtecScheduler::RT_Info *, ACE_Less_Than<const char *>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_RB_Tree_Iterator_Base<char const *, RtecScheduler::RT_Info *, ACE_Less_Than<char const *>, TAO_SYNCH_MUTEX> +#pragma instantiate ACE_RB_Tree_Reverse_Iterator<const char *, RtecScheduler::RT_Info *, ACE_Less_Than<const char *>, TAO_SYNCH_MUTEX> +#pragma instantiate TAO_Reconfig_Scheduler<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> +#pragma instantiate TAO_RSE_Dependency_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> +#pragma instantiate TAO_RSE_DFS_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> +#pragma instantiate TAO_RSE_Priority_Visitor<TAO_MUF_Reconfig_Sched_Strategy> +#pragma instantiate TAO_RSE_Propagation_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> +#pragma instantiate TAO_RSE_SCC_Visitor<TAO_MUF_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> +#pragma instantiate TAO_RSE_Utilization_Visitor<TAO_MUF_Reconfig_Sched_Strategy> + +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/EC_Config/Supplier.cpp b/TAO/orbsvcs/tests/EC_Config/Supplier.cpp new file mode 100644 index 00000000000..badc65b011d --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Supplier.cpp @@ -0,0 +1,21 @@ +// $Id$ + +#include "Supplier.h" + +ACE_RCSID(EC_Examples, Supplier, "$Id$") + +Supplier::Supplier (void) +{ +} + +void +Supplier::disconnect_push_supplier (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +// **************************************************************** + +#if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION) +#elif defined(ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA) +#endif /* ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION */ diff --git a/TAO/orbsvcs/tests/EC_Config/Supplier.h b/TAO/orbsvcs/tests/EC_Config/Supplier.h new file mode 100644 index 00000000000..b0391f7602b --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Supplier.h @@ -0,0 +1,54 @@ +/* -*- C++ -*- */ +// $Id$ +// +// ============================================================================ +// +// = LIBRARY +// ORBSVCS Real-time Event Channel examples +// +// = FILENAME +// Supplier +// +// = AUTHOR +// Carlos O'Ryan (coryan@cs.wustl.edu) +// +// ============================================================================ + +#ifndef SUPPLIER_H +#define SUPPLIER_H + +#include "orbsvcs/RtecEventCommS.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class Supplier : public POA_RtecEventComm::PushSupplier +{ + // = TITLE + // Simple supplier object + // + // = DESCRIPTION + // This class is a supplier of events. + // It simply register for two event typesone event type + // The class is just a helper to simplify common tasks in EC + // tests, such as subscribing for a range of events, disconnecting + // from the EC, informing the driver of shutdown messages, etc. + // + // There are several ways to connect and disconnect this class, + // and it is up to the driver program to use the right one. + // +public: + Supplier (void); + // Constructor + + // = The RtecEventComm::PushSupplier methods + + virtual void disconnect_push_supplier (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)); + // The skeleton methods. + +private: +}; + +#endif /* SUPPLIER_H */ diff --git a/TAO/orbsvcs/tests/EC_Config/Test.cpp b/TAO/orbsvcs/tests/EC_Config/Test.cpp new file mode 100644 index 00000000000..cddb1b5eccd --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Test.cpp @@ -0,0 +1,109 @@ +// $Id$ + +#include "ace/Array.h" +#include "ace/Bound_Ptr.h" +#include "ace/Synch.h" +#include "ACEXML/parser/parser/Parser.h" +#include "ACEXML/common/InputSource.h" +#include "ACEXML/common/FileCharStream.h" +#include "ACEXML/common/DefaultHandler.h" + +#include "ECConfig.h" +#include "Config_Factory.h" +#include "Test_Handler.h" + +using namespace TestConfig; + +typedef ACE_Strong_Bound_Ptr<Test_Config_Set,ACE_Null_Mutex> TCFG_SET_SPTR; + +//NOTE: Read from a formatted file rather than hardcode the configuration. Check ACE_XML. + +int +main (int argc, char** argv) +{ + int retval = 0; + + ACEXML_TRY_NEW_ENV + { + ACEXML_Parser parser; + + // TODO parse args for config filename + + ACEXML_Char *filename = ACE_LIB_TEXT("test.xml"); + ACEXML_FileCharStream fcs; + if ((retval = fcs.open(filename)) != 0) { + ACE_DEBUG ((LM_DEBUG, "Could not open file %s\n",filename)); + return retval; + } + + ACEXML_InputSource is (&fcs); + + Test_Handler handler (filename); + ACEXML_DefaultHandler dflt; + + parser.setContentHandler (&handler); + parser.setDTDHandler (&dflt); + parser.setErrorHandler (&handler); + parser.setEntityResolver (&dflt); + + parser.parse(&is); + ACEXML_TRY_CHECK; + + // TODO configure according to parsed XML + } + ACEXML_CATCH (ACEXML_SAXException, ex) + { + ACE_UNUSED_ARG (ex); + ACE_DEBUG ((LM_ERROR, ACE_TEXT ("Exception occurred. Exiting...\n"))); + return 1; + } + ACEXML_ENDTRY; + +#if 0 + ConfigFactory::Default_Config_Factory fact; + fact.init(argc,argv); + + Test_Config *backend = fact.create_testconfig(); + if (0 == backend) { + ACE_DEBUG((LM_DEBUG, "Error: could not create back end!\n")); + return 1; + } + + TCFG_SET_SPTR cfg_ptr(new Test_Config_Set(2)); + + (*cfg_ptr)[0] = new test_config_t(); + (*cfg_ptr)[0]->type = 0; + (*cfg_ptr)[0]->period = 1000; + (*cfg_ptr)[0]->criticality = HIGH_CRITICALITY; + (*cfg_ptr)[0]->importance = VERY_LOW_IMPORTANCE; + (*cfg_ptr)[0]->num_entities = 10; + + (*cfg_ptr)[1] = new test_config_t(); + (*cfg_ptr)[1]->type = 1; + (*cfg_ptr)[1]->period = 2000; + (*cfg_ptr)[1]->criticality = LOW_CRITICALITY; + (*cfg_ptr)[1]->importance = VERY_LOW_IMPORTANCE; + (*cfg_ptr)[1]->num_entities = 10; + + // PROBLEM: occasional segfault on run and configure + int retval = 0; + if ((retval = backend->configure(TCFG_SET_WPTR(cfg_ptr))) != 0) { + ACE_DEBUG((LM_DEBUG, "Error configuring back end! (%d)\n",retval)); + return retval; + } + + if ((retval = backend->run()) != 0) { + ACE_DEBUG((LM_DEBUG, "Error running back end! (%d)\n",retval)); + return retval; + } + + for(size_t i=0; i<cfg_ptr->size(); ++i) { + delete (*cfg_ptr)[i]; + } + + fact.destroy_testconfig(backend); + fact.fini(); +#endif /* 0 */ + + return retval; +} diff --git a/TAO/orbsvcs/tests/EC_Config/TestConfig.h b/TAO/orbsvcs/tests/EC_Config/TestConfig.h new file mode 100644 index 00000000000..8294348537f --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/TestConfig.h @@ -0,0 +1,125 @@ +/* -*- C++ -*- */ +// $Id$ +// +// ============================================================================ +// +// = FILENAME +// TestConfig +// +// = AUTHOR +// Bryan Thrall (thrall@cse.wustl.edu) +// +// ============================================================================ + +#ifndef TESTCONFIG_H +#define TESTCONFIG_H + +#include "ace/Array.h" +#include "ace/Bound_Ptr.h" +#include "ace/Synch.h" //for ACE_Null_Mutex + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +namespace TestConfig { + +struct test_config_t; +typedef ACE_Array<test_config_t*> Test_Config_Set; +typedef ACE_Weak_Bound_Ptr<Test_Config_Set,ACE_Null_Mutex> TCFG_SET_WPTR; + +// Entity_Type_t is used to distinguish different types of entities +// (such as Event Channel events and Distributable Threads). Not exactly +// an enumeration of those types, but it should take on reasonably +// distinct values for each. +typedef unsigned long Entity_Type_t; + +typedef long Period_t; + +enum Criticality_t { +// Defines the criticality of the entity. + VERY_LOW_CRITICALITY, + LOW_CRITICALITY, + MEDIUM_CRITICALITY, + HIGH_CRITICALITY, + VERY_HIGH_CRITICALITY +}; + +enum Importance_t { +// Defines the importance of the entity, +// which can be used as a "tie-breaker" when +// other scheduling parameters are equal. + VERY_LOW_IMPORTANCE, + LOW_IMPORTANCE, + MEDIUM_IMPORTANCE, + HIGH_IMPORTANCE, + VERY_HIGH_IMPORTANCE +}; + + +struct test_config_t +// = TITLE +// Test configuration information for the back-end. +// +// = DESCRIPTION +// The QoS and number of tasks for each +// test "entity" described by the following +// information. +{ + // The entity type should uniquely identify the + // set of entities configured by this struct. + Entity_Type_t type; + + // This expresses the rate at which entities are + // pushed. + Period_t period; + + // Entity Criticality (user assigned significance). + Criticality_t criticality; + + // Entity importance, used to "break ties". + Importance_t importance; + + // Number of entities to push through the back-end. This is + // effectively a termination condition for the test, since it will + // terminate once all num_entities entities have been pushed for + // each test_config_t used to configure the back-end. + long num_entities; +}; + +class Test_Config { + // = TITLE + // Interface for configuring the test back-end. + // + // = DESCRIPTION + // This class provides an interface for configuring the back-end of the test. + // For example, the Event Channel might be the back-end, so an adapter + // implementing this interface would be used to configure the EC in that case. + // +public: + Test_Config (void) {}; + + virtual ~Test_Config (void) {}; + + virtual int configure (TCFG_SET_WPTR configs) = 0; + // Configures the back-end. Each test_config_t in the set specifies + // the configuration of a separate type of entity. Returns 0 when + // the configuration is successful, non-zero otherwise. An + // ACE_Weak_Bound_Ptr is used because the TestConfig might want to + // keep a pointer to the Test_Config_Set but should not take + // possession of the set (that is, control when the set is deleted). + + virtual int run (void) = 0; + // Runs the configured back-end. Returns 0 if the run encountered + // no errors, non-zero otherwise. Entities are pushed periodically + // according to their respective test_config_t's until num_entities + // are pushed of each test_config_t. + + //NOTE: It might be useful to distinguish between a run which + //returns after the last entity was pushed and one which returns + //after the last entity was received at its destination. +}; + +} /* namespace TestConfig */ + +#endif /* TESTCONFIG_H */ diff --git a/TAO/orbsvcs/tests/EC_Config/Test_Handler.cpp b/TAO/orbsvcs/tests/EC_Config/Test_Handler.cpp new file mode 100644 index 00000000000..d19d542bf46 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Test_Handler.cpp @@ -0,0 +1,204 @@ +// -*- C++ -*- $Id$ + +#include "Test_Handler.h" +#include "ace/ACE.h" +#include "ace/Log_Msg.h" + +// TODO Create test_config_t's based on XML using entities described in testconfig.dtd + +Test_Handler::Test_Handler (ACEXML_Char* fileName) + : configs_(0), + fileName_(ACE::strnew (fileName)) +{ + +} + +Test_Handler::~Test_Handler (void) +{ + delete[] this->fileName_; + + for(size_t i=0; i<configs_.size(); ++i) { + delete configs_[i]; + } +} + +const TestConfig::Test_Config_Set & +Test_Handler::get_configs (void) const +{ + return this->configs_; +} + + +void +Test_Handler::characters (const ACEXML_Char *cdata, + int start, + int end ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event characters () ** start: %d end: %d ***************\n%s\n- End event characters () ---------------\n"), + start, end, cdata)); +} + +void +Test_Handler::endDocument (ACEXML_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event endDocument () ***************\n"))); +} + +void +Test_Handler::endElement (const ACEXML_Char *uri, + const ACEXML_Char *name, + const ACEXML_Char *qName + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event endElement (%s, %s, %s) ***************\n"), + uri, name, qName)); +} + +void +Test_Handler::endPrefixMapping (const ACEXML_Char *prefix + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event endPrefixMapping (%s) ***************\n"), + prefix)); +} + +void +Test_Handler::ignorableWhitespace (const ACEXML_Char *, + int, + int + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event ignorableWhitespace () ***************\n"))); +} + +void +Test_Handler::processingInstruction (const ACEXML_Char *target, + const ACEXML_Char *data + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event processingInstruction (%s, %s) ***************\n"), + target, data)); +} + +void +Test_Handler::setDocumentLocator (ACEXML_Locator * locator) +{ + + this->locator_ = locator; + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event setDocumentLocator () ***************\n"))); +} + +void +Test_Handler::skippedEntity (const ACEXML_Char *name + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event skippedEntity (%s) ***************\n"), + name)); +} + +void +Test_Handler::startDocument (ACEXML_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event startDocument () ***************\n"))); +} + +void +Test_Handler::startElement (const ACEXML_Char *uri, + const ACEXML_Char *name, + const ACEXML_Char *qName, + ACEXML_Attributes *alist + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event startElement (%s, %s, %s) ***************\n"), + uri, name, qName)); + + if (alist != 0) + for (size_t i = 0; i < alist->getLength (); ++i) + { + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT (" %s = \"%s\"\n"), + alist->getQName (i), alist->getValue (i))); + } +} + +void +Test_Handler::startPrefixMapping (const ACEXML_Char * prefix, + const ACEXML_Char * uri ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("* Event startPrefixMapping () ***************\n"))); + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("Prefix = %s, URI = %s\n"), prefix, uri)); +} + +// Methods inherited from ACEXML_ErrorHandler. + +/* + * Receive notification of a recoverable error. + */ +void +Test_Handler::error (ACEXML_SAXParseException & ex ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + ACE_DEBUG ((LM_DEBUG, "%s:%d:%d ", this->fileName_, + this->locator_->getLineNumber(), + this->locator_->getColumnNumber())); + ex.print(); +} + +void +Test_Handler::fatalError (ACEXML_SAXParseException& ex ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + + ACE_DEBUG ((LM_DEBUG, "%s:%d:%d ", this->fileName_, + this->locator_->getLineNumber(), + this->locator_->getColumnNumber())); + ex.print(); +} + +void +Test_Handler::warning (ACEXML_SAXParseException & ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // No-op. +} diff --git a/TAO/orbsvcs/tests/EC_Config/Test_Handler.h b/TAO/orbsvcs/tests/EC_Config/Test_Handler.h new file mode 100644 index 00000000000..5c2b332a255 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/Test_Handler.h @@ -0,0 +1,168 @@ +// $Id$ + +//============================================================================= +/** + * @file Test_Handler.h + * + * $Id$ + * + * @author Bryan Thrall <thrall@cse.wustl.edu> + */ +//============================================================================= + + +#ifndef TEST_HANDLER_H +#define TEST_HANDLER_H + +#include "ACEXML/common/ContentHandler.h" +#include "ACEXML/common/ErrorHandler.h" + +#include "TestConfig.h" + +/** + * @class Test_Handler + * + * @brief Test_Handler is a SAX event handler which parses testconfig.dtd XML + * + * This SAX event handler parses XML according to testconfig.dtd, producing a + * set of test_config_t's. + */ +class Test_Handler : public ACEXML_ContentHandler, public ACEXML_ErrorHandler +{ +public: + /* + * Default constructor. + */ + Test_Handler (ACEXML_Char* fileName); + + /* + * Default destructor. + */ + virtual ~Test_Handler (void); + + /** + * Returns a reference to the Handler's internal set of + * test_config_t's. The Handler retains ownership of the + * (dynamically allocated) test_config_t's in the set. + */ + const TestConfig::Test_Config_Set &get_configs (void) const; + + // Methods inherited from ACEXML_ContentHandler. + + /* + * Receive notification of character data. + */ + virtual void characters (const ACEXML_Char *ch, + int start, + int length ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of the end of a document. + */ + virtual void endDocument (ACEXML_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of the end of an element. + */ + virtual void endElement (const ACEXML_Char *namespaceURI, + const ACEXML_Char *localName, + const ACEXML_Char *qName ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * End the scope of a prefix-URI mapping. + */ + virtual void endPrefixMapping (const ACEXML_Char *prefix ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of ignorable whitespace in element content. + */ + virtual void ignorableWhitespace (const ACEXML_Char *ch, + int start, + int length ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of a processing instruction. + */ + virtual void processingInstruction (const ACEXML_Char *target, + const ACEXML_Char *data ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive an object for locating the origin of SAX document events. + */ + virtual void setDocumentLocator (ACEXML_Locator *locator) ; + + /* + * Receive notification of a skipped entity. + */ + virtual void skippedEntity (const ACEXML_Char *name ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of the beginning of a document. + */ + virtual void startDocument (ACEXML_ENV_SINGLE_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of the beginning of an element. + */ + virtual void startElement (const ACEXML_Char *namespaceURI, + const ACEXML_Char *localName, + const ACEXML_Char *qName, + ACEXML_Attributes *atts ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Begin the scope of a prefix-URI Namespace mapping. + */ + virtual void startPrefixMapping (const ACEXML_Char *prefix, + const ACEXML_Char *uri ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + // Methods inherited from ACEXML_ErrorHandler. + + /* + * Receive notification of a recoverable error. + */ + virtual void error (ACEXML_SAXParseException &exception ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of a non-recoverable error. + */ + virtual void fatalError (ACEXML_SAXParseException &exception ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; + + /* + * Receive notification of a warning. + */ + virtual void warning (ACEXML_SAXParseException &exception ACEXML_ENV_ARG_DECL) + ACE_THROW_SPEC ((ACEXML_SAXException)) + ; +private: + TestConfig::Test_Config_Set configs_; + + ACEXML_Char* fileName_; + ACEXML_Locator* locator_; + +}; + +#endif /* TEST_HANDLER_H */ diff --git a/TAO/orbsvcs/tests/EC_Config/svc.conf b/TAO/orbsvcs/tests/EC_Config/svc.conf new file mode 100644 index 00000000000..bfbfac829b5 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/svc.conf @@ -0,0 +1,2 @@ +# $Id$ +static EC_Factory "-ECProxyPushConsumerCollection mt:immediate:list -ECProxyPushSupplierCollection mt:immediate:list -ECdispatching kokyu -ECscheduling kokyu -ECfiltering kokyu -ECproxyconsumerlock thread -ECproxysupplierlock thread -ECsupplierfiltering per-supplier" diff --git a/TAO/orbsvcs/tests/EC_Config/svc.conf.xml b/TAO/orbsvcs/tests/EC_Config/svc.conf.xml new file mode 100644 index 00000000000..2bc3e1255ca --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/svc.conf.xml @@ -0,0 +1,6 @@ +<?xml version='1.0'?> +<!-- Converted from ./orbsvcs/examples/RtEC/Schedule/svc.conf by svcconf-convert.pl --> +<ACE_Svc_Conf> + <!-- $Id$ --> + <static id="EC_Factory" params="-ECProxyPushConsumerCollection mt:immediate:list -ECProxyPushSupplierCollection mt:immediate:list -ECdispatching kokyu -ECscheduling kokyu -ECfiltering kokyu -ECproxyconsumerlock thread -ECproxysupplierlock thread -ECsupplierfiltering per-supplier"/> +</ACE_Svc_Conf> diff --git a/TAO/orbsvcs/tests/EC_Config/test.xml b/TAO/orbsvcs/tests/EC_Config/test.xml new file mode 100644 index 00000000000..5a37434eb0f --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/test.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<!DOCTYPE testconfig SYSTEM "testconfig.dtd"> +<testconfig> + <test_config_t> + <type>0</type> + <period>1000</period> + <criticality value="HIGH" /> + <importance value="VERY_LOW" /> + <num_entities>10</num_entities> + </test_config_t> + <test_config_t> + <type>1</type> + <period>2000</period> + <criticality value="LOW"/> + <importance value="VERY_LOW"/> + <num_entities>10</num_entities> + </test_config_t> +</testconfig>
\ No newline at end of file diff --git a/TAO/orbsvcs/tests/EC_Config/testconfig.dtd b/TAO/orbsvcs/tests/EC_Config/testconfig.dtd new file mode 100644 index 00000000000..6330b60e817 --- /dev/null +++ b/TAO/orbsvcs/tests/EC_Config/testconfig.dtd @@ -0,0 +1,9 @@ + <!ELEMENT testconfig (test_config_t*) > + <!ELEMENT test_config_t (type,period,criticality,importance,num_entities) > + <!ELEMENT type (#PCDATA) > + <!ELEMENT period (#PCDATA) > + <!ELEMENT criticality EMPTY > + <!ELEMENT importance EMPTY > + <!ELEMENT num_entities (#PCDATA) > + <!ATTLIST criticality value (VERY_LOW|LOW|MEDIUM|HIGH|VERY_HIGH) #REQUIRED > + <!ATTLIST importance value (VERY_LOW|LOW|MEDIUM|HIGH|VERY_HIGH) #REQUIRED > |