summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthrall <thrall@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-10-31 20:22:16 +0000
committerthrall <thrall@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2003-10-31 20:22:16 +0000
commit40aeddfed38c05ba0d58b9639f1cc683dc2ee9ac (patch)
tree115ec5337c95a1c2de34ff22fa57e3b53b3a0849
parent061ebfda6bc438115795ec7e750bffbb70c56286 (diff)
downloadATCD-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".
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Config_Factory.cpp130
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Config_Factory.h104
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Consumer.cpp193
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Consumer.h109
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.cpp523
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/ECConfig.h133
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Makefile73
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Schedule.h42
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Service.cpp531
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Supplier.cpp21
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Supplier.h54
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Test.cpp133
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.cpp11
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/TestConfig.h134
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Test_Handler.cpp464
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/Test_Handler.h191
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/TimeoutConsumer.cpp294
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/TimeoutConsumer.h110
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/example.xml33
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/svc.conf2
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/svc.conf.xml6
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/test.xml33
-rw-r--r--TAO/orbsvcs/examples/RtEC/test_driver/testconfig.dtd11
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 >