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