root/branches/streaming-rework/src/debugmodule/debugmodule.cpp

Revision 385, 11.3 kB (checked in by pieterpalmers, 17 years ago)

- fixed issues with SYT timestamp processing
- SYT based sync works if syncing to the received stream

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 /* debugmodule.cpp
2  * Copyright (C) 2005 by Daniel Wagner
3  *
4  * This file is part of FreeBoB.
5  *
6  * FreeBoB is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * FreeBoB is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with FreeBoB; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
18  * MA 02111-1307 USA.
19  */
20
21 #include "debugmodule.h"
22
23 #include <stdarg.h>
24 #include <netinet/in.h>
25
26 #include <iostream>
27
28 using namespace std;
29
30 struct ColorEntry  {
31     const char* preSequence;
32     const char* postSequence;
33 };
34
35 ColorEntry colorTable[] = {
36     { "\033[31mFatal",   "\033[0m" },
37     { "\033[31mError",   "\033[0m" },
38     { "\033[31mWarning", "\033[0m" },
39     { "Debug",           ""        },
40 };
41
42
43 DebugModule::DebugModule( std::string name,  debug_level_t level )
44     : m_name( name )
45     , m_level( level )
46 {
47     if ( !DebugModuleManager::instance()->registerModule( *this ) ) {
48         cerr << "Could not register DebugModule (" << name
49              << ") at DebugModuleManager"
50              << endl;
51     }
52 }
53
54 DebugModule::~DebugModule()
55 {
56     if ( m_level >= eDL_VeryVerbose ) {
57         cout << "Unregistering "
58              << this->getName()
59              << " at DebugModuleManager"
60              << endl;
61     }
62     if ( !DebugModuleManager::instance()->unregisterModule( *this ) ) {
63         cerr << "Could not unregister DebugModule at DebugModuleManager"
64              << endl;
65     }
66
67 }
68
69 void
70 DebugModule::printShort( debug_level_t level,
71                          const char* format,
72                          ... ) const
73 {
74     if ( level > m_level ) {
75         return;
76     }
77
78     va_list arg;
79
80     va_start( arg, format );
81
82     DebugModuleManager::instance()->va_print( format, arg );
83
84     va_end( arg );
85 }
86
87 void
88 DebugModule::print( debug_level_t level,
89                     const char*   file,
90                     const char*   function,
91                     unsigned int  line,
92                     const char*   format,
93                     ... ) const
94 {
95     if ( level > m_level ) {
96         return;
97     }
98
99     va_list arg;
100     va_start( arg, format );
101     DebugModuleManager::instance()->print( "%s (%s)[%4d] %s: ", getPreSequence( level ),
102                  file,  line,  function );
103     DebugModuleManager::instance()->va_print( format, arg );
104     DebugModuleManager::instance()->print( "%s", getPostSequence( level ) );
105     va_end( arg );
106 }
107
108 const char*
109 DebugModule::getPreSequence( debug_level_t level ) const
110 {
111     if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) {
112         return colorTable[level].preSequence;
113     }
114     return colorTable[eDL_Normal].preSequence;
115 }
116
117 const char*
118 DebugModule::getPostSequence( debug_level_t level ) const
119 {
120     if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) {
121         return colorTable[level].postSequence;
122     }
123     return colorTable[eDL_Normal].postSequence;
124 }
125
126 //--------------------------------------
127
128 DebugModuleManager* DebugModuleManager::m_instance = 0;
129
130 DebugModuleManager::DebugModuleManager()
131     : mb_initialized(0)
132     , mb_inbuffer(0)
133     , mb_outbuffer(0)
134     , mb_overruns(0)
135
136 {
137
138 }
139
140 DebugModuleManager::~DebugModuleManager()
141 {
142         // cleanin up leftover modules
143     for ( DebugModuleVectorIterator it = m_debugModules.begin();
144           it != m_debugModules.end();
145           ++it )
146     {
147         fprintf(stderr,"Cleaning up leftover debug module: %s\n",(*it)->getName().c_str());
148         m_debugModules.erase( it );
149         delete *it;
150     }
151
152         if (!mb_initialized)
153                 return;
154
155         pthread_mutex_lock(&mb_write_lock);
156         mb_initialized = 0;
157         pthread_cond_signal(&mb_ready_cond);
158         pthread_mutex_unlock(&mb_write_lock);
159
160         pthread_join(mb_writer_thread, NULL);
161         mb_flush();
162
163         if (mb_overruns)
164                 fprintf(stderr, "WARNING: %d message buffer overruns!\n",
165                         mb_overruns);
166         else
167                 fprintf(stderr, "no message buffer overruns\n");
168
169         pthread_mutex_destroy(&mb_write_lock);
170         pthread_cond_destroy(&mb_ready_cond);
171
172 }
173
174 bool
175 DebugModuleManager::init()
176 {
177         if (mb_initialized)
178                 return true;
179
180         // if ( m_level >= eDL_VeryVerbose )
181         //         cout << "DebugModuleManager init..." << endl;
182
183         pthread_mutex_init(&mb_write_lock, NULL);
184         pthread_cond_init(&mb_ready_cond, NULL);
185
186         mb_overruns = 0;
187         mb_initialized = 1;
188
189         if (pthread_create(&mb_writer_thread, NULL, &mb_thread_func, (void *)this) != 0)
190                 mb_initialized = 0;
191
192     return true;
193 }
194
195 DebugModuleManager*
196 DebugModuleManager::instance()
197 {
198     if ( !m_instance ) {
199         m_instance = new DebugModuleManager;
200         if ( !m_instance ) {
201             cerr << "DebugModuleManager::instance Failed to create "
202                  << "DebugModuleManager" << endl;
203         }
204         if ( !m_instance->init() ) {
205             cerr << "DebugModuleManager::instance Failed to init "
206                  << "DebugModuleManager" << endl;
207         }
208     }
209     return m_instance;
210 }
211
212 bool
213 DebugModuleManager::registerModule( DebugModule& debugModule )
214 {
215     bool already_present=false;
216    
217     for ( DebugModuleVectorIterator it = m_debugModules.begin();
218           it != m_debugModules.end();
219           ++it )
220     {
221         if ( *it == &debugModule ) {
222             already_present=true;
223             return true;
224         }
225     }
226    
227     if (already_present) {
228         cerr << "DebugModuleManager::registerModule: Module already registered: "
229             << "DebugModule (" << debugModule.getName() << ")" << endl;
230     } else {
231         m_debugModules.push_back( &debugModule );
232     }
233     return true;
234 }
235
236 bool
237 DebugModuleManager::unregisterModule( DebugModule& debugModule )
238 {
239    
240     for ( DebugModuleVectorIterator it = m_debugModules.begin();
241           it != m_debugModules.end();
242           ++it )
243     {
244         if ( *it == &debugModule ) {
245             m_debugModules.erase( it );
246             return true;
247         }
248     }
249    
250     cerr << "DebugModuleManager::unregisterModule: Could not unregister "
251          << "DebugModule (" << debugModule.getName() << ")" << endl;
252     return false;
253 }
254
255 bool
256 DebugModuleManager::setMgrDebugLevel( std::string name, debug_level_t level )
257 {
258     for ( DebugModuleVectorIterator it = m_debugModules.begin();
259           it != m_debugModules.end();
260           ++it )
261     {
262         if ( (*it)->getName() == name ) {
263             return (*it)->setLevel( level );
264         }
265     }
266
267     cerr << "setDebugLevel: Did not find DebugModule ("
268          << name << ")" << endl;
269     return false;
270 }
271
272
273 void
274 DebugModuleManager::mb_flush()
275 {
276         /* called WITHOUT the mb_write_lock */
277         while (mb_outbuffer != mb_inbuffer) {
278                 fputs(mb_buffers[mb_outbuffer], stderr);
279                 mb_outbuffer = MB_NEXT(mb_outbuffer);
280         }
281 }
282
283 void *
284 DebugModuleManager::mb_thread_func(void *arg)
285 {
286
287     DebugModuleManager *m=static_cast<DebugModuleManager *>(arg);
288
289         /* The mutex is only to eliminate collisions between multiple
290          * writer threads and protect the condition variable. */
291         pthread_mutex_lock(&m->mb_write_lock);
292
293         while (m->mb_initialized) {
294                 pthread_cond_wait(&m->mb_ready_cond, &m->mb_write_lock);
295
296                 /* releasing the mutex reduces contention */
297                 pthread_mutex_unlock(&m->mb_write_lock);
298                 m->mb_flush();
299                 pthread_mutex_lock(&m->mb_write_lock);
300         }
301
302         pthread_mutex_unlock(&m->mb_write_lock);
303
304         return NULL;
305 }
306
307 void
308 DebugModuleManager::print(const char *fmt, ...)
309 {
310         char msg[MB_BUFFERSIZE];
311         va_list ap;
312
313         /* format the message first, to reduce lock contention */
314         va_start(ap, fmt);
315         vsnprintf(msg, MB_BUFFERSIZE, fmt, ap);
316         va_end(ap);
317
318         if (!mb_initialized) {
319                 /* Unable to print message with realtime safety.
320                  * Complain and print it anyway. */
321                 fprintf(stderr, "ERROR: messagebuffer not initialized: %s",
322                         msg);
323                 return;
324         }
325         if (pthread_mutex_trylock(&mb_write_lock) == 0) {
326                 strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE);
327                 mb_inbuffer = MB_NEXT(mb_inbuffer);
328                 pthread_cond_signal(&mb_ready_cond);
329                 pthread_mutex_unlock(&mb_write_lock);
330         } else {                        /* lock collision */
331 //              atomic_add(&mb_overruns, 1);
332                 // FIXME: atomicity
333                 mb_overruns++; // skip the atomicness for now
334         }
335 }
336
337
338 void
339 DebugModuleManager::va_print (const char *fmt, va_list ap)
340 {
341         char msg[MB_BUFFERSIZE];
342
343         /* format the message first, to reduce lock contention */
344         vsnprintf(msg, MB_BUFFERSIZE, fmt, ap);
345
346         if (!mb_initialized) {
347                 /* Unable to print message with realtime safety.
348                  * Complain and print it anyway. */
349                 fprintf(stderr, "ERROR: messagebuffer not initialized: %s",
350                         msg);
351                 return;
352         }
353
354         if (pthread_mutex_trylock(&mb_write_lock) == 0) {
355                 strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE);
356                 mb_inbuffer = MB_NEXT(mb_inbuffer);
357                 pthread_cond_signal(&mb_ready_cond);
358                 pthread_mutex_unlock(&mb_write_lock);
359         } else {                        /* lock collision */
360 //              atomic_add(&mb_overruns, 1);
361                 // FIXME: atomicity
362                 mb_overruns++; // skip the atomicness for now
363         }
364 }
365
366 //----------------------------------------
367
368 unsigned char
369 toAscii( unsigned char c )
370 {
371     if ( ( c > 31 ) && ( c < 126) ) {
372         return c;
373     } else {
374         return '.';
375     }
376 }
377
378 /* converts a quadlet to a uchar * buffer
379  * not implemented optimally, but clear
380  */
381 void
382 quadlet2char( quadlet_t quadlet, unsigned char* buff )
383 {
384     *(buff)   = (quadlet>>24)&0xFF;
385     *(buff+1) = (quadlet>>16)&0xFF;
386     *(buff+2) = (quadlet>> 8)&0xFF;
387     *(buff+3) = (quadlet)    &0xFF;
388 }
389
390 void
391 hexDump( unsigned char *data_start, unsigned int length )
392 {
393     unsigned int i=0;
394     unsigned int byte_pos;
395     unsigned int bytes_left;
396
397     if ( length <= 0 ) {
398         return;
399     }
400     if ( length >= 7 ) {
401         for ( i = 0; i < (length-7); i += 8 ) {
402             printf( "%04X: %02X %02X %02X %02X %02X %02X %02X %02X "
403                     "- [%c%c%c%c%c%c%c%c]\n",
404
405                     i,
406
407                     *(data_start+i+0),
408                     *(data_start+i+1),
409                     *(data_start+i+2),
410                     *(data_start+i+3),
411                     *(data_start+i+4),
412                     *(data_start+i+5),
413                     *(data_start+i+6),
414                     *(data_start+i+7),
415
416                     toAscii( *(data_start+i+0) ),
417                     toAscii( *(data_start+i+1) ),
418                     toAscii( *(data_start+i+2) ),
419                     toAscii( *(data_start+i+3) ),
420                     toAscii( *(data_start+i+4) ),
421                     toAscii( *(data_start+i+5) ),
422                     toAscii( *(data_start+i+6) ),
423                     toAscii( *(data_start+i+7) )
424                 );
425         }
426     }
427     byte_pos = i;
428     bytes_left = length - byte_pos;
429
430     printf( "%04X:" ,i );
431     for ( i = byte_pos; i < length; i += 1 ) {
432         printf( " %02X", *(data_start+i) );
433     }
434     for ( i=0; i < 8-bytes_left; i+=1 ) {
435         printf( "   " );
436     }
437
438     printf( " - [" );
439     for ( i = byte_pos; i < length; i += 1) {
440         printf( "%c", toAscii(*(data_start+i)));
441     }
442     for ( i = 0; i < 8-bytes_left; i += 1) {
443         printf( " " );
444     }
445
446     printf( "]" );
447     printf( "\n" );
448 }
449
450 void
451 hexDumpQuadlets( quadlet_t *data, unsigned int length )
452 {
453     unsigned int i=0;
454
455     if ( length <= 0 ) {
456         return;
457     }
458     for (i = 0; i< length; i += 1) {
459         printf( "%02d %04X: %08X (%08X)"
460                 "\n", i, i*4, data[i],ntohl(data[i]));
461     }
462 }
463
464
Note: See TracBrowser for help on using the browser.