root/trunk/libffado/src/debugmodule/debugmodule.cpp

Revision 406, 11.5 kB (checked in by jwoithe, 14 years ago)

Fix uninitialised pointer in debugmodule.

  • 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    
102     // remove the path info from the filename
103     const char *f = file;
104     const char *fname = file;
105     while((f=strstr(f, "/"))) {
106         f++; // move away from delimiter
107         fname=f;
108     }
109    
110     DebugModuleManager::instance()->print( "%s (%s)[%4d] %s: ", getPreSequence( level ),
111                  fname,  line,  function );
112     DebugModuleManager::instance()->va_print( format, arg );
113     DebugModuleManager::instance()->print( "%s", getPostSequence( level ) );
114     va_end( arg );
115 }
116
117 const char*
118 DebugModule::getPreSequence( debug_level_t level ) const
119 {
120     if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) {
121         return colorTable[level].preSequence;
122     }
123     return colorTable[eDL_Normal].preSequence;
124 }
125
126 const char*
127 DebugModule::getPostSequence( debug_level_t level ) const
128 {
129     if ( ( level <= eDL_Normal ) && ( level >= eDL_Fatal ) ) {
130         return colorTable[level].postSequence;
131     }
132     return colorTable[eDL_Normal].postSequence;
133 }
134
135 //--------------------------------------
136
137 DebugModuleManager* DebugModuleManager::m_instance = 0;
138
139 DebugModuleManager::DebugModuleManager()
140     : mb_initialized(0)
141     , mb_inbuffer(0)
142     , mb_outbuffer(0)
143     , mb_overruns(0)
144
145 {
146
147 }
148
149 DebugModuleManager::~DebugModuleManager()
150 {
151         // cleanin up leftover modules
152     for ( DebugModuleVectorIterator it = m_debugModules.begin();
153           it != m_debugModules.end();
154           ++it )
155     {
156         fprintf(stderr,"Cleaning up leftover debug module: %s\n",(*it)->getName().c_str());
157         m_debugModules.erase( it );
158         delete *it;
159     }
160
161         if (!mb_initialized)
162                 return;
163
164         pthread_mutex_lock(&mb_write_lock);
165         mb_initialized = 0;
166         pthread_cond_signal(&mb_ready_cond);
167         pthread_mutex_unlock(&mb_write_lock);
168
169         pthread_join(mb_writer_thread, NULL);
170         mb_flush();
171
172         if (mb_overruns)
173                 fprintf(stderr, "WARNING: %d message buffer overruns!\n",
174                         mb_overruns);
175         else
176                 fprintf(stderr, "no message buffer overruns\n");
177
178         pthread_mutex_destroy(&mb_write_lock);
179         pthread_cond_destroy(&mb_ready_cond);
180
181 }
182
183 bool
184 DebugModuleManager::init()
185 {
186         if (mb_initialized)
187                 return true;
188
189         // if ( m_level >= eDL_VeryVerbose )
190         //         cout << "DebugModuleManager init..." << endl;
191
192         pthread_mutex_init(&mb_write_lock, NULL);
193         pthread_cond_init(&mb_ready_cond, NULL);
194
195         mb_overruns = 0;
196         mb_initialized = 1;
197
198         if (pthread_create(&mb_writer_thread, NULL, &mb_thread_func, (void *)this) != 0)
199                 mb_initialized = 0;
200
201     return true;
202 }
203
204 DebugModuleManager*
205 DebugModuleManager::instance()
206 {
207     if ( !m_instance ) {
208         m_instance = new DebugModuleManager;
209         if ( !m_instance ) {
210             cerr << "DebugModuleManager::instance Failed to create "
211                  << "DebugModuleManager" << endl;
212         }
213         if ( !m_instance->init() ) {
214             cerr << "DebugModuleManager::instance Failed to init "
215                  << "DebugModuleManager" << endl;
216         }
217     }
218     return m_instance;
219 }
220
221 bool
222 DebugModuleManager::registerModule( DebugModule& debugModule )
223 {
224     bool already_present=false;
225    
226     for ( DebugModuleVectorIterator it = m_debugModules.begin();
227           it != m_debugModules.end();
228           ++it )
229     {
230         if ( *it == &debugModule ) {
231             already_present=true;
232             return true;
233         }
234     }
235    
236     if (already_present) {
237         cerr << "DebugModuleManager::registerModule: Module already registered: "
238             << "DebugModule (" << debugModule.getName() << ")" << endl;
239     } else {
240         m_debugModules.push_back( &debugModule );
241     }
242     return true;
243 }
244
245 bool
246 DebugModuleManager::unregisterModule( DebugModule& debugModule )
247 {
248    
249     for ( DebugModuleVectorIterator it = m_debugModules.begin();
250           it != m_debugModules.end();
251           ++it )
252     {
253         if ( *it == &debugModule ) {
254             m_debugModules.erase( it );
255             return true;
256         }
257     }
258    
259     cerr << "DebugModuleManager::unregisterModule: Could not unregister "
260          << "DebugModule (" << debugModule.getName() << ")" << endl;
261     return false;
262 }
263
264 bool
265 DebugModuleManager::setMgrDebugLevel( std::string name, debug_level_t level )
266 {
267     for ( DebugModuleVectorIterator it = m_debugModules.begin();
268           it != m_debugModules.end();
269           ++it )
270     {
271         if ( (*it)->getName() == name ) {
272             return (*it)->setLevel( level );
273         }
274     }
275
276     cerr << "setDebugLevel: Did not find DebugModule ("
277          << name << ")" << endl;
278     return false;
279 }
280
281 void
282 DebugModuleManager::sync()
283 {
284     mb_flush();
285 }
286
287 void
288 DebugModuleManager::mb_flush()
289 {
290         /* called WITHOUT the mb_write_lock */
291         while (mb_outbuffer != mb_inbuffer) {
292                 fputs(mb_buffers[mb_outbuffer], stderr);
293                 mb_outbuffer = MB_NEXT(mb_outbuffer);
294         }
295 }
296
297 void *
298 DebugModuleManager::mb_thread_func(void *arg)
299 {
300
301     DebugModuleManager *m=static_cast<DebugModuleManager *>(arg);
302
303         /* The mutex is only to eliminate collisions between multiple
304          * writer threads and protect the condition variable. */
305         pthread_mutex_lock(&m->mb_write_lock);
306
307         while (m->mb_initialized) {
308                 pthread_cond_wait(&m->mb_ready_cond, &m->mb_write_lock);
309
310                 /* releasing the mutex reduces contention */
311                 pthread_mutex_unlock(&m->mb_write_lock);
312                 m->mb_flush();
313                 pthread_mutex_lock(&m->mb_write_lock);
314         }
315
316         pthread_mutex_unlock(&m->mb_write_lock);
317
318         return NULL;
319 }
320
321 void
322 DebugModuleManager::print(const char *fmt, ...)
323 {
324         char msg[MB_BUFFERSIZE];
325         va_list ap;
326
327         /* format the message first, to reduce lock contention */
328         va_start(ap, fmt);
329         vsnprintf(msg, MB_BUFFERSIZE, fmt, ap);
330         va_end(ap);
331
332         if (!mb_initialized) {
333                 /* Unable to print message with realtime safety.
334                  * Complain and print it anyway. */
335                 fprintf(stderr, "ERROR: messagebuffer not initialized: %s",
336                         msg);
337                 return;
338         }
339         if (pthread_mutex_trylock(&mb_write_lock) == 0) {
340                 strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE);
341                 mb_inbuffer = MB_NEXT(mb_inbuffer);
342                 pthread_cond_signal(&mb_ready_cond);
343                 pthread_mutex_unlock(&mb_write_lock);
344         } else {                        /* lock collision */
345 //              atomic_add(&mb_overruns, 1);
346                 // FIXME: atomicity
347                 mb_overruns++; // skip the atomicness for now
348         }
349 }
350
351
352 void
353 DebugModuleManager::va_print (const char *fmt, va_list ap)
354 {
355         char msg[MB_BUFFERSIZE];
356
357         /* format the message first, to reduce lock contention */
358         vsnprintf(msg, MB_BUFFERSIZE, fmt, ap);
359
360         if (!mb_initialized) {
361                 /* Unable to print message with realtime safety.
362                  * Complain and print it anyway. */
363                 fprintf(stderr, "ERROR: messagebuffer not initialized: %s",
364                         msg);
365                 return;
366         }
367
368         if (pthread_mutex_trylock(&mb_write_lock) == 0) {
369                 strncpy(mb_buffers[mb_inbuffer], msg, MB_BUFFERSIZE);
370                 mb_inbuffer = MB_NEXT(mb_inbuffer);
371                 pthread_cond_signal(&mb_ready_cond);
372                 pthread_mutex_unlock(&mb_write_lock);
373         } else {                        /* lock collision */
374 //              atomic_add(&mb_overruns, 1);
375                 // FIXME: atomicity
376                 mb_overruns++; // skip the atomicness for now
377         }
378 }
379
380 //----------------------------------------
381
382 unsigned char
383 toAscii( unsigned char c )
384 {
385     if ( ( c > 31 ) && ( c < 126) ) {
386         return c;
387     } else {
388         return '.';
389     }
390 }
391
392 /* converts a quadlet to a uchar * buffer
393  * not implemented optimally, but clear
394  */
395 void
396 quadlet2char( quadlet_t quadlet, unsigned char* buff )
397 {
398     *(buff)   = (quadlet>>24)&0xFF;
399     *(buff+1) = (quadlet>>16)&0xFF;
400     *(buff+2) = (quadlet>> 8)&0xFF;
401     *(buff+3) = (quadlet)    &0xFF;
402 }
403
404 void
405 hexDump( unsigned char *data_start, unsigned int length )
406 {
407     unsigned int i=0;
408     unsigned int byte_pos;
409     unsigned int bytes_left;
410
411     if ( length <= 0 ) {
412         return;
413     }
414     if ( length >= 7 ) {
415         for ( i = 0; i < (length-7); i += 8 ) {
416             printf( "%04X: %02X %02X %02X %02X %02X %02X %02X %02X "
417                     "- [%c%c%c%c%c%c%c%c]\n",
418
419                     i,
420
421                     *(data_start+i+0),
422                     *(data_start+i+1),
423                     *(data_start+i+2),
424                     *(data_start+i+3),
425                     *(data_start+i+4),
426                     *(data_start+i+5),
427                     *(data_start+i+6),
428                     *(data_start+i+7),
429
430                     toAscii( *(data_start+i+0) ),
431                     toAscii( *(data_start+i+1) ),
432                     toAscii( *(data_start+i+2) ),
433                     toAscii( *(data_start+i+3) ),
434                     toAscii( *(data_start+i+4) ),
435                     toAscii( *(data_start+i+5) ),
436                     toAscii( *(data_start+i+6) ),
437                     toAscii( *(data_start+i+7) )
438                 );
439         }
440     }
441     byte_pos = i;
442     bytes_left = length - byte_pos;
443
444     printf( "%04X:" ,i );
445     for ( i = byte_pos; i < length; i += 1 ) {
446         printf( " %02X", *(data_start+i) );
447     }
448     for ( i=0; i < 8-bytes_left; i+=1 ) {
449         printf( "   " );
450     }
451
452     printf( " - [" );
453     for ( i = byte_pos; i < length; i += 1) {
454         printf( "%c", toAscii(*(data_start+i)));
455     }
456     for ( i = 0; i < 8-bytes_left; i += 1) {
457         printf( " " );
458     }
459
460     printf( "]" );
461     printf( "\n" );
462 }
463
464 void
465 hexDumpQuadlets( quadlet_t *data, unsigned int length )
466 {
467     unsigned int i=0;
468
469     if ( length <= 0 ) {
470         return;
471     }
472     for (i = 0; i< length; i += 1) {
473         printf( "%02d %04X: %08X (%08X)"
474                 "\n", i, i*4, data[i],ntohl(data[i]));
475     }
476 }
477
478
Note: See TracBrowser for help on using the browser.