diff options
author | thrall <thrall@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-10-31 20:22:16 +0000 |
---|---|---|
committer | thrall <thrall@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2003-10-31 20:22:16 +0000 |
commit | 40aeddfed38c05ba0d58b9639f1cc683dc2ee9ac (patch) | |
tree | 115ec5337c95a1c2de34ff22fa57e3b53b3a0849 | |
parent | 061ebfda6bc438115795ec7e750bffbb70c56286 (diff) | |
download | ATCD-40aeddfed38c05ba0d58b9639f1cc683dc2ee9ac.tar.gz |
Initial commit of Configurator code. The example.xml file mimics the
$TAO_ROOT/TAO/orbsvcs/examples/RtEC/Kokyu example.
To make the example, use "make Test", then "Test -f example.xml".
23 files changed, 3335 insertions, 0 deletions
diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/Config_Factory.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/Config_Factory.cpp new file mode 100644 index 00000000000..0d18f0cce6e --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Config_Factory.cpp @@ -0,0 +1,130 @@ +// $Id$ + +#include "Config_Factory.h" +#include "ECConfig.h" + +#include "ace/Arg_Shifter.h" +#include "orbsvcs/Sched/Reconfig_Scheduler.h" + +using namespace ConfigFactory; + +//ACE_RCSID(DOA03, Default_Config_Factory, "$Id$") + +typedef TAO_Reconfig_Scheduler<TAO_MUF_FAIR_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> MUF_SCHED_TYPE; +typedef TAO_Reconfig_Scheduler<TAO_RMS_FAIR_Reconfig_Sched_Strategy, TAO_SYNCH_MUTEX> RMS_SCHED_TYPE; + +Config_Factory::~Config_Factory (void) +{ +} + +Default_Config_Factory::Default_Config_Factory (void) + : Config_Factory (), + test_config_(0), //default to ECConfig + sched_type_(RMS) //default to RMS scheduling +{ +} + +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: + ACE_DEBUG ((LM_DEBUG, + "Default_Config_Factory: Returning MUF Test_Config\n")); + return new TestConfig::ECConfig<MUF_SCHED_TYPE>(); + break; + case RMS: + ACE_DEBUG ((LM_DEBUG, + "Default_Config_Factory: Returning RMS Test_Config\n")); + 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/examples/RtEC/test_driver/Config_Factory.h b/TAO/orbsvcs/examples/RtEC/test_driver/Config_Factory.h new file mode 100644 index 00000000000..0c38b350f16 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Config_Factory.h @@ -0,0 +1,104 @@ +/* -*- 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: + ///Constructor + Config_Factory (void) {} + + ///Destructor + 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/examples/RtEC/test_driver/Consumer.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/Consumer.cpp new file mode 100644 index 00000000000..c0ff8bef3a1 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Consumer.cpp @@ -0,0 +1,193 @@ +// $Id$ + +#include "Consumer.h" + +#include <sstream> //for ostringstream + +#include "ace/Thread.h" +#include "orbsvcs/Event_Utilities.h" //for ACE_Supplier/ConsumerQOS_Factory +#include "orbsvcs/RtecSchedulerC.h" + +ACE_RCSID(EC_Examples, Consumer, "$Id$") + +Consumer::Consumer (void) + : _consumer(this) + , _consumer_id(-1) +{ +} + +Consumer::~Consumer(void) +{ +} + +void +Consumer::connect (RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + int consumer_id, //unique identifier + long event_type, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL) +{ + this->connect_impl(false, + scheduler, + entry_prefix, + consumer_id, + event_type, + 0, //period; ignored + RtecScheduler::VERY_LOW_IMPORTANCE, //ignored + RtecScheduler::VERY_LOW_CRITICALITY, //ignored + ec + ACE_ENV_ARG_PARAMETER); +} + +void +Consumer::connect (RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + int consumer_id, //unique identifier + long event_type, + TimeBase::TimeT period, + RtecScheduler::Importance_t importance, + RtecScheduler::Criticality_t criticality, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL) +{ + this->connect_impl(true, + scheduler, + entry_prefix, + consumer_id, + event_type, + period, + importance, + criticality, + ec + ACE_ENV_ARG_PARAMETER); +} + +void +Consumer::connect_impl (bool set_rtinfo, //true if should set RT_Info + RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + int consumer_id, //unique identifier + long event_type, + TimeBase::TimeT period, + RtecScheduler::Importance_t importance, + RtecScheduler::Criticality_t criticality, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL) +{ + this->_consumer_id = consumer_id; + + //create consumer RT_Info + std::ostringstream cons_entry_pt; + cons_entry_pt << entry_prefix; //unique RT_Info entry point + ACE_DEBUG((LM_DEBUG,"Creating %s\n",cons_entry_pt.str().c_str())); + RtecScheduler::handle_t rt_info = scheduler->create (cons_entry_pt.str().c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + if (set_rtinfo) + { + ACE_Time_Value tv (0,0); + TimeBase::TimeT tmp; + ORBSVCS_Time::Time_Value_to_TimeT (tmp, tv); + scheduler->set (rt_info, + criticality, + tmp,tmp,tmp, + period, + importance, + tmp, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + ACE_DEBUG((LM_DEBUG,"Set Consumer %d RT_Info\n",this->_consumer_id)); + } else + { + ACE_DEBUG((LM_DEBUG,"NOT Set Consumer %d RT_Info\n",this->_consumer_id)); + } + + // Register as consumer of appropriate event type + ACE_ConsumerQOS_Factory consQoS; + consQoS.insert_type(event_type, + rt_info); + + RtecEventChannelAdmin::ConsumerAdmin_var consumer_admin = + ec->for_consumers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_supplier_proxy = + consumer_admin->obtain_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + RtecEventComm::PushConsumer_var consumerv = + this->_consumer._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_supplier_proxy->connect_push_consumer (consumerv.in (), + consQoS.get_ConsumerQOS () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_DEBUG((LM_DEBUG,"Consumer %d connected\n",this->_consumer_id)); + ACE_DEBUG((LM_DEBUG,"\tEvent type: %d\n",event_type)); +} + +void +Consumer::disconnect (ACE_ENV_SINGLE_ARG_DECL) +{ + //disconnect consumer + + if (! CORBA::is_nil (this->_supplier_proxy.in())) + { + this->_supplier_proxy->disconnect_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_supplier_proxy = RtecEventChannelAdmin::ProxyPushSupplier::_nil(); + + //Deactivate the servant + PortableServer::POA_var poa = + this->_consumer._default_POA(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + PortableServer::ObjectId_var id = + poa->servant_to_id (&this->_consumer ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + poa->deactivate_object(id.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + ACE_DEBUG((LM_DEBUG,"Consumer %d disconnected\n",this->_consumer_id)); + } else + { + ACE_DEBUG((LM_DEBUG,"Cannot disconnect; Consumer %d not connected!\n",this->_consumer_id)); + } +} + +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", + this->_consumer_id,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/examples/RtEC/test_driver/Consumer.h b/TAO/orbsvcs/examples/RtEC/test_driver/Consumer.h new file mode 100644 index 00000000000..800bc309f3b --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Consumer.h @@ -0,0 +1,109 @@ +/* -*- C++ -*- */ +// $Id$ +// +// ============================================================================ +// +// = LIBRARY +// ORBSVCS Real-time Event Channel examples +// +// = FILENAME +// Consumer +// +// = AUTHOR +// Bryan A. Thrall (thrall@cse.wustl.edu) +// +// ============================================================================ + +#ifndef CONSUMER_H +#define CONSUMER_H + +#include "orbsvcs/RtecEventChannelAdminC.h" +#include "orbsvcs/RtecEventCommC.h" +#include "orbsvcs/RtecSchedulerC.h" +#include "orbsvcs/Channel_Clients_T.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class Consumer +{ + // = TITLE + // Simple consumer object + // + // = DESCRIPTION + // This class is a consumer of the events pushed by a TimeoutConsumer + // every timeout. + // + // It simply registers for the event type specified in its connect() + // function. + // +public: + Consumer (void); + // Default Constructor. + + virtual ~Consumer (void); + + void connect (RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + int consumer_id, //unique identifier + long event_type, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL); + // This method connects the consumer to the EC without setting anything + // in the RT_Info (such as period, criticality, etc.). The consumer + // subscribes to events with the specified event_type. + + void connect (RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + int consumer_id, //unique identifier + long event_type, + TimeBase::TimeT period, + RtecScheduler::Importance_t importance, + RtecScheduler::Criticality_t criticality, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL); + // This method connects the consumer to the EC, setting RT_Info values + // for period, criticality, and importance. The consumer subscribes + // to events with the specified event_type. + + void disconnect (ACE_ENV_SINGLE_ARG_DECL); + // Disconnect from the EC. + + // = 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. + +protected: + void connect_impl (bool set_rtinfo, //true if should set RT_Info + RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + int consumer_id, //unique identifier + long event_type, + TimeBase::TimeT period, + RtecScheduler::Importance_t importance, + RtecScheduler::Criticality_t criticality, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL); + // This method implements the Consumer::connect() methods; if the first + // parameter is false, then the RT_Info values are ignored. Otherwise, + // they are set. + +private: + RtecEventChannelAdmin::ProxyPushSupplier_var _supplier_proxy; + // We talk to the EC (as a consumer) using this proxy. + + ACE_PushConsumer_Adapter<Consumer> _consumer; + // We connect to the EC as a consumer so we can receive the + // timeout events. + + int _consumer_id; +}; + +#endif /* CONSUMER_H */ diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.cpp new file mode 100644 index 00000000000..e24655ea671 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.cpp @@ -0,0 +1,523 @@ +// $Id$ + +#ifndef ECCONFIG_C +#define ECCONFIG_C + +#include "ECConfig.h" +#include "Consumer.h" +#include "TimeoutConsumer.h" + +#include <sstream> //for ostringstream + +#include "ace/Array.h" +#include "ace/Bound_Ptr.h" +#include "ace/Thread_Manager.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 "orbsvcs/RtecSchedulerC.h" +#include "orbsvcs/RtecEventCommC.h" + +namespace TestConfig { + +template <class SCHED_STRAT> +ECConfig<SCHED_STRAT>::ECConfig (void) + : Test_Config () + , ec_impl(0) + , sched_impl(0) + , periods(0) + , importances(0) + , crits(0) + , test_done(new ACE_RW_Mutex()) + , configured (0) //false +{ +} + +template <class SCHED_STRAT> +ECConfig<SCHED_STRAT>::~ECConfig (void) +{ + this->reset(ACE_ENV_SINGLE_ARG_PARAMETER); + + delete this->test_done; +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::reset (ACE_ENV_SINGLE_ARG_DECL) +{ + // We should do a lot of cleanup (disconnect from the EC, + // deactivate all the objects with the POA, etc.). + + this->disconnect_suppliers(ACE_ENV_SINGLE_ARG_PARAMETER); //should release all read locks on this->test_done + + this->disconnect_consumers(ACE_ENV_SINGLE_ARG_PARAMETER); + + { + // Deactivate the EC + PortableServer::POA_var poa = + this->ec_impl->_default_POA (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + PortableServer::ObjectId_var id = + poa->servant_to_id (this->ec_impl ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + poa->deactivate_object (id.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_DEBUG ((LM_DEBUG, "EC deactivated\n")); + } + + { + // Deactivate the Scheduler + PortableServer::POA_var poa = + this->sched_impl->_default_POA (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + PortableServer::ObjectId_var id = + poa->servant_to_id (this->sched_impl ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + poa->deactivate_object (id.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_DEBUG ((LM_DEBUG, "scheduler deactivated\n")); + } + + delete this->ec_impl; + this->ec_impl = 0; + + delete this->sched_impl; + this->sched_impl = 0; + + //TODO clear config_infos? + + //TODO clear RT_Infos from scheduler? + + configured = 0; //false +} + +template <class SCHED_STRAT> int +ECConfig<SCHED_STRAT>::configure (TCFG_SET_WPTR testconfigs) +{ + if (this->configured) { + ACE_DEBUG((LM_DEBUG,ACE_TEXT("Resetting EC\n"))); + this->reset(); //delete memory used by previous configuration + } + + ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + this->initEC(); + + ACE_DEBUG((LM_DEBUG,ACE_TEXT("EC Initialized\n"))); + + ////////////////// EC ready; do config //////////////////// + size_t tsize = testconfigs->size(); + size_t supp_size = 0; //number of suppliers (sources) + size_t cons_size = 0; //number of consumers (sinks) + this->testcfgs.size(tsize); + this->periods.size(tsize); + this->importances.size(tsize); + this->crits.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]; + this->testcfgs[i] = curcfg; + + switch (curcfg->criticality) { + case VERY_LOW_CRITICALITY : + this->crits[i] = RtecScheduler::VERY_LOW_CRITICALITY; + break; + case LOW_CRITICALITY : + this->crits[i] = RtecScheduler::LOW_CRITICALITY; + break; + case MEDIUM_CRITICALITY : + this->crits[i] = RtecScheduler::MEDIUM_CRITICALITY; + break; + case HIGH_CRITICALITY : + this->crits[i] = RtecScheduler::HIGH_CRITICALITY; + break; + case VERY_HIGH_CRITICALITY : + this->crits[i] = RtecScheduler::VERY_HIGH_CRITICALITY; + break; + } + + switch (curcfg->importance) { + case VERY_LOW_IMPORTANCE : + this->importances[i] = RtecScheduler::VERY_LOW_IMPORTANCE; + break; + case LOW_IMPORTANCE : + this->importances[i] = RtecScheduler::LOW_IMPORTANCE; + break; + case MEDIUM_IMPORTANCE : + this->importances[i] = RtecScheduler::MEDIUM_IMPORTANCE; + break; + case HIGH_IMPORTANCE : + this->importances[i] = RtecScheduler::HIGH_IMPORTANCE; + break; + case VERY_HIGH_IMPORTANCE : + this->importances[i] = RtecScheduler::VERY_HIGH_IMPORTANCE; + break; + } + + ACE_Time_Value tv; + tv.msec(curcfg->period); + ORBSVCS_Time::Time_Value_to_TimeT (this->periods[i], tv); + + if (curcfg->comptype == TestConfig::SOURCE) + { + ++supp_size; + } + else if (curcfg->comptype == TestConfig::SINK) + { + ++cons_size; + } + } + + this->consumers.size(cons_size); + this->connect_consumers(ACE_ENV_SINGLE_ARG_PARAMETER); + this->suppliers.size(supp_size); + this->connect_suppliers(ACE_ENV_SINGLE_ARG_PARAMETER); + + ////////////////// 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; + RtecScheduler::Dependency_Set_var deps; + + // 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 (), + deps.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 (), + deps.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 = 1; //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 + { + ACE_Thread_Manager *inst = ACE_Thread_Manager::instance(); + + // Spawn orb thread (which calls orb.run(), then terminates on return) + ACE_DEBUG((LM_DEBUG,"SPAWNING ORB thread\n")); + int ret = inst->spawn(ECConfig<SCHED_STRAT>::run_orb,&(this->orb)); + //no need for getting tid? + if (ret == -1) + { + ACE_DEBUG ((LM_DEBUG, "ERROR: Couldn't spawn ORB->run() thread: %s\n", + ACE_OS::strerror(errno))); + return 1; + } + + // Block waiting for consumers to finish + //when can acquire write lock, all TimeoutConsumers are finished + ret = this->test_done->acquire_write(); + if (ret == -1) + { + ACE_DEBUG((LM_DEBUG, "ERROR: could not acquire write lock for ECConfig: %s\n", + ACE_OS::strerror(errno))); + return 1; + } + + //all TimeoutConsumers done, so stop EC and ORB + //Shutdown EC + this->reset(); + + // Shutdown ORB + this->orb->shutdown(1); //argument is TRUE + + if (inst->wait() == -1) //wait for ORB thread to terminate + { + ACE_ERROR((LM_ERROR, "ERROR: Thread_Manager wait failed: %s\n", + ACE_OS::strerror(errno))); + return 1; + } + + ACE_DEBUG ((LM_DEBUG, "suppliers finished\n")); + + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION (ACE_ANY_EXCEPTION, "ECConfig"); + return 1; + } + ACE_ENDTRY; + + return 0; //successful run +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::initEC(ACE_ENV_SINGLE_ARG_DECL) +{ + TAO_EC_Kokyu_Factory::init_svcs (); + + ACE_DEBUG ((LM_DEBUG,ACE_TEXT("Initializing event channel\n"))); + + // ORB initialization boiler plate... + int argc = 0; + char** argv = 0; + this->orb = + CORBA::ORB_init (argc, argv, "" ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_DEBUG((LM_DEBUG,ACE_TEXT("Resolving initial references\n"))); + + CORBA::Object_var object = + orb->resolve_initial_references ("RootPOA" ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + this->poa = + PortableServer::POA::_narrow (object.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + this->poa_manager = + poa->the_POAManager (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + poa_manager->activate (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + // DO these need to remain in scope beyond this function? + + ACE_DEBUG((LM_DEBUG,ACE_TEXT("Creating sched service\n"))); + + // Create a scheduling service + ACE_NEW (this->sched_impl,SCHED_STRAT); + + this->scheduler = sched_impl->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_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 (this->ec_impl,TAO_EC_Event_Channel (attributes)); + + ACE_DEBUG((LM_DEBUG,ACE_TEXT("Created ec_impl\n"))); + + this->event_channel = + this->ec_impl->_this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::connect_suppliers (ACE_ENV_SINGLE_ARG_DECL) +{ + RtecEventComm::EventSet event(1); + event.length(1); + + ACE_DEBUG((LM_DEBUG,"TimeoutConsumers to connect: %d\n",this->suppliers.size())); + //this->suppliers already has correct size + size_t supp_idx = 0; + for (size_t i=0; i<this->testcfgs.size(); ++i) + { + if (this->testcfgs[i]->comptype == SOURCE) + { + ACE_ASSERT(supp_idx < this->suppliers.size()); + ACE_NEW (this->suppliers[supp_idx], TimeoutConsumer ()); + + event[0].header.type = ACE_ES_EVENT_UNDEFINED+this->testcfgs[i]->type; + event[0].header.source = supp_idx; //supplier_id + event[0].header.ttl = 1; + + std::ostringstream entry_prefix; + entry_prefix << "TimeoutConsumer " << supp_idx; + + ACE_DEBUG((LM_DEBUG,"TimeoutConsumer.connect() for %s\n",entry_prefix.str().c_str())); + this->suppliers[supp_idx]->connect (this->test_done, + this->scheduler.in(), + entry_prefix.str().c_str(), + this->periods[i], //period + this->importances[i], //importance + this->crits[i], //criticality + supp_idx, //supplier_id + this->testcfgs[i]->num_entities, //to_send + event, //event set + this->event_channel.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + ++supp_idx; //proceed to next supplier + } + } +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::connect_consumers (ACE_ENV_SINGLE_ARG_DECL) +{ + ACE_DEBUG((LM_DEBUG,"Consumers to connect: %d\n",this->consumers.size())); + //this->suppliers already has correct size + size_t cons_idx = 0; + for (size_t i=0; i<this->testcfgs.size(); ++i) + { + if (this->testcfgs[i]->comptype == SINK) + { + ACE_ASSERT(cons_idx < this->consumers.size()); + ACE_NEW (this->consumers[cons_idx], Consumer ()); + + std::ostringstream entry_prefix; + entry_prefix << "Consumer " << cons_idx; + + ACE_DEBUG((LM_DEBUG,"Consumer.connect() for %s\n",entry_prefix.str().c_str())); + //don't set the RT_Info values + this->consumers[cons_idx]->connect (this->scheduler.in(), + entry_prefix.str().c_str(), + cons_idx, //consumer id + ACE_ES_EVENT_UNDEFINED+this->testcfgs[i]->type, //type + /* + this->periods[i], + this->importances[i], + this->crits[i], + */ + this->event_channel.in() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + ++cons_idx; //proceed to next sink + } + } +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::disconnect_suppliers (ACE_ENV_SINGLE_ARG_DECL) +{ + for (size_t i = 0; i < this->suppliers.size(); ++i) + { + this->suppliers[i]->disconnect (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + delete this->suppliers[i]; + this->suppliers[i] = 0; + } +} + +template <class SCHED_STRAT> void +ECConfig<SCHED_STRAT>::disconnect_consumers (ACE_ENV_SINGLE_ARG_DECL) +{ + for (size_t i = 0; i < this->consumers.size(); ++i) + { + this->consumers[i]->disconnect (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + delete this->consumers[i]; + this->consumers[i] = 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; + +} + +template <class SCHED_STRAT> ACE_THR_FUNC_RETURN +ECConfig<SCHED_STRAT>::run_orb(void *data) +{ + //ACE_DECLARE_NEW_CORBA_ENV; + ACE_TRY + { + ACE_DEBUG((LM_DEBUG, "ORB thread: Casting %x\n",data)); + + CORBA::ORB_var orb = *(ACE_reinterpret_cast(CORBA::ORB_var*,data)); + + ACE_DEBUG((LM_DEBUG, "ORB thread: Running orb\n")); + + orb->run(); + //this method returns when orb->shutdown() is called; then thread exits + + ACE_DEBUG((LM_DEBUG, "ORB thread: Shutdown\n")); + } + ACE_CATCHANY + { + ACE_PRINT_EXCEPTION(ACE_ANY_EXCEPTION, "ECConfig ORB thread"); + } + ACE_ENDTRY; + + return 0; +} + +} /* namespace TestConfig */ + +#endif /* ECCONFIG_C */ diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.h b/TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.h new file mode 100644 index 00000000000..e0b3b1c2384 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.h @@ -0,0 +1,133 @@ +/* -*- 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 "ace/RW_Mutex.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 "TimeoutConsumer.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<TimeBase::TimeT> PeriodList; +typedef ACE_Array<RtecScheduler::Importance_t> ImportanceList; +typedef ACE_Array<RtecScheduler::Criticality_t> CritList; + +typedef ACE_Array<Consumer*> ConsumerList; +typedef ACE_Array<TimeoutConsumer*> 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: + // TODO USE DEFAULTS FOR ANY OF THESE? + + virtual void initEC (ACE_ENV_SINGLE_ARG_DECL); + + void connect_suppliers (ACE_ENV_SINGLE_ARG_DECL); + + void disconnect_suppliers (ACE_ENV_SINGLE_ARG_DECL); + + void connect_consumers (ACE_ENV_SINGLE_ARG_DECL); + + void disconnect_consumers (ACE_ENV_SINGLE_ARG_DECL); + + virtual void reset (ACE_ENV_SINGLE_ARG_DECL); + +private: + + void print_RT_Infos (ACE_Array<RtecScheduler::handle_t> cfg_set); + + static ACE_THR_FUNC_RETURN run_orb(void *data); //thread fcn for running ORB + + 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; + + TAO_EC_Event_Channel *ec_impl; + + SCHED_STRAT *sched_impl; + + ConsumerList consumers; + + SupplierList suppliers; + + PeriodList periods; + + ImportanceList importances; + + CritList crits; + + ACE_RW_Mutex* test_done; + //TimeoutConsumers acquire read locks; when the ECConfig can acquire + //a write lock, all TimeoutConsumers must've finished, so the test + //is finished. + + int configured; //boolean +}; + +} /* 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/examples/RtEC/test_driver/Makefile b/TAO/orbsvcs/examples/RtEC/test_driver/Makefile new file mode 100644 index 00000000000..fb585fceabb --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Makefile @@ -0,0 +1,73 @@ +#---------------------------------------------------------------------------- +# +# $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 TestConfig.cpp TimeoutConsumer.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 Consumer ECConfig Config_Factory Test_Handler TestConfig TimeoutConsumer) +Service_OBJS=$(addsuffix .o, Service Supplier Consumer ECConfig TestConfig) + +#---------------------------------------------------------------------------- +# Include macros and targets +#---------------------------------------------------------------------------- + +# To allow debug, disable optimization: +debug=1 +optimize=0 + +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/examples/RtEC/test_driver/Schedule.h b/TAO/orbsvcs/examples/RtEC/test_driver/Schedule.h new file mode 100644 index 00000000000..55fab809258 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/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/examples/RtEC/test_driver/Service.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/Service.cpp new file mode 100644 index 00000000000..cf9926708a9 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/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/examples/RtEC/test_driver/Supplier.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/Supplier.cpp new file mode 100644 index 00000000000..badc65b011d --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/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/examples/RtEC/test_driver/Supplier.h b/TAO/orbsvcs/examples/RtEC/test_driver/Supplier.h new file mode 100644 index 00000000000..b0391f7602b --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/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/examples/RtEC/test_driver/Test.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/Test.cpp new file mode 100644 index 00000000000..705725f9e52 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Test.cpp @@ -0,0 +1,133 @@ +// $Id$ + +#include "ace/Array.h" +#include "ace/Bound_Ptr.h" +#include "ace/Synch.h" +#include "ace/Get_Opt.h" +#include "ace/String_Base.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; + +struct Arguments +{ + ACE_CString filename_; +}; + +int parse_args (int argc, char *argv[],Arguments &args); + +int +main (int argc, char *argv[]) +{ + int retval = 0; + + ACEXML_TRY_NEW_ENV + { + ACEXML_Parser parser; + Arguments args; + args.filename_.set(ACE_TEXT("test.xml")); + + // parse args for config filename + if (parse_args(argc,argv,args) == -1) + { + return 1; + } + + ACEXML_FileCharStream *fcs = new ACEXML_FileCharStream(); + if ((retval = fcs->open(args.filename_.c_str())) != 0) { + ACE_DEBUG ((LM_DEBUG, "Could not open file %s\n",args.filename_.c_str())); + return retval; + } + + ACEXML_InputSource is (fcs); //takes responsibility of fcs + + Test_Handler handler (args.filename_.c_str()); + ACEXML_DefaultHandler dflt; + + parser.setContentHandler (&handler); + parser.setDTDHandler (&dflt); + parser.setErrorHandler (&handler); + parser.setEntityResolver (&dflt); + + parser.parse(&is); + ACEXML_TRY_CHECK; + + if ((retval = fcs->close()) != 0) { + ACE_DEBUG ((LM_DEBUG, "Could not close file %s\n",args.filename_.c_str())); + return retval; + } + + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Finished parsing\n"))); + + // configure according to parsed XML + 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; + } + + // PROBLEM: occasional segfault on run and configure + TCFG_SET_WPTR cfg_ptr(handler.get_configs()); + + int retval = 0; + if ((retval = backend->configure(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; + } + + fact.destroy_testconfig(backend); + fact.fini(); + + } + ACEXML_CATCH (ACEXML_SAXException, ex) + { + ACE_DEBUG ((LM_ERROR, ACE_TEXT ("Exception occurred: %s. Exiting...\n"), + ex.message())); + return 1; + } + ACEXML_ENDTRY; + + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Finished successfully\n"))); + + return retval; +} + +int parse_args (int argc, char *argv[], Arguments &args) +{ + ACE_Get_Opt get_opts (argc, argv, "f:"); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'f': + args.filename_.set(get_opts.opt_arg()); + ACE_DEBUG((LM_DEBUG,ACE_TEXT("Filename argument: %s\n"),args.filename_.c_str())); + break; + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "[-f <filename>] " + "\n", + argv [0]), + -1); + } + // Indicates sucessful parsing of the command line + return 0; +} diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.cpp new file mode 100644 index 00000000000..37be921b867 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.cpp @@ -0,0 +1,11 @@ +// $Id$ + +#include /**/ "TestConfig.h" + +namespace TestConfig { + +Test_Config::~Test_Config (void) +{ +} + +} /* namespace TestConfig */ diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.h b/TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.h new file mode 100644 index 00000000000..e54baeb699f --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.h @@ -0,0 +1,134 @@ +/* -*- 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_Strong_Bound_Ptr<Test_Config_Set,ACE_Null_Mutex> TCFG_SET_SPTR; +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; //in milliseconds + +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 +}; + +enum Component_Type_t { +// Defines the type of component the test_config_t represents + SOURCE, //component produces entities. + SINK, //component consumes entities. + SOURCESINK //component produces and consumes entities. NOT SUPPORTED +}; + +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. +{ + Component_Type_t comptype; + + // 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/examples/RtEC/test_driver/Test_Handler.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/Test_Handler.cpp new file mode 100644 index 00000000000..fa4c0989b47 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Test_Handler.cpp @@ -0,0 +1,464 @@ +// -*- C++ -*- $Id$ + +#include "Test_Handler.h" + +#include "TestConfig.h" +#include "ace/ACE.h" +#include "ace/Log_Msg.h" + +#include <stdlib.h> //for atol +#include <sstream> //for istringstream + +Test_Handler::Test_Handler (const char *filename) + : configs_(new TestConfig::Test_Config_Set(0)), + fileName_(filename), + didtype_(0), //false + didperiod_(0), + didcrit_(0), + didimp_(0), + didnum_(0) +{ + +} + +Test_Handler::~Test_Handler (void) +{ + const TestConfig::Test_Config_Set &cfgs = *this->configs_; + + for(size_t i=0; i<cfgs.size(); ++i) { + delete cfgs[i]; + } +} + +const TestConfig::TCFG_SET_WPTR +Test_Handler::get_configs (void) const +{ + return TestConfig::TCFG_SET_WPTR(this->configs_); +} + + +void +Test_Handler::characters (const ACEXML_Char * cdata, + int , + int + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + const TestConfig::Test_Config_Set &cfgs = *this->configs_; + TestConfig::test_config_t *curcfg = 0; //current test_config_t is last in set + std::istringstream iss(cdata); + + switch (this->scope_.top()) + { + case TYPE: + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("TYPE Characters: %s\n"),cdata)); + curcfg = cfgs[cfgs.size()-1]; + if (curcfg == 0) + { + ACEXML_THROW(ACEXML_SAXException(ACE_TEXT ("No existing test_config_t"))); + } + if ((iss >> curcfg->type) == 0) + { + ACEXML_THROW(ACEXML_SAXException(ACE_TEXT ("Invalid number format"))); + } + this->didtype_ = 1; //true + break; + case PERIOD: + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("PERIOD Characters: %s\n"),cdata)); + curcfg = cfgs[cfgs.size()-1]; + if (curcfg == 0) + { + ACEXML_THROW(ACEXML_SAXException(ACE_TEXT ("No existing test_config_t"))); + } + if ((iss >> curcfg->period) == 0) + { + ACEXML_THROW(ACEXML_SAXException(ACE_TEXT ("Invalid number format"))); + } + this->didperiod_ = 1; //true + break; + case NUM_ENTITIES: + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("NUM_ENTITIES Characters: %s\n"),cdata)); + curcfg = cfgs[cfgs.size()-1]; + if (curcfg == 0) + { + ACEXML_THROW(ACEXML_SAXException(ACE_TEXT ("No existing test_config_t"))); + } + if ((iss >> curcfg->num_entities) == 0) + { + ACEXML_THROW(ACEXML_SAXException(ACE_TEXT ("Invalid number format"))); + } + this->didnum_ = 1; //true + break; + case CRITICALITY: + case IMPORTANCE: + case SOURCE_CONFIG_T: + case SINK_CONFIG_T: + case TESTCONFIG: + default: + //ignore characters outside leaf elements + /* + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Ignoring characters outside leaf elements: %s\n"), + cdata)); + */ + break; + } +} + +void +Test_Handler::endDocument (ACEXML_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // Print out test_config_t's: + const TestConfig::Test_Config_Set &cfgs = *this->configs_; + char *cfg_format = "{%10d, %10d, %10d, %10d, %10d }"; + + for (size_t i=0; i<cfgs.size(); ++i) { + TestConfig::test_config_t *cfg = cfgs[i]; + + if (i!=0) + { + //finish previous line + ACE_DEBUG ((LM_DEBUG, "\n")); + } + if (cfg->comptype == TestConfig::SOURCE) + { + ACE_DEBUG ((LM_DEBUG, "SOURCE : ")); + } + else if (cfg->comptype == TestConfig::SINK) + { + ACE_DEBUG ((LM_DEBUG, "SINK : ")); + } + else + { + ACE_DEBUG ((LM_DEBUG, "UNKNOWN: ")); + } + ACE_DEBUG ((LM_DEBUG, cfg_format, + cfg->type, + cfg->period, + cfg->criticality, + cfg->importance, + cfg->num_entities)); + } + //finish last line + ACE_DEBUG ((LM_DEBUG, "\n")); +} + +void +Test_Handler::endElement (const ACEXML_Char *, + const ACEXML_Char *, + const ACEXML_Char * + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + if (this->scope_.empty() == 1) + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("Element end outside of any scope"))); + } + else + { + if (this->scope_.top() == SOURCE_CONFIG_T + || this->scope_.top() == SINK_CONFIG_T) + { + //check that all leaf elements were there + if (this->didtype_ == 0 + || this->didperiod_ == 0 + || this->didcrit_ == 0 + || this->didimp_ == 0 + || this->didnum_ == 0) + { + ACEXML_THROW(ACEXML_SAXException(ACE_TEXT("Missing leaf element " + "(TYPE, PERIOD, CRITICALITY, " + "IMPORTANCE, or NUM_ENTITIES)"))); + } + } + this->scope_.pop(); + /* + ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Popped scope; new top is %d\n"), + this->scope_.empty() ? -1 : this->scope_.top())); + */ + } +} + +void +Test_Handler::endPrefixMapping (const ACEXML_Char * + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // no-op +} + +void +Test_Handler::ignorableWhitespace (const ACEXML_Char *, + int, + int + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // no-op +} + +void +Test_Handler::processingInstruction (const ACEXML_Char *, + const ACEXML_Char * + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // no-op +} + +void +Test_Handler::setDocumentLocator (ACEXML_Locator * locator) +{ + this->locator_ = locator; +} + +void +Test_Handler::skippedEntity (const ACEXML_Char * + ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // no-op +} + +void +Test_Handler::startDocument (ACEXML_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // no-op +} + +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))); + } + */ + ACE_UNUSED_ARG(uri); + ACE_UNUSED_ARG(name); + + const TestConfig::Test_Config_Set &cfgs = *this->configs_; + + element newscope; + if (ACE_OS_String::strcmp (qName, ACE_TEXT ("type")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing TYPE scope\n"))); + newscope = TYPE; + } + else if (ACE_OS_String::strcmp (qName, ACE_TEXT ("period")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing PERIOD scope\n"))); + newscope = PERIOD; + } + else if (ACE_OS_String::strcmp (qName, ACE_TEXT ("criticality")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing CRITICALITY scope\n"))); + newscope = CRITICALITY; + if (alist != 0) + { + const ACEXML_Char *val = alist->getValue(ACE_TEXT("value")); + if (val != 0) + { + TestConfig::test_config_t *curcfg = 0; //current test_config_t is last in set + curcfg = cfgs[cfgs.size()-1]; + if (curcfg == 0) + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("No existing test_config_t"))); + } + if (ACE_OS_String::strcmp(val,ACE_TEXT("VERY_LOW")) == 0) + { + curcfg->criticality = TestConfig::VERY_LOW_CRITICALITY; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("LOW")) == 0) + { + curcfg->criticality = TestConfig::LOW_CRITICALITY; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("MEDIUM")) == 0) + { + curcfg->criticality = TestConfig::MEDIUM_CRITICALITY; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("HIGH")) == 0) + { + curcfg->criticality = TestConfig::HIGH_CRITICALITY; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("VERY_HIGH")) == 0) + { + curcfg->criticality = TestConfig::VERY_HIGH_CRITICALITY; + } + else + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("Invalid value for \"value\"" + " attribute for criticality"))); + } + } + else + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("Invalid attributes for criticality"))); + } + this->didcrit_ = 1; //true + } + else + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("No attributes for criticality"))); + } + } + else if (ACE_OS_String::strcmp (qName, ACE_TEXT ("importance")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing IMPORTANCE scope\n"))); + newscope = IMPORTANCE; + if (alist != 0) + { + const ACEXML_Char *val = alist->getValue(ACE_TEXT("value")); + if (val != 0) + { + TestConfig::test_config_t *curcfg = 0; //current test_config_t is last in set + curcfg = cfgs[cfgs.size()-1]; + if (curcfg == 0) + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("No existing test_config_t"))); + } + if (ACE_OS_String::strcmp(val,ACE_TEXT("VERY_LOW")) == 0) + { + curcfg->importance = TestConfig::VERY_LOW_IMPORTANCE; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("LOW")) == 0) + { + curcfg->importance = TestConfig::LOW_IMPORTANCE; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("MEDIUM")) == 0) + { + curcfg->importance = TestConfig::MEDIUM_IMPORTANCE; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("HIGH")) == 0) + { + curcfg->importance = TestConfig::HIGH_IMPORTANCE; + } + else if (ACE_OS_String::strcmp(val,ACE_TEXT("VERY_HIGH")) == 0) + { + curcfg->importance = TestConfig::VERY_HIGH_IMPORTANCE; + } + else + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("Invalid value for \"value\"" + " attribute for importance"))); + } + } + else + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("Invalid attributes for importance"))); + } + this->didimp_ = 1; //true + } + else + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("No attributes for importance"))); + } + } + else if (ACE_OS_String::strcmp (qName, ACE_TEXT ("num_entities")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing NUM_ENTITIES scope\n"))); + newscope = NUM_ENTITIES; + } + else if (ACE_OS_String::strcmp(qName,ACE_TEXT("source")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing SOURCE_CONFIG_T scope\n"))); + newscope = SOURCE_CONFIG_T; + //create test_config_t for filling in by the sub-elements of this element + TestConfig::test_config_t *newcfg = 0; + ACE_NEW(newcfg,TestConfig::test_config_t()); + newcfg->comptype = TestConfig::SOURCE; + TestConfig::Test_Config_Set &cfgs = *this->configs_; + size_t cfgsize = cfgs.size(); + cfgs.size(cfgsize+1); + cfgs[cfgsize] = newcfg; + this->didtype_ = 0; //false + this->didperiod_ = 0; //false + this->didcrit_ = 0; //false + this->didimp_ = 0; //false + this->didnum_ = 0; //false + } + else if (ACE_OS_String::strcmp(qName,ACE_TEXT("sink")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing SINK_CONFIG_T scope\n"))); + newscope = SINK_CONFIG_T; + //create test_config_t for filling in by the sub-elements of this element + TestConfig::test_config_t *newcfg = 0; + ACE_NEW(newcfg,TestConfig::test_config_t()); + newcfg->comptype = TestConfig::SINK; + TestConfig::Test_Config_Set &cfgs = *this->configs_; + size_t cfgsize = cfgs.size(); + cfgs.size(cfgsize+1); + cfgs[cfgsize] = newcfg; + this->didtype_ = 0; //false + this->didperiod_ = 0; //false + this->didcrit_ = 0; //false + this->didimp_ = 0; //false + this->didnum_ = 0; //false + } + else if (ACE_OS_String::strcmp (qName, ACE_TEXT ("testconfig")) == 0) + { + //ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("Pushing TESTCONFIG scope\n"))); + newscope = TESTCONFIG; + } + else + { + ACEXML_THROW (ACEXML_SAXException (ACE_TEXT("Element start of unknown type"))); + } + this->scope_.push(newscope); +} + +void +Test_Handler::startPrefixMapping (const ACEXML_Char *, + const ACEXML_Char * ACEXML_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((ACEXML_SAXException)) +{ + // no-op +} + +// 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_.c_str(), + 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_.c_str(), + 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/examples/RtEC/test_driver/Test_Handler.h b/TAO/orbsvcs/examples/RtEC/test_driver/Test_Handler.h new file mode 100644 index 00000000000..6207791d19c --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/Test_Handler.h @@ -0,0 +1,191 @@ +// $Id$ + +//============================================================================= +/** + * @file Test_Handler.h + * + * $Id$ + * + * @author Bryan Thrall <thrall@cse.wustl.edu> + */ +//============================================================================= + + +#ifndef TEST_HANDLER_H +#define TEST_HANDLER_H + +#include "TestConfig.h" + +#include "ace/String_Base.h" +#include "ACEXML/common/ContentHandler.h" +#include "ACEXML/common/ErrorHandler.h" + +#include <stack> + +enum element { + TESTCONFIG, + SOURCE_CONFIG_T, + SINK_CONFIG_T, + TYPE, + PERIOD, + CRITICALITY, + IMPORTANCE, + NUM_ENTITIES +}; + +// TODO Change XML format to list supplier and client RT_Infos separate, plus dependencies + +/** + * @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: + + typedef std::stack<element> STACK; + + /* + * Default constructor. + */ + Test_Handler (const 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::TCFG_SET_WPTR 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::TCFG_SET_SPTR configs_; + + ACE_CString fileName_; + ACEXML_Locator* locator_; + + STACK scope_; + + int didtype_,didperiod_,didcrit_,didimp_,didnum_; + //for each test_config_t, whether the leaf element was processed or not +}; + +#endif /* TEST_HANDLER_H */ diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/TimeoutConsumer.cpp b/TAO/orbsvcs/examples/RtEC/test_driver/TimeoutConsumer.cpp new file mode 100644 index 00000000000..8bd30cc0e82 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/TimeoutConsumer.cpp @@ -0,0 +1,294 @@ +// $Id$ + +#include "TimeoutConsumer.h" + +#include <sstream> //for ostringstream + +#include "orbsvcs/Event_Utilities.h" //for ACE_Supplier/ConsumerQOS_Factory +#include "orbsvcs/Event_Service_Constants.h" +#include "orbsvcs/RtecSchedulerC.h" +#include "orbsvcs/RtecEventCommC.h" +#include "ace/RW_Mutex.h" + +ACE_RCSID(EC_Examples, Consumer, "$Id$") + +TimeoutConsumer::TimeoutConsumer (void) + : _to_send(0) + , _num_sent(0) + , _hold_mtx(0) + , _done(0) + , _supplier(this) + , _consumer(this) + , _events(0) +{ +} + +TimeoutConsumer::~TimeoutConsumer (void) +{ + // TODO this->disconnect() ??? + + if (this->_hold_mtx && this->_done!=0) + { + this->_done->release(); + this->_hold_mtx = 0; + } +} + +void +TimeoutConsumer::connect (ACE_RW_Mutex* done, + RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + TimeBase::TimeT period, + RtecScheduler::Importance_t importance, + RtecScheduler::Criticality_t criticality, + RtecEventComm::EventSourceID supplier_id, + size_t to_send, + const RtecEventComm::EventSet& events, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL) +{ + this->_supplier_id = supplier_id; + this->_to_send = to_send; + this->_num_sent = 0; + this->_hold_mtx = 0; + this->_done = done; + if (this->_done!= 0 && this->_num_sent<this->_to_send) + { + int ret = done->acquire_read(); + if (ret == -1) + { + ACE_DEBUG((LM_DEBUG,"ERROR: Could not acquire read lock for TimeoutConsumer: %s\n", + ACE_OS::strerror(errno))); + } else + { + ACE_DEBUG((LM_DEBUG,"ACQUIRED read lock for TimeoutConsumer %d\n",this->_supplier_id)); + this->_hold_mtx = 1; + } + } else + { + ACE_DEBUG((LM_DEBUG,"Already done; did not grab read lock for TimeoutConsumer\n")); + } + + this->_events.length(events.length()); + for (size_t i=0; i<events.length(); ++i) + { + this->_events[i] = events[i]; //copy event to local set + this->_events[i].header.source = this->_supplier_id; //make sure event source is this + } + + //create supplier RT_Info + std::ostringstream supp_entry_pt; + supp_entry_pt << entry_prefix << " Supplier " << this->_supplier_id; //unique RT_Info entry point + ACE_DEBUG((LM_DEBUG,"Creating %s\n",supp_entry_pt.str().c_str())); + RtecScheduler::handle_t rt_info = scheduler->create (supp_entry_pt.str().c_str() + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + ACE_Time_Value tv (0,0); + TimeBase::TimeT tmp; + ORBSVCS_Time::Time_Value_to_TimeT (tmp, tv); + scheduler->set (rt_info, + criticality, + tmp,tmp,tmp, + period, + importance, + tmp, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Register as supplier of events + ACE_SupplierQOS_Factory supplierQOS; + for (size_t i=0; i<events.length(); ++i) + { + //insert type for each event + supplierQOS.insert (this->_supplier_id, + events[i].header.type, + rt_info, + 1); + } + + RtecEventChannelAdmin::SupplierAdmin_var supplier_admin = + ec->for_suppliers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_consumer_proxy = + supplier_admin->obtain_push_consumer (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + RtecEventComm::PushSupplier_var supplierv = + this->_supplier._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_consumer_proxy->connect_push_supplier (supplierv.in (), + supplierQOS.get_SupplierQOS () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_DEBUG((LM_DEBUG,"TimeoutConsumer connected as event supplier\n")); + for (size_t i=0; i<events.length(); ++i) + { + ACE_DEBUG((LM_DEBUG,"\tEvent Type: %d\n",events[i].header.type)); + } + + //create consumer RT_Info + std::ostringstream cons_entry_pt; + cons_entry_pt << entry_prefix << " Consumer"; //unique RT_Info entry point + ACE_DEBUG((LM_DEBUG,"Creating %s\n",cons_entry_pt.str().c_str())); + rt_info = scheduler->create (cons_entry_pt.str().c_str() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + scheduler->set (rt_info, + criticality, + period, period, period, + period, + importance, + period, + 0, + RtecScheduler::OPERATION + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + // Register as consumer of timeout events + ACE_ConsumerQOS_Factory timeoutQOS; + timeoutQOS.insert_time(ACE_ES_EVENT_INTERVAL_TIMEOUT /*??*/, + period, //TimeBase::TimeT + rt_info); + + RtecEventChannelAdmin::ConsumerAdmin_var consumer_admin = + ec->for_consumers (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_supplier_proxy = + consumer_admin->obtain_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + RtecEventComm::PushConsumer_var consumerv = + this->_consumer._this (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_supplier_proxy->connect_push_consumer (consumerv.in (), + timeoutQOS.get_ConsumerQOS () + ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + + ACE_DEBUG((LM_DEBUG,"TimeoutConsumer connected as timeout consumer\n")); + std::ostringstream prd; + prd << period; + ACE_DEBUG((LM_DEBUG,"\tTimeout period: %s\n",prd.str().c_str())); +} + +void +TimeoutConsumer::disconnect (ACE_ENV_SINGLE_ARG_DECL) +{ + if (! CORBA::is_nil (this->_consumer_proxy.in ())) + { + this->_consumer_proxy->disconnect_push_consumer (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_consumer_proxy = + RtecEventChannelAdmin::ProxyPushConsumer::_nil (); + + // Deactivate the servant + PortableServer::POA_var poa = + this->_supplier._default_POA (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + PortableServer::ObjectId_var id = + poa->servant_to_id (&this->_supplier ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + poa->deactivate_object (id.in () ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + + //disconnect consumer ??? + if (! CORBA::is_nil (this->_supplier_proxy.in())) + { + this->_supplier_proxy->disconnect_push_supplier (ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + + this->_supplier_proxy = RtecEventChannelAdmin::ProxyPushSupplier::_nil(); + + //Deactivate the servant + PortableServer::POA_var poa = + this->_consumer._default_POA(ACE_ENV_SINGLE_ARG_PARAMETER); + ACE_CHECK; + PortableServer::ObjectId_var id = + poa->servant_to_id (&this->_consumer ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + poa->deactivate_object(id.in() ACE_ENV_ARG_PARAMETER); + ACE_CHECK; + } + + if (this->_hold_mtx && this->_done!=0) + { + this->_done->release(); + this->_hold_mtx = 0; + } +} + +void +TimeoutConsumer::push (const RtecEventComm::EventSet& events + ACE_ENV_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ + if (events.length () == 0) + { + ACE_DEBUG ((LM_DEBUG,"TimeoutConsumer (%P|%t) push but no events\n")); + return; + } + + ACE_DEBUG((LM_DEBUG,"TimeoutConsumer %d (%P|%t) received %d events:\n",this->_supplier_id, + events.length())); + if (this->_num_sent < this->_to_send) + { + for (size_t i=0; i<events.length(); ++i) + { + if (ACE_ES_EVENT_INTERVAL_TIMEOUT == events[i].header.type) + { + ACE_DEBUG((LM_DEBUG,"TimeoutConsumer %d (%P|%t) received timeout event\n",this->_supplier_id)); + + //TODO send this->_events + ++this->_num_sent; + ACE_DEBUG((LM_DEBUG,"Sent events; %d sent\t%d total\n",this->_num_sent,this->_to_send)); + if (this->_num_sent >= this->_to_send) + { + //done + ACE_DEBUG((LM_DEBUG,"RELEASE read lock from TimeoutConsumer %d\n", + this->_supplier_id)); + this->_done->release(); + this->_hold_mtx = 0; + } + } + else + { + 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, "TimeoutConsumer @%d (%P|%t) we received event type %d\n", + prio,events[0].header.type)); + } + } + } else + { + //do nothing + } +} + +void +TimeoutConsumer::disconnect_push_consumer (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)) +{ +} + +void +TimeoutConsumer::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/examples/RtEC/test_driver/TimeoutConsumer.h b/TAO/orbsvcs/examples/RtEC/test_driver/TimeoutConsumer.h new file mode 100644 index 00000000000..db55b9970c3 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/TimeoutConsumer.h @@ -0,0 +1,110 @@ +/* -*- C++ -*- */ +// $Id$ +// +// ============================================================================ +// +// = LIBRARY +// ORBSVCS Real-time Event Channel examples +// +// = FILENAME +// TimeoutConsumer +// +// = AUTHOR +// Bryan Thrall (thrall@cse.wustl.edu) +// +// ============================================================================ + +#ifndef TIMEOUTCONSUMER_H +#define TIMEOUTCONSUMER_H + +#include "orbsvcs/RtecEventChannelAdminC.h" +#include "orbsvcs/RtecEventCommC.h" +#include "orbsvcs/RtecSchedulerC.h" +#include "orbsvcs/Channel_Clients_T.h" +//#include "ace/Task.h" +//#include "ace/Synch.h" +#include "ace/RW_Mutex.h" + +#if !defined (ACE_LACKS_PRAGMA_ONCE) +# pragma once +#endif /* ACE_LACKS_PRAGMA_ONCE */ + +class TimeoutConsumer +{ + // = TITLE + // Simple consumer object which responds to timeout events. + // + // = DESCRIPTION + // This class is a consumer of timeout events. + // For each timeout event it consumes, it pushes a specified EventSet into the EC. + // + // There are several ways to connect and disconnect this class, + // and it is up to the driver program to use the right one. + // +public: + TimeoutConsumer (void); + // Default Constructor. + + virtual ~TimeoutConsumer (void); + + void connect (ACE_RW_Mutex* done, + RtecScheduler::Scheduler_ptr scheduler, + const char *entry_prefix, + TimeBase::TimeT period, + RtecScheduler::Importance_t importance, + RtecScheduler::Criticality_t criticality, + RtecEventComm::EventSourceID supplier_id, + size_t to_send, + const RtecEventComm::EventSet& events, + RtecEventChannelAdmin::EventChannel_ptr ec + ACE_ENV_ARG_DECL); + // This method connects the supplier to the EC. + + void disconnect (ACE_ENV_SINGLE_ARG_DECL); + // Disconnect from the EC. + + // = The RtecEventComm::PushConsumer methods + + virtual void push (const RtecEventComm::EventSet& events + ACE_ENV_ARG_DECL) + ACE_THROW_SPEC ((CORBA::SystemException)); + // pushes _events as a supplier until _to_send pushes, then calls resume() on this task. + + virtual void disconnect_push_consumer (ACE_ENV_SINGLE_ARG_DECL_NOT_USED) + ACE_THROW_SPEC ((CORBA::SystemException)); + // The skeleton methods. + + // = 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: + size_t _to_send; //number of times to push on timeout + size_t _num_sent; //number of pushes so far + int _hold_mtx; //1 when hold _done mutex; 0 else + ACE_RW_Mutex* _done; //release read lock when _num_sent >= _to_send + + RtecEventComm::EventSourceID _supplier_id; + // We generate an id based on the name.... + + RtecEventChannelAdmin::ProxyPushConsumer_var _consumer_proxy; + // We talk to the EC (as a supplier) using this proxy. + + ACE_PushSupplier_Adapter<TimeoutConsumer> _supplier; + // We connect to the EC as a supplier so we can push events + // every time we receive a timeout event. + + RtecEventChannelAdmin::ProxyPushSupplier_var _supplier_proxy; + // We talk to the EC (as a consumer) using this proxy. + + ACE_PushConsumer_Adapter<TimeoutConsumer> _consumer; + // We connect to the EC as a consumer so we can receive the + // timeout events. + + RtecEventComm::EventSet _events; + // set of events to push when a timeout event is received. +}; + +#endif /* CONSUMER_H */ diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/example.xml b/TAO/orbsvcs/examples/RtEC/test_driver/example.xml new file mode 100644 index 00000000000..c08ee57e902 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/example.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<!DOCTYPE testconfig SYSTEM "testconfig.dtd"> +<testconfig> + <source> + <type>0</type> + <period>1000</period> + <criticality value="VERY_LOW" /> + <importance value="VERY_LOW" /> + <num_entities>10</num_entities> + </source> + <source> + <type>1</type> + <period>3000</period> + <criticality value="VERY_HIGH"/> + <importance value="VERY_HIGH"/> + <num_entities>10</num_entities> + </source> + + <sink> + <type>0</type> + <period>1000</period> + <criticality value="VERY_LOW"/> + <importance value="VERY_LOW"/> + <num_entities>10</num_entities> + </sink> + <sink> + <type>1</type> + <period>3000</period> + <criticality value="VERY_HIGH" /> + <importance value="VERY_HIGH" /> + <num_entities>10</num_entities> + </sink> +</testconfig> diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/svc.conf b/TAO/orbsvcs/examples/RtEC/test_driver/svc.conf new file mode 100644 index 00000000000..bfbfac829b5 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/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/examples/RtEC/test_driver/svc.conf.xml b/TAO/orbsvcs/examples/RtEC/test_driver/svc.conf.xml new file mode 100644 index 00000000000..2bc3e1255ca --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/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/examples/RtEC/test_driver/test.xml b/TAO/orbsvcs/examples/RtEC/test_driver/test.xml new file mode 100644 index 00000000000..2c5662ec84e --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/test.xml @@ -0,0 +1,33 @@ +<?xml version="1.0"?> +<!DOCTYPE testconfig SYSTEM "testconfig.dtd"> +<testconfig> + <source> + <type>0</type> + <period>700</period> + <criticality value="HIGH" /> + <importance value="VERY_LOW" /> + <num_entities>10</num_entities> + </source> + <sink> + <type>0</type> + <period>700</period> + <criticality value="HIGH" /> + <importance value="VERY_LOW" /> + <num_entities>10</num_entities> + </sink> + + <source> + <type>1</type> + <period>2100</period> + <criticality value="LOW"/> + <importance value="VERY_LOW"/> + <num_entities>10</num_entities> + </source> + <sink> + <type>1</type> + <period>2100</period> + <criticality value="LOW"/> + <importance value="VERY_LOW"/> + <num_entities>10</num_entities> + </sink> +</testconfig> diff --git a/TAO/orbsvcs/examples/RtEC/test_driver/testconfig.dtd b/TAO/orbsvcs/examples/RtEC/test_driver/testconfig.dtd new file mode 100644 index 00000000000..31a4cdaf457 --- /dev/null +++ b/TAO/orbsvcs/examples/RtEC/test_driver/testconfig.dtd @@ -0,0 +1,11 @@ + <!ELEMENT testconfig (test_config_t*) > + <!ELEMENT sink (type,period,criticality,importance,num_entities) > + <!ELEMENT source (type,period,criticality,importance,num_entities) > + <!ELEMENT type (#PCDATA) > +<!-- period is in milliseconds --> + <!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 > |