296dfc5dcc643182aa9a3bb43a0bbd55708f3b18
[senf.git] / PPI / DebugModules.hh
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
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_DebugModules_
27 #define HH_DebugModules_ 1
28
29 // Custom includes
30 #include <deque>
31 #include "Utils/SafeBool.hh"
32 #include "Packets/Packets.hh"
33 #include "Module.hh"
34 #include "ActiveFeeder.hh"
35 #include "Utils/Logger.hh"
36
37 //#include "DebugModules.mpp"
38 ///////////////////////////////hh.p////////////////////////////////////////
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 SafeBool<ActiveSource>
79     {
80         SENF_PPI_MODULE(ActiveSource);
81
82     public:
83         connector::ActiveOutput output;
84
85         ActiveSource();
86
87         void submit(Packet 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 submit(Packet packet);     ///< Enqueue packet
114
115         bool empty();                   ///< \c true if queue is empty
116         size_type size();               ///< Number of packets in queue
117
118     private:
119         void request();
120         void init();
121         
122         Queue packets_;
123     };
124     
125     /** \brief Debug packet sink with active input
126
127         This module requests packets from the network. Each call to request() will pass a packet
128         request into the network.
129
130         \note This module should not be used together with senf::ppi::run(). Instead use
131             senf::ppi::init() and explicit request() calls. It follows, that <em>no events will be
132             signaled in the network</em>.
133      */
134     class ActiveSink
135         : public Module,
136           public SafeBool<ActiveSink>
137     {
138         SENF_PPI_MODULE(ActiveSink);
139
140     public:
141         connector::ActiveInput input;
142
143         ActiveSink();
144
145         Packet request();               ///< Request packet
146                                         /**< \pre boolean_test() is \c true */
147
148         bool boolean_test() const;      ///< \c true, if \a input is not throttled
149     };
150
151     /** \brief Debug packet sink with passive input
152
153         This module provides a queue for the network to write packets into. The packets can then
154         later be analyzed.
155      */
156     class PassiveSink
157         : public Module
158     {
159         SENF_PPI_MODULE(PassiveSink);
160
161         typedef std::deque<Packet> Queue;
162
163     public:
164         typedef Queue::size_type size_type;
165         typedef Queue::const_iterator iterator;
166
167         connector::PassiveInput input;
168         
169         PassiveSink();
170
171         bool empty();                   ///< \c true, if queue is empty
172         size_type size();               ///< number of packets in the queue
173         iterator begin();               ///< begin iterator of packets in the queue
174         iterator end();                 ///< past-the-end iterator of packets in the queue
175
176         Packet front();                 ///< first packet in the queue
177         Packet pop_front();             ///< remove and return first packet in the queue
178
179         void clear();                   ///< clear the queue
180
181     private:
182         void request();
183         
184         Queue packets_;
185     };
186
187     /** \brief Active, queue-based packet source
188         
189         The ActiveFeederSource contains a packet queue containing the packets to be precessed. These
190         packets are actively fed into the network when it is run with senf::ppi::run() until it is
191         empty, when senf::ppi::run() will return.
192
193         \note senf::ppi::run will return as soon as no events are active. If want you want is to
194             precess a set of packets placed into the ActiveFeederSource queue you must make sure,
195             that eventually all events in the module are disabled by throttling or other
196             activities. Otherwise, senf::ppi::run() will \e not return.
197
198         ActiveFeederSource is not a module but a collection of two modules: a PassiveSource and an
199         ActiveFeeder.
200      */
201     class ActiveFeederSource
202     {
203     private:
204         PassiveSource source;
205         ActiveFeeder feeder;
206
207     public:
208         typedef PassiveSource::size_type size_type;
209         
210         connector::ActiveOutput & output;
211
212         ActiveFeederSource();
213
214         void submit(Packet packet);     ///< enqueue packet
215         bool empty();                   ///< \c true, if queue is empty
216         size_type size();               ///< number of packets in the queue
217     };
218
219     /** \brief Active, queue-based packet sink
220     
221         The ActiveFeederSink contains a packet queue to receive the packets from the network. The
222         ActiveFeederSink will actively request packets from the network until it's input is
223         throttled.
224
225         \note ActiveFeederSink does \e not have a termination condition like ActiveFeederSource, it
226             relies on the network to throttle it's input. Also, the same not as for
227             ActiveFeederSource applies here too: You need to ensure, that no events are active
228             eventually or senf::ppi::run will not return.
229
230         ActiveFeederSink is not a module but a collection of two modules: a PassiveSink and an
231         ActiveFeeder. 
232      */
233     class ActiveFeederSink
234     {
235     private:
236         PassiveSink sink;
237         ActiveFeeder feeder;
238
239     public:
240         typedef PassiveSink::size_type size_type;
241         typedef PassiveSink::iterator iterator;
242
243         connector::ActiveInput & input;
244         
245         ActiveFeederSink();
246
247         bool empty();
248         size_type size();
249         iterator begin();
250         iterator end();
251
252         Packet front();
253         Packet pop_front();
254
255         void clear();
256     };
257    
258     /** \brief Log received packets
259
260         This module will log all packets sent to it's input using SENF_LOG to the given log
261         \a Stream, \a Area and \a level.
262      */
263     template < class Stream           = log::Debug, 
264                class Area             = log::DefaultArea, 
265                senf::log::Level level = log::VERBOSE >
266     class LogWriter
267         : public module::Module
268     {
269         SENF_PPI_MODULE(LogWriter);
270     public:
271
272         connector::PassiveInput input;
273
274         LogWriter();
275
276     private:
277         void request();
278     };
279
280 }}}}
281
282 ///////////////////////////////hh.e////////////////////////////////////////
283 #include "DebugModules.cci"
284 //#include "DebugModules.ct"
285 #include "DebugModules.cti"
286 #endif
287
288 \f
289 // Local Variables:
290 // mode: c++
291 // fill-column: 100
292 // comment-column: 40
293 // c-file-style: "senf"
294 // indent-tabs-mode: nil
295 // ispell-local-dictionary: "american"
296 // compile-command: "scons -u test"
297 // End: