PPI: Add optional template arg for packet type to connectors
[senf.git] / PPI / DebugModules.hh
index 1a38d4b..60ac7e5 100644 (file)
@@ -1,8 +1,8 @@
 // $Id$
 //
 // Copyright (C) 2007 
-// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
-// Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
+// Fraunhofer Institute for Open Communication Systems (FOKUS) 
+// Competence Center NETwork research (NET), St. Augustin, GERMANY 
 //     Stefan Bund <g0dil@berlios.de>
 //
 // This program is free software; you can redistribute it and/or modify
 
 // Custom includes
 #include <deque>
-#include "Utils/SafeBool.hh"
-#include "Packets/Packets.hh"
+#include "../Utils/safe_bool.hh"
+#include "../Packets/Packets.hh"
 #include "Module.hh"
+#include "ActiveFeeder.hh"
+#include "../Utils/Logger/SenfLog.hh"
 
 //#include "DebugModules.mpp"
 ///////////////////////////////hh.p////////////////////////////////////////
@@ -40,36 +42,81 @@ namespace ppi {
 namespace module {
 namespace debug {
     
-    class ActivePacketSource
+    /** \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 <i>Active modules</i> (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 <i>Passive modules</i> (PassiveSource, PassiveSink) contain a queue to save packets
+            (either packets to be transmitted or packets received) and are driven by the network.
+        \li <i>Feeder (almost-)modules</i> (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 <em>no events will be
+            signaled in the network</em>.
+     */
+    class ActiveSource
         : public Module, 
-          public SafeBool<ActivePacketSource>
+          public safe_bool<ActiveSource>
     {
+        SENF_PPI_MODULE(ActiveSource);
+
     public:
-        connector::ActiveOutput output;
+        connector::ActiveOutput<> output;
 
-        ActivePacketSource();
+        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
     };
 
-    class PassivePacketSource
+    /** \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
     {
+        SENF_PPI_MODULE(PassiveSource);
+
         typedef std::deque<Packet> Queue;
 
     public:
         typedef Queue::size_type size_type;
         
-        PassivePacketSource();
-        
-        connector::PassiveOutput output;
+        connector::PassiveOutput<> output;
+
+        PassiveSource();
+
+        void throttle();                ///< Throttle output connector
+        void unthrottle();              ///< Unthrottle output connector
         
-        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();
@@ -77,33 +124,131 @@ namespace debug {
         
         Queue packets_;
     };
+    
+    /** \brief Debug packet sink with active input
 
-    class ActivePacketSink
+        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 <em>no events will be
+            signaled in the network</em>.
+     */
+    class ActiveSink
         : public Module,
-          public SafeBool<ActivePacketSink>
+          public safe_bool<ActiveSink>
     {
+        SENF_PPI_MODULE(ActiveSink);
+
     public:
-        connector::ActiveInput input;
+        connector::ActiveInput<> input;
 
-        ActivePacketSink();
+        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
     };
 
-    class PassivePacketSink
+    /** \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
     {
+        SENF_PPI_MODULE(PassiveSink);
+
         typedef std::deque<Packet> Queue;
 
     public:
         typedef Queue::size_type size_type;
         typedef Queue::const_iterator iterator;
 
-        connector::PassiveInput input;
+        connector::PassiveInput<> input;
+
+        PassiveSink();
+
+        void throttle();                ///< Throttle input connection
+        void unthrottle();              ///< Unthrottle input connection
+
+        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();                 ///< first packet in the queue
+        Packet pop_front();             ///< remove and return first packet in the queue
+
+        void clear();                   ///< clear the queue
+
+    private:
+        void request();
         
-        PassivePacketSink();
+        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:
+        PassiveSource source;
+        ActiveFeeder feeder;
+
+    public:
+        typedef PassiveSource::size_type size_type;
+        
+        connector::ActiveOutput<> & output;
+
+        ActiveFeederSource();
+
+        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:
+        PassiveSink sink;
+        ActiveFeeder feeder;
+
+    public:
+        typedef PassiveSink::size_type size_type;
+        typedef PassiveSink::iterator iterator;
+
+        connector::ActiveInput<> & input;
+        
+        ActiveFeederSink();
 
         bool empty();
         size_type size();
@@ -114,11 +259,28 @@ namespace debug {
         Packet pop_front();
 
         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, 
+               class Level  = log::VERBOSE >
+    class LogSink
+        : public module::Module
+    {
+        SENF_PPI_MODULE(LogSink);
+    public:
+
+        connector::PassiveInput<> input;
+
+        LogSink();
 
     private:
         void request();
-        
-        Queue packets_;
     };
 
 }}}}
@@ -126,7 +288,7 @@ namespace debug {
 ///////////////////////////////hh.e////////////////////////////////////////
 #include "DebugModules.cci"
 //#include "DebugModules.ct"
-//#include "DebugModules.cti"
+#include "DebugModules.cti"
 #endif
 
 \f