From: g0dil Date: Thu, 23 Aug 2007 22:40:59 +0000 (+0000) Subject: PPI: Implement LogWriter X-Git-Url: http://g0dil.de/git?a=commitdiff_plain;h=7231c220a7332754de3d16e4e8aacd5dbd31c501;p=senf.git PPI: Implement LogWriter PPI: Add documentation Utils: Make Logger macros define empty stub types git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@407 270642c3-0616-0410-b53a-bc976706d245 --- diff --git a/PPI/ActiveFeeder.hh b/PPI/ActiveFeeder.hh index a545050..d981c46 100644 --- a/PPI/ActiveFeeder.hh +++ b/PPI/ActiveFeeder.hh @@ -38,6 +38,15 @@ namespace senf { namespace ppi { namespace module { + /** \brief Adapter to connect passive connectors + + ActiveFeeder is an adapter module which allows to connect to passive connectors. As long as + none of the connectors is throttled, the ActiveFeeder will forward packets from it's input + to it's output. + + \note For this Module to work correctly, it is very important for the connectors to be + correctly throttled. Otherwise the system might well hang in an endless loop. + */ class ActiveFeeder : public Module { diff --git a/PPI/Connectors.hh b/PPI/Connectors.hh index 3824628..e37ad1f 100644 --- a/PPI/Connectors.hh +++ b/PPI/Connectors.hh @@ -57,7 +57,11 @@ namespace senf { namespace ppi { namespace connector { - /** \brief Connector baseclass + /** \namespace senf::ppi::connector + \brief Connector classes + */ + + /** \brief Connector base-class This connector provides access to the generic connector facilities. This includes the connection management (access to the connected peer) and the containment management (access @@ -85,7 +89,7 @@ namespace connector { friend class module::Module; }; - /** \brief Passive connector baseclass + /** \brief Passive connector base-class A passive connector is a connector which is activated externally whenever an I/O request occurs. Passive connectors are the origin of throttling notifications. Depending on the type @@ -134,8 +138,8 @@ namespace connector { private: // Called by the routing to change the remote throttling state - void notifyThrottle(); ///< Forward a throttling notification to this connector - void notifyUnthrottle(); ///< Forward an unthrottling notification to this connector + void notifyThrottle(); ///< Forward a throttle notification to this connector + void notifyUnthrottle(); ///< Forward an unthrottle notification to this connector // Internal members to emit throttling notifications void emitThrottle(); @@ -159,7 +163,7 @@ namespace connector { friend class senf::ppi::ForwardingRoute; }; - /** \brief Active connector baseclass + /** \brief Active connector base-class An active connector is a connector which emits I/O requests. Active connectors receive throttling notifications. Depending on the type of connector (input or output) the @@ -225,7 +229,7 @@ namespace connector { friend class PassiveConnector; }; - /** \brief Input connector baseclass + /** \brief Input connector base-class An input connector receives packets. It may be either an ActiveConnector or a PassiveConnector. An input connector contains a packet queue. This queue enables processing @@ -242,7 +246,7 @@ namespace connector { insertion/removal properties on both ends. So probably we will use a deque. I'd like a container which keeps iterators intact on - isertion/deletion but I believe that list is just to expensive since every packet will + insertion/deletion but I believe that list is just to expensive since every packet will be added to the queue before it can be processed. */ class InputConnector @@ -287,7 +291,7 @@ namespace connector { friend class OutputConnector; }; - /** \brief Output connector baseclass + /** \brief Output connector base-class An output connector sends out packets. It may be either an ActiveConnector or a PassiveConnector. An output connector does \e not have an built-in queueing, it relies on diff --git a/PPI/DebugEvent.hh b/PPI/DebugEvent.hh index 3a2f254..6b445b4 100644 --- a/PPI/DebugEvent.hh +++ b/PPI/DebugEvent.hh @@ -35,7 +35,10 @@ namespace senf { namespace ppi { - /** \brief + /** \brief Manually triggered event + + DebugEvent is a manually triggered event. The event is triggered by explicit calls to + trigger() and not by the event infrastructure. */ class DebugEvent : public EventImplementation<> @@ -57,7 +60,7 @@ namespace ppi { ///@} /////////////////////////////////////////////////////////////////////////// - void trigger(); + void trigger(); ///< Trigger event protected: diff --git a/PPI/DebugModules.cti b/PPI/DebugModules.cti new file mode 100644 index 0000000..7e65003 --- /dev/null +++ b/PPI/DebugModules.cti @@ -0,0 +1,69 @@ +// $Id$ +// +// Copyright (C) 2007 +// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) +// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Stefan Bund +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +/** \file + \brief DebugModules inline template implementation */ + +//#include "DebugModules.ih" + +// Custom includes +#include "Utils/hexdump.hh" + +#define prefix_ inline +///////////////////////////////cti.p/////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////// +// senf::ppi::module::debug::LogWriter + +template +prefix_ senf::ppi::module::debug::LogWriter::LogWriter() +{ + noroute(input); + input.onRequest(&LogWriter::request); +} + +//////////////////////////////////////// +// private members + +template +prefix_ void senf::ppi::module::debug::LogWriter::request() +{ + Packet packet (input()); + SENF_LOG_BLOCK((Stream)(Area)(level)({ + packet.dump(log); + hexdump(packet.last().data().begin(), packet.last().data().end(),log); + })); +} + +///////////////////////////////cti.e/////////////////////////////////////// +#undef prefix_ + + +// Local Variables: +// mode: c++ +// fill-column: 100 +// comment-column: 40 +// c-file-style: "senf" +// indent-tabs-mode: nil +// ispell-local-dictionary: "american" +// compile-command: "scons -u test" +// End: diff --git a/PPI/DebugModules.hh b/PPI/DebugModules.hh index ad76884..296dfc5 100644 --- a/PPI/DebugModules.hh +++ b/PPI/DebugModules.hh @@ -32,25 +32,46 @@ #include "Packets/Packets.hh" #include "Module.hh" #include "ActiveFeeder.hh" +#include "Utils/Logger.hh" //#include "DebugModules.mpp" ///////////////////////////////hh.p//////////////////////////////////////// -/** \namespace senf::ppi::module::debug - \brief Debug modules - - This namespace collects several modules helpful for PPI debugging. The modules allow to manually - pass packets into a network and read back the output packets. - - - */ - namespace senf { namespace ppi { namespace module { namespace debug { - /** \brief + /** \namespace senf::ppi::module::debug + \brief Debug modules + + This namespace collects several modules helpful for PPI debugging. The modules allow to + manually pass packets into a network and read back the output packets. + + There are three categories of modules: + + \li Active modules (ActiveSource, ActiveSink) are triggered by external + calls. Calling \c submit() / \c request() will send the request into the module network + synchronously. From this it follows, that senf::ppi::run() should \e not be + called. Instead senf::ppi::init() is used to initialize the network and explicit calls + to the active debug modules drive the execution. + \li Passive modules (PassiveSource, PassiveSink) contain a queue to save packets + (either packets to be transmitted or packets received) and are driven by the network. + \li Feeder (almost-)modules (ActiveFeederSource, ActiveFeederSink) are a hybrid of + both types of modules: They contain a packet queue but actively drive the network and + are used together with senf::ppi::run(). senf::ppi::run() will automatically terminate + if all available packets have been processed. These are not modules, they are + collections combining a passive debug module and a senf::ppi::ActiveFeeder. + */ + + /** \brief Debug packet source with active output + + This module provides packets into the network. Each call to submit() will process the packet + synchronously. + + \note This module should not be used together with senf::ppi::run(). Instead use + senf::ppi::init() and explicit submit() calls. It follows, that no events will be + signaled in the network. */ class ActiveSource : public Module, @@ -63,11 +84,18 @@ namespace debug { ActiveSource(); - void submit(Packet packet); + void submit(Packet packet); ///< Submit packet + /**< \pre boolean_test() is \c true */ - bool boolean_test() const; + bool boolean_test() const; ///< \c true if \a output is not throttled }; + /** \brief Debug packet source with passive output + + This module provides a queue of packets for reading by the network. Each submit() call adds + a packet to the queue which will be sent into the network when requested. The output is + automatically throttled when the queue becomes empty. + */ class PassiveSource : public Module { @@ -78,14 +106,14 @@ namespace debug { public: typedef Queue::size_type size_type; - PassiveSource(); - connector::PassiveOutput output; + + PassiveSource(); - void submit(Packet packet); + void submit(Packet packet); ///< Enqueue packet - bool empty(); - size_type size(); + bool empty(); ///< \c true if queue is empty + size_type size(); ///< Number of packets in queue private: void request(); @@ -93,7 +121,16 @@ namespace debug { Queue packets_; }; + + /** \brief Debug packet sink with active input + This module requests packets from the network. Each call to request() will pass a packet + request into the network. + + \note This module should not be used together with senf::ppi::run(). Instead use + senf::ppi::init() and explicit request() calls. It follows, that no events will be + signaled in the network. + */ class ActiveSink : public Module, public SafeBool @@ -105,11 +142,17 @@ namespace debug { ActiveSink(); - Packet request(); + Packet request(); ///< Request packet + /**< \pre boolean_test() is \c true */ - bool boolean_test() const; + bool boolean_test() const; ///< \c true, if \a input is not throttled }; + /** \brief Debug packet sink with passive input + + This module provides a queue for the network to write packets into. The packets can then + later be analyzed. + */ class PassiveSink : public Module { @@ -125,15 +168,15 @@ namespace debug { PassiveSink(); - bool empty(); - size_type size(); - iterator begin(); - iterator end(); + bool empty(); ///< \c true, if queue is empty + size_type size(); ///< number of packets in the queue + iterator begin(); ///< begin iterator of packets in the queue + iterator end(); ///< past-the-end iterator of packets in the queue - Packet front(); - Packet pop_front(); + Packet front(); ///< first packet in the queue + Packet pop_front(); ///< remove and return first packet in the queue - void clear(); + void clear(); ///< clear the queue private: void request(); @@ -141,6 +184,20 @@ namespace debug { Queue packets_; }; + /** \brief Active, queue-based packet source + + The ActiveFeederSource contains a packet queue containing the packets to be precessed. These + packets are actively fed into the network when it is run with senf::ppi::run() until it is + empty, when senf::ppi::run() will return. + + \note senf::ppi::run will return as soon as no events are active. If want you want is to + precess a set of packets placed into the ActiveFeederSource queue you must make sure, + that eventually all events in the module are disabled by throttling or other + activities. Otherwise, senf::ppi::run() will \e not return. + + ActiveFeederSource is not a module but a collection of two modules: a PassiveSource and an + ActiveFeeder. + */ class ActiveFeederSource { private: @@ -154,11 +211,25 @@ namespace debug { ActiveFeederSource(); - void submit(Packet packet); - bool empty(); - size_type size(); + void submit(Packet packet); ///< enqueue packet + bool empty(); ///< \c true, if queue is empty + size_type size(); ///< number of packets in the queue }; + /** \brief Active, queue-based packet sink + + The ActiveFeederSink contains a packet queue to receive the packets from the network. The + ActiveFeederSink will actively request packets from the network until it's input is + throttled. + + \note ActiveFeederSink does \e not have a termination condition like ActiveFeederSource, it + relies on the network to throttle it's input. Also, the same not as for + ActiveFeederSource applies here too: You need to ensure, that no events are active + eventually or senf::ppi::run will not return. + + ActiveFeederSink is not a module but a collection of two modules: a PassiveSink and an + ActiveFeeder. + */ class ActiveFeederSink { private: @@ -183,13 +254,35 @@ namespace debug { void clear(); }; + + /** \brief Log received packets + + This module will log all packets sent to it's input using SENF_LOG to the given log + \a Stream, \a Area and \a level. + */ + template < class Stream = log::Debug, + class Area = log::DefaultArea, + senf::log::Level level = log::VERBOSE > + class LogWriter + : public module::Module + { + SENF_PPI_MODULE(LogWriter); + public: + + connector::PassiveInput input; + + LogWriter(); + + private: + void request(); + }; }}}} ///////////////////////////////hh.e//////////////////////////////////////// #include "DebugModules.cci" //#include "DebugModules.ct" -//#include "DebugModules.cti" +#include "DebugModules.cti" #endif diff --git a/PPI/DebugModules.test.cc b/PPI/DebugModules.test.cc index 1f6f668..60cb8e8 100644 --- a/PPI/DebugModules.test.cc +++ b/PPI/DebugModules.test.cc @@ -26,8 +26,16 @@ //#include "DebubgModules.test.hh" //#include "DebubgModules.test.ih" + // Custom includes #include +#include + +#define _senf_LOG_STREAM logstream +namespace { + std::stringstream logstream; +} + #include "Packets/Packets.hh" #include "DebugModules.hh" #include "Setup.hh" @@ -97,9 +105,7 @@ BOOST_AUTO_UNIT_TEST(activeFeederSource) debug::PassiveSink sink; ppi::connect(source,sink); - source.submit(senf::DataPacket::create()); - ppi::run(); BOOST_CHECK( source.empty() ); @@ -113,9 +119,7 @@ BOOST_AUTO_UNIT_TEST(activeFeederSink) debug::ActiveFeederSink sink; ppi::connect(source,sink); - source.submit(senf::DataPacket::create()); - ppi::run(); BOOST_CHECK( ! sink.empty() ); @@ -128,6 +132,20 @@ BOOST_AUTO_UNIT_TEST(activeFeederSink) BOOST_CHECK( source.empty() ); } +BOOST_AUTO_UNIT_TEST(logWriter) +{ + debug::ActiveFeederSource source; + debug::LogWriter<> sink; + + ppi::connect(source,sink); + senf::PacketData::byte data[] = { 0x13u, 0x24u, 0x35u }; + source.submit( senf::DataPacket::create(data) ); + senf::ppi::run(); + + BOOST_CHECK_EQUAL( logstream.str(), + " 0000 13 24 35 .$5\n\n" ); +} + ///////////////////////////////cc.e//////////////////////////////////////// #undef prefix_ diff --git a/PPI/EventManager.hh b/PPI/EventManager.hh index 2df295f..482d17b 100644 --- a/PPI/EventManager.hh +++ b/PPI/EventManager.hh @@ -39,7 +39,11 @@ namespace senf { namespace ppi { - /** \brief + /** \brief Event registry and control + + The EventManager control event registration and manages global event parameters. The + EventManager controls event dispatch but does \e not control event generation. This is the + responsibility of an external component (the Scheduler) */ class EventManager { @@ -47,16 +51,13 @@ namespace ppi { /////////////////////////////////////////////////////////////////////////// // Types - template #ifndef DOXYGEN + // Somehow doxygen barfs on this definition + template struct Callback -#else - // This is SO stupid but doxygen must have some scoping problems if the - // struct is called 'Callback' and will hang in an endless loop somewhere - struct Callback_ -#endif : public detail::Callback {}; +#endif /////////////////////////////////////////////////////////////////////////// ///\name Structors and default members @@ -74,17 +75,17 @@ namespace ppi { ///@} /////////////////////////////////////////////////////////////////////////// + ClockService::clock_type now(); ///< Current time at last event dispatch + ClockService::clock_type time(); ///< Expected time of the last event + + protected: + + private: template void registerEvent(module::Module & module, typename Callback::type callback, Descriptor & descriptor); - ClockService::clock_type now(); - ClockService::clock_type time(); - - protected: - - private: void destroyModule(module::Module & module); typedef boost::ptr_vector EventRegistrations; diff --git a/PPI/Events.hh b/PPI/Events.hh index 1b99c4b..6f9c9c9 100644 --- a/PPI/Events.hh +++ b/PPI/Events.hh @@ -43,10 +43,9 @@ namespace ppi { // 'callback()' will access the EventBinding wrapper to find the user-callback to signal. It // will do any needed internal processing, call that user callback and clean up afterwards. - /** \brief Generic event interface baseclass + /** \brief Generic event interface base-class - The EventDescriptor baseclass provides an interface to manipulate events in a generic - way. This allows to register events or to temporarily disable event processing. + The EventDescriptor base-class provides an interface to control events. */ class EventDescriptor { @@ -78,6 +77,8 @@ namespace ppi { friend class ForwardingRoute; }; + /** \brief Internal: Callback forwarders + */ template class EventImplementationHelper { @@ -85,7 +86,13 @@ namespace ppi { typedef typename detail::EventArgType::type EventArg; void callback(EventArg event, ClockService::clock_type time); - void callback(EventArg event); + ///< Forward event to user callback + /**< \param[in] event Event argument to pass to the user + callback + \param[in] time Expected time of the event */ + void callback(EventArg event); ///< Forward event to user callback + /**< \param[in] event Event argument to pass to the user + callback. */ private: detail::EventBinding & binding(); @@ -106,6 +113,43 @@ namespace ppi { #endif + /** \brief Event implementation base class + + EventImplementation provides the base-class for all Event implementations. + \code + class SomeEvent : public EventImplementation + { + public: + SomeEvent() {} + + private: + virtual void v_enable() { + // register cb() to be called when the event occurs + } + + virtual void v_disable() { + // unregister cb() + } + + void cb() { + // Build event argument + SomeEventArg arg (...); + // Call the event callback + callback(arg); + } + }; + \endcode + + Every event needs to implement v_enable() and v_disable(). v_enable() should register some + member (in the example \c cb() ) to be called whenever the event occurs, while v_disable() + should unregister it. + + The \a EventType argument to EventImplementation defines the type of argument passed to the + user callback. It defaults to \c void. . This user callback is called from within the + registered member (e.g. \c cb() ) by calling the inherited callback() member. This member + takes an \a EventType reference as argument which will be forwarded to the user callback. If + available, you should also provide the \e expected event time as a second argument. + */ template class EventImplementation : public EventDescriptor, @@ -115,8 +159,8 @@ namespace ppi { typedef EventType Event; typedef typename detail::EventArgType::type EventArg; - module::Module & module() const; - EventManager & manager() const; + module::Module & module() const; ///< Module in which the event is registered + EventManager & manager() const; ///< EventManager of the event protected: EventImplementation(); diff --git a/PPI/Events.ih b/PPI/Events.ih index 1e342a0..d23e780 100644 --- a/PPI/Events.ih +++ b/PPI/Events.ih @@ -34,14 +34,14 @@ namespace senf { namespace ppi { namespace detail { +#ifndef DOXYGEN + template struct EventArgType { typedef EventType const & type; }; -#ifndef DOXYGEN - template <> struct EventArgType { diff --git a/PPI/IOEvent.hh b/PPI/IOEvent.hh index 9157622..f750530 100644 --- a/PPI/IOEvent.hh +++ b/PPI/IOEvent.hh @@ -36,12 +36,21 @@ namespace senf { namespace ppi { + /** \brief IOEvent event information + + Information passed to the IOEvent event handler + */ struct IOEventInfo { - unsigned events; + unsigned events; ///< Type of event signaled + /**< The value is a combination of the flags from + IOEvent::EventFlags */ }; - /** \brief + /** \brief FileHandle based I/O read/write event + + An IOEvent is signaled, whenever the FileHandle \a handle becomes readable or writable. The + type of event is specified using the \a events mask with values from EventFlags. \fixme Implement error/EOF handling */ diff --git a/PPI/IdleEvent.hh b/PPI/IdleEvent.hh index 3064380..1b7fc2d 100644 --- a/PPI/IdleEvent.hh +++ b/PPI/IdleEvent.hh @@ -35,6 +35,11 @@ namespace senf { namespace ppi { + /** \brief Continually signaled event + + An IdleEvent is signaled continually and repeatedly while enabled. It will consume 100% of + available CPU resources. The resource usage is controlled by adequate event throttling. + */ class IdleEvent : public EventImplementation<> { diff --git a/PPI/IntervalTimer.hh b/PPI/IntervalTimer.hh index cfb0631..798729a 100644 --- a/PPI/IntervalTimer.hh +++ b/PPI/IntervalTimer.hh @@ -36,14 +36,21 @@ namespace senf { namespace ppi { + /** \brief IntervalTimer event information + + Information passed to the IntervalTimer event handler + */ struct IntervalTimerEventInfo { - ClockService::clock_type expected; - ClockService::clock_type intervalStart; - unsigned number; + ClockService::clock_type expected; ///< Scheduled event time + ClockService::clock_type intervalStart; ///< Start of the current time interval + unsigned number; ///< Number of the current event within the interval }; - /** \brief + /** \brief High precision regularly signaled event. + + An IntervalTimer signals an event \a eventsPerInterval times each \a interval + nanoseconds. The event counter and timer are reset, whenever the event is disabled. */ class IntervalTimer : public EventImplementation diff --git a/PPI/Mainpage.dox b/PPI/Mainpage.dox index 861decf..2cd9212 100644 --- a/PPI/Mainpage.dox +++ b/PPI/Mainpage.dox @@ -394,6 +394,9 @@ \section class_diagram Class Diagram \image html classes.png + + \fixme Implement Spliters: PassiveSplitter, PrioritySplitter, CloneSplitter + \fixme Implement DiscardSink, CloneSource */ diff --git a/PPI/Module.hh b/PPI/Module.hh index 4b4323c..231b045 100644 --- a/PPI/Module.hh +++ b/PPI/Module.hh @@ -39,9 +39,9 @@ namespace senf { namespace ppi { namespace module { - /** \brief Module baseclass + /** \brief Module base-class - senf::ppi::Module is the baseclass of all PPI modules. It provides the module implementation + senf::ppi::Module is the base-class of all PPI modules. It provides the module implementation with interfaces to several PPI facilities: \li Connector management @@ -49,10 +49,77 @@ namespace module { \li Event handling To provide internal bookkeeping, most access to the PPI infrastructure is managed through - this base class. - - Instances of this class may be allocated either statically or dynamically. Dynamic instances - are automatically managed using the dynamicModule adaptor. + this base class. This is an example module specification: + \code + class SomeModule : public senf::ppi::module::Module + { + SENF_PPI_MODULE(SomeModule); + + senf::FileHandle handle; + + // If needed, define events + senf::ppi::IOEvent event; + + public: + // Define connectors. Any number and type of connectors may be defined. Connectors + // must be public since they need to be accessed to connect modules with each other. + senf::ppi::connector::PassiveInput input; + senf::ppi::connector::ActiveOutput output; + + SomeModule(senf::FileHandle h) + : handle ( h ), + event ( handle, senf::ppi::IOEvent::Read ) + { + // Set up routing. If some connector is not routed you need to explicitly state this + // using noroute() + route( input, output ); + route( event, output ) + .autoThrottling( false ); + + // Register event handlers + registerEvent( &SomeModule::read, event ); + + // Register passive connector handlers + input.onRequest( &SomeModule::outputRequest ); + + // If needed, you may register throttling event handlers + output.onThrottle( &SomeModule::throttle ); + output.onUnthrottle( &SomeModule::unthrottle ); + } + + void read() { + // Called whenever the 'handle' is readable. Read data, do processing and so + // on. This example reads the data, puts it into an ethernet packet and sends the + // packet out via the active output. + output(senf::EthernetPacket::create(handle.read())) + } + + void outputRequest() { + // Called whenever a packet is sent into the input to. Here we just forward it to + // the output if it is an EthernetPacket + senf::EthernetPacket p (input().find(senf::nothrow)); + if (p) + output(p); + } + + void onThrottle() { + // Called whenever a throttle notification comes in. Here, we just disable the + // event (which is stupid since we should just not have disabled autoThrottling on + // the route but this is only an example which tries to be simple ...) + event.disable(); + } + + void onUnthrottle() { + // and for unthrottle notifications + event.enable(); + } + + }; + \endcode + + If your module only has a single input connector, you should call this connector \c + input. If it has only a single output connector, you should call it \c output. This allows + to setup connections without stating the connector explicitly (see senf::ppi::connect()). */ class Module : boost::noncopyable @@ -108,9 +175,9 @@ namespace module { callable object or it may be a member function pointer pointing to a member function of the Module derived classed. The handler may \e optionally take an Argument - of type typename Descriptor::Event const - &. This object allows to access detailed - information on the event delivered. + of type Descriptor::Event const &. This object + allows to access detailed information on the event + delivered. The \a descriptor describes the event to signal. This @@ -121,10 +188,11 @@ namespace module { event is signaled \param[in] descriptor The type of event to register */ - ClockService::clock_type time() const; ///< Return timestamp of the currently processing - ///< event + ClockService::clock_type time() const; ///< Time-stamp of the currently processing event + /**< If available, this returns the scheduled time of the + event. */ - ClockService::clock_type now() const; + ClockService::clock_type now() const; ///< Current time of the currently processing event #ifndef DOXYGEN virtual void macro_SENF_PPI_MODULE_missing() = 0; diff --git a/PPI/Module.ih b/PPI/Module.ih index 697fa7b..3386687 100644 --- a/PPI/Module.ih +++ b/PPI/Module.ih @@ -33,6 +33,8 @@ namespace ppi { namespace module { namespace detail { +#ifndef DOXYGEN + // Placing these into a class simplifies the friend declaration template struct RouteHelper @@ -50,6 +52,8 @@ namespace detail { EventDescriptor &, connector::OutputConnector &); }; + +#endif }}}} diff --git a/PPI/ModuleManager.cc b/PPI/ModuleManager.cc index bda5e66..25c771e 100644 --- a/PPI/ModuleManager.cc +++ b/PPI/ModuleManager.cc @@ -45,6 +45,8 @@ prefix_ void senf::ppi::ModuleManager::init() (*i)->init(); } +#ifndef DOXYGEN + struct senf::ppi::ModuleManager::RunGuard { RunGuard(ModuleManager & m) : manager(m) { manager.running_ = true; } @@ -52,6 +54,8 @@ struct senf::ppi::ModuleManager::RunGuard ModuleManager & manager; }; +#endif + prefix_ void senf::ppi::ModuleManager::run() { init(); diff --git a/PPI/ModuleManager.hh b/PPI/ModuleManager.hh index 843562b..b944123 100644 --- a/PPI/ModuleManager.hh +++ b/PPI/ModuleManager.hh @@ -70,8 +70,10 @@ namespace ppi { typedef std::vector ModuleRegistry; +#ifndef DOXYGEN struct RunGuard; friend class RunGuard; +#endif ModuleRegistry moduleRegistry_; bool running_; diff --git a/PPI/Route.hh b/PPI/Route.hh index 88722c2..307d341 100644 --- a/PPI/Route.hh +++ b/PPI/Route.hh @@ -34,6 +34,11 @@ namespace senf { namespace ppi { + /** \brief Routing base class + + Routing information is defined within each module to define the control flow. RouteBase is + the generic base class for all routing entries. + */ class RouteBase { public: @@ -46,11 +51,17 @@ namespace ppi { module::Module * module_; }; + /** \brief Forwarding route base class + + All routes which may forward control information are based on + ForwardingRoute. ForwardingRoute provides methods to control and query the throttling + behavior. + */ class ForwardingRoute : public RouteBase { public: - bool autoThrottling() const; + bool autoThrottling() const; ///< Query current autoThrottling state void autoThrottling(bool state); ///< Change automatic throttle notification forwarding /**< By default, throttle notifications are automatically forwarded from active to passive connectors. This may @@ -66,7 +77,10 @@ namespace ppi { \param[in] state New throttle forwarding state */ - bool throttled() const; + bool throttled() const; ///< \c true, if the route is throttled + /**< This member checks only the automatic throttling + state. If autoThrottling() is \c false, this member + will always return \c false. */ protected: ForwardingRoute(module::Module & module); @@ -104,13 +118,17 @@ namespace ppi { Route instances are created by Module::route statements. The Route class provides an interface to manipulate the flow processing. + + The concrete interface provided depends on the type of route. If the route is a forwarding + route, it will be based on ForwardingRoute otherwise it will be based directly on + RouteBase. */ template class Route : public detail::RouteImplementation { - typedef detail::RouteImplementation Base; private: + typedef detail::RouteImplementation Base; typedef detail::RouteImplementation Implementation; Route(module::Module & module, Source & source, Target & target); diff --git a/PPI/Route.ih b/PPI/Route.ih index 7637d3e..46b7e8a 100644 --- a/PPI/Route.ih +++ b/PPI/Route.ih @@ -35,6 +35,8 @@ ///////////////////////////////ih.p//////////////////////////////////////// +#ifndef DOXYGEN + namespace senf { namespace ppi { namespace detail { @@ -59,8 +61,6 @@ namespace detail { typedef Connector type; }; -#ifndef DOXYGEN - // RoutingTraits specialization for Event types. Events may be both dataSource or dataTarget but // cannot be notifySource. template @@ -75,8 +75,6 @@ namespace detail { typedef EventDescriptor type; }; -#endif - // The RoutingTraits give routing related information about the argument type: // - Wether the type is a notifySource or notifyTarget // - Wether the type is dataSource or dataTarget @@ -203,6 +201,8 @@ namespace detail { }}} +#endif + ///////////////////////////////ih.e//////////////////////////////////////// #endif diff --git a/PPI/SocketReader.hh b/PPI/SocketReader.hh index 5c0ca9e..f416c0d 100644 --- a/PPI/SocketReader.hh +++ b/PPI/SocketReader.hh @@ -81,11 +81,16 @@ namespace module { class SomeReader { public: - typedef unspecified_type Handle; // type of handle requested - SomeReader(); // default constructible - Packet::ptr operator()(Handle handle); // extraction function + typedef unspecified_type Handle; // type of handle requested + SomeReader(); // default constructible + Packet operator()(Handle handle); // extraction function }; \endcode + + Whenever the FileHandle object is ready for reading, the \a Reader's \c operator() is called + to read a packet. The default \a Reader is \c PacketReader<>, which will read packets from a + datagram SocketHandle into DataPacket's. You may + */ template > class ActiveSocketReader diff --git a/PPI/detail/EventBinding.hh b/PPI/detail/EventBinding.hh index e60ab58..05ade30 100644 --- a/PPI/detail/EventBinding.hh +++ b/PPI/detail/EventBinding.hh @@ -38,6 +38,7 @@ namespace senf { namespace ppi { namespace detail { + /** \brief Internal: Association Event - Module - Handler, base-class */ class EventBindingBase { public: @@ -60,6 +61,8 @@ namespace detail { friend class senf::ppi::EventManager; }; + /** \brief Internal: Callback forwarders + */ template class EventBindingHelper { @@ -88,6 +91,7 @@ namespace detail { #endif + /** \brief Internal: Association Event - Module - Handler, event type specific */ template class EventBinding : public EventBindingBase, diff --git a/PPI/predecl.hh b/PPI/predecl.hh index 8fb57dd..92c0546 100644 --- a/PPI/predecl.hh +++ b/PPI/predecl.hh @@ -43,6 +43,8 @@ namespace ppi { class QueueingDiscipline; class ModuleManager; +#ifndef DOXYGEN + namespace detail { class EventBindingBase; template class EventBinding; @@ -58,6 +60,8 @@ namespace ppi { class RouteImplementation; } +#endif + namespace module { class Module; namespace detail { diff --git a/Utils/Logger.hh b/Utils/Logger.hh index 99880a8..c766392 100644 --- a/Utils/Logger.hh +++ b/Utils/Logger.hh @@ -121,6 +121,7 @@ ///////////////////////////////hh.p//////////////////////////////////////// namespace senf { +namespace log { # ifndef _senf_LOG_STREAM # define _senf_LOG_STREAM std::cerr @@ -181,7 +182,7 @@ namespace senf { \hideinitializer */ -# define SENF_LOG_DEF_AREA(area) +# define SENF_LOG_DEF_AREA(area) struct area {} /** \brief Define log stream @@ -190,7 +191,7 @@ namespace senf { \hideinitializer */ -# define SENF_LOG_DEF_STREAM(stream) +# define SENF_LOG_DEF_STREAM(stream) struct stream {} /** \brief Define log parameter alias @@ -199,11 +200,16 @@ namespace senf { \hideinitializer */ -# define SENF_LOG_DEF_ALIAS(alias,args) +# define SENF_LOG_DEF_ALIAS(alias,args) struct alias {} /// @} -} + enum Level { VERBOSE, NOTICE, MESSAGE, IMPORTANT, CRITICAL }; + + SENF_LOG_DEF_STREAM(Debug); + SENF_LOG_DEF_AREA(DefaultArea); + +}} ///////////////////////////////hh.e//////////////////////////////////////// //#include "Logger.cci" diff --git a/senf.dict b/senf.dict index 362d243..8fec9c3 100644 --- a/senf.dict +++ b/senf.dict @@ -1,18 +1,28 @@ acceptfrom accessor +ActiveConnector +ActiveFeeder +ActiveFeederSink +ActiveFeederSource +ActiveInput +ActiveOutput +ActiveSink +ActiveSource addr AddressingPolicy AddressingPolicyBase addtogroup aListCollection alloc +arg async +autoThrottling aVectorCollection BaseParser berlios bitfield bund -Callback +callback callbacks cb cerr @@ -29,9 +39,11 @@ createBefore DataPacket dd de +DebugModules DefaultBundle defaultInit defgroup +deque dil DNS dontinclude @@ -47,6 +59,12 @@ ethertype EthVLan EUI EUID +EventBinding +EventDescriptor +EventImplementation +EventManager +eventsPerInterval +EventType ExampleListPolicy ExampleVectorPolicy ExtendedParser @@ -59,6 +77,7 @@ findPrev fixme fokus FooParser +ForwardingRoute fraunhofer fuer GlobalScope @@ -72,6 +91,7 @@ htm html http IANA +IdleEvent ih impl INet @@ -80,10 +100,13 @@ init initHeadSize initSize inline +InputConnector Institut Int +IntervalTimer IntField InvalidPacketChainException +IOEvent ip IpV ipv @@ -111,15 +134,21 @@ nextPacketType NIS NoAddressingPolicy noinit +noroute nothrow offene Ok +onRequest +onThrottle +onUnthrottle Ooops org os ostream OtherPacket OtherPacketType +OutputConnector +outputRequest OverlayField PacketData PacketImpl @@ -146,12 +175,21 @@ ParseListB ParseListN parseNextAs ParseVec +PassiveConnector +PassiveInput +PassiveOutput +PassiveSink +PassiveSource png +ppi pre prev protocolbundle protocolbundles +QueueingDiscipline +queueSize refcount +registerEvent registerPacket registerPacketType registerSomePacket @@ -174,7 +212,10 @@ SiteScope SizeParser skipline SocketHandle +SomeEvent +SomeEventArg someField +SomeModule someOtherField SomePacket SomePacketParser @@ -192,6 +233,7 @@ SyntaxException SystemException td templated +ThresholdQueueing todo tr TruncatedPacketException @@ -203,6 +245,9 @@ UDPPacket UInt UIntField unicast +unthrottle +unthrottles +unthrottling VectorN vlanId VLanId