switch to new MPL based Fraunhofer FOKUS Public License
[senf.git] / senf / PPI / DebugModules.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 //
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at 
9 // http://senf.berlios.de/license.html
10 //
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on, 
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
14 //
15 // Software distributed under the License is distributed on an "AS IS" basis, 
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 
17 // for the specific language governing rights and limitations under the License.
18 //
19 // The Original Code is Fraunhofer FOKUS code.
20 //
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V. 
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
24 //
25 // Contributor(s):
26 //   Stefan Bund <g0dil@berlios.de>
27
28 /** \file
29     \brief DebugModules public header */
30
31 #ifndef HH_SENF_PPI_DebugModules_
32 #define HH_SENF_PPI_DebugModules_ 1
33
34 // Custom includes
35 #include <deque>
36 #include <senf/Utils/safe_bool.hh>
37 #include "MonitorModule.hh"
38 #include "ActiveFeeder.hh"
39 #include <senf/Utils/Logger/SenfLog.hh>
40
41 //#include "DebugModules.mpp"
42 //-/////////////////////////////////////////////////////////////////////////////////////////////////
43
44 namespace senf {
45 namespace ppi {
46 namespace module {
47 namespace debug {
48
49     /** \namespace senf::ppi::module::debug
50         \brief Debug modules
51
52         This namespace collects several modules helpful for PPI debugging. The modules allow to
53         manually pass packets into a network and read back the output packets.
54
55         There are three categories of modules:
56
57         \li <i>Active modules</i> (ActiveSource, ActiveSink) are triggered by external
58             calls. Calling \c submit() / \c request() will send the request into the module network
59             synchronously. From this it follows, that senf::ppi::run() should \e not be
60             called. Instead senf::ppi::init() is used to initialize the network and explicit calls
61             to the active debug modules drive the execution.
62         \li <i>Passive modules</i> (PassiveSource, PassiveSink) contain a queue to save packets
63             (either packets to be transmitted or packets received) and are driven by the network.
64         \li <i>Feeder (almost-)modules</i> (ActiveFeederSource, ActiveFeederSink) are a hybrid of
65             both types of modules: They contain a packet queue but actively drive the network and
66             are used together with senf::ppi::run(). senf::ppi::run() will automatically terminate
67             if all available packets have been processed. These are not modules, they are
68             collections combining a passive debug module and a senf::ppi::ActiveFeeder.
69      */
70
71     /** \brief Debug packet source with active output
72
73         This module provides packets into the network. Each call to submit() will process the packet
74         synchronously.
75
76         \note This module should not be used together with senf::ppi::run(). Instead use
77             senf::ppi::init() and explicit submit() calls. It follows, that <em>no events will be
78             signaled in the network</em>.
79      */
80     class ActiveSource
81         : public Module,
82           public safe_bool<ActiveSource>
83     {
84         SENF_PPI_MODULE(ActiveSource);
85
86     public:
87         connector::ActiveOutput<> output;
88
89         ActiveSource();
90
91         void submit(Packet const & packet);     ///< Submit packet
92                                         /**< \pre boolean_test() is \c true */
93
94         bool boolean_test() const;      ///< \c true if \a output is not throttled
95     };
96
97     /** \brief Debug packet source with passive output
98
99         This module provides a queue of packets for reading by the network. Each submit() call adds
100         a packet to the queue which will be sent into the network when requested. The output is
101         automatically throttled when the queue becomes empty.
102      */
103     class PassiveSource
104         : public Module
105     {
106         SENF_PPI_MODULE(PassiveSource);
107
108         typedef std::deque<Packet> Queue;
109
110     public:
111         typedef Queue::size_type size_type;
112
113         connector::PassiveOutput<> output;
114
115         PassiveSource();
116
117         void throttle();                ///< Throttle output connector
118         void unthrottle();              ///< Unthrottle output connector
119
120         void submit(Packet const & packet);     ///< Enqueue packet
121
122         bool empty();                   ///< \c true if queue is empty
123         size_type size();               ///< Number of packets in queue
124
125     private:
126         void request();
127         virtual void v_init();
128
129         Queue packets_;
130     };
131
132     /** \brief Debug packet sink with active input
133
134         This module requests packets from the network. Each call to request() will pass a packet
135         request into the network.
136
137         \note This module should not be used together with senf::ppi::run(). Instead use
138             senf::ppi::init() and explicit request() calls. It follows, that <em>no events will be
139             signaled in the network</em>.
140      */
141     class ActiveSink
142         : public Module,
143           public safe_bool<ActiveSink>
144     {
145         SENF_PPI_MODULE(ActiveSink);
146
147     public:
148         connector::ActiveInput<> input;
149
150         ActiveSink();
151
152         Packet request();               ///< Request packet
153                                         /**< \pre boolean_test() is \c true */
154
155         bool boolean_test() const;      ///< \c true, if \a input is not throttled
156     };
157
158     /** \brief Debug packet sink with passive input
159
160         This module provides a queue for the network to write packets into. The packets can then
161         later be analyzed.
162      */
163     class PassiveSink
164         : public Module
165     {
166         SENF_PPI_MODULE(PassiveSink);
167
168         typedef std::deque<Packet> Queue;
169
170     public:
171         typedef Queue::size_type size_type;
172         typedef Queue::const_iterator iterator;
173
174         connector::PassiveInput<> input;
175
176         PassiveSink();
177
178         void throttle();                ///< Throttle input connection
179         void unthrottle();              ///< Unthrottle input connection
180
181         bool empty();                   ///< \c true, if queue is empty
182         size_type size();               ///< number of packets in the queue
183         iterator begin();               ///< begin iterator of packets in the queue
184         iterator end();                 ///< past-the-end iterator of packets in the queue
185
186         Packet front();                 ///< first packet in the queue
187         Packet pop_front();             ///< remove and return first packet in the queue
188
189         void clear();                   ///< clear the queue
190
191     private:
192         void request();
193
194         Queue packets_;
195     };
196
197     /** \brief Active, queue-based packet source
198
199         The ActiveFeederSource contains a packet queue containing the packets to be processed. These
200         packets are actively fed into the network when it is run with senf::ppi::run() until it is
201         empty, when senf::ppi::run() will return.
202
203         \note senf::ppi::run will return as soon as no events are active. If want you want is to
204             Process a set of packets placed into the ActiveFeederSource queue you must make sure,
205             that eventually all events in the module are disabled by throttling or other
206             activities. Otherwise, senf::ppi::run() will \e not return.
207
208         ActiveFeederSource is not a module but a collection of two modules: a PassiveSource and an
209         ActiveFeeder.
210      */
211     class ActiveFeederSource
212     {
213     private:
214         PassiveSource source;
215         ActiveFeeder feeder;
216
217     public:
218         typedef PassiveSource::size_type size_type;
219
220         connector::ActiveOutput<> & output;
221
222         ActiveFeederSource();
223
224         void submit(Packet packet);     ///< enqueue packet
225         bool empty();                   ///< \c true, if queue is empty
226         size_type size();               ///< number of packets in the queue
227     };
228
229     /** \brief Active, queue-based packet sink
230
231         The ActiveFeederSink contains a packet queue to receive the packets from the network. The
232         ActiveFeederSink will actively request packets from the network until it's input is
233         throttled.
234
235         \note ActiveFeederSink does \e not have a termination condition like ActiveFeederSource, it
236             relies on the network to throttle it's input. Additionally, the restrictions of
237             ActiveFeederSource apply here too: You need to ensure, that no (additional) events are
238             active (eventually) or senf::ppi::run will not return.
239
240         ActiveFeederSink is not a module but a collection of two modules: a PassiveSink and an
241         ActiveFeeder.
242      */
243     class ActiveFeederSink
244     {
245     private:
246         PassiveSink sink;
247         ActiveFeeder feeder;
248
249     public:
250         typedef PassiveSink::size_type size_type;
251         typedef PassiveSink::iterator iterator;
252
253         connector::ActiveInput<> & input;
254
255         ActiveFeederSink();
256
257         bool empty();
258         size_type size();
259         iterator begin();
260         iterator end();
261
262         Packet front();
263         Packet pop_front();
264
265         void clear();
266     };
267
268     /** \brief Log received packets
269
270         This module will %log all packets sent to it's input using SENF_LOG to the given %log
271         \a Stream, \a Area and \a Level.
272      */
273     template < class Stream = log::Debug,
274                class Area   = log::DefaultArea,
275                class Level  = log::VERBOSE >
276     class Logger
277         : public MonitorModule<>
278     {
279         SENF_PPI_MODULE(Logger);
280     public:
281         Logger();
282         explicit Logger(std::string label);
283
284     private:
285         virtual void v_handlePacket(Packet const & packet);
286
287         std::string label_;
288     };
289
290 }}}}
291
292 //-/////////////////////////////////////////////////////////////////////////////////////////////////
293 #include "DebugModules.cci"
294 //#include "DebugModules.ct"
295 #include "DebugModules.cti"
296 #endif
297
298 \f
299 // Local Variables:
300 // mode: c++
301 // fill-column: 100
302 // comment-column: 40
303 // c-file-style: "senf"
304 // indent-tabs-mode: nil
305 // ispell-local-dictionary: "american"
306 // compile-command: "scons -u test"
307 // End: