Branch data Line data Source code
1 : : #include "DebugOutput.hpp"
2 : : #include "moab/MOABConfig.h"
3 : : #include "moab/Range.hpp"
4 : : #include "moab/CN.hpp"
5 : : #include "Internals.hpp"
6 : :
7 : : #include <iostream>
8 : : #include <string.h>
9 : : #include <algorithm>
10 : : #include <assert.h>
11 : :
12 : : namespace moab
13 : : {
14 : :
15 [ - + ]: 344 : DebugOutputStream::~DebugOutputStream() {}
16 : :
17 [ - + ]: 436 : class FILEDebugStream : public DebugOutputStream
18 : : {
19 : : private:
20 : : FILE* filePtr;
21 : :
22 : : public:
23 : 218 : FILEDebugStream( FILE* filep ) : filePtr( filep ) {}
24 : : void println( int rank, const char* pfx, const char* str );
25 : : void println( const char* pfx, const char* str );
26 : : };
27 : 0 : void FILEDebugStream::println( int rank, const char* pfx, const char* str )
28 : : {
29 : 0 : fprintf( filePtr, "%3d %s%s\n", rank, pfx, str );
30 : 0 : fflush( filePtr );
31 : 0 : }
32 : 0 : void FILEDebugStream::println( const char* pfx, const char* str )
33 : : {
34 : 0 : fputs( pfx, filePtr );
35 : 0 : fputs( str, filePtr );
36 : 0 : fputc( '\n', filePtr );
37 : 0 : fflush( filePtr );
38 : 0 : }
39 : :
40 [ - + ]: 252 : class CxxDebugStream : public DebugOutputStream
41 : : {
42 : : private:
43 : : std::ostream& outStr;
44 : :
45 : : public:
46 : 132 : CxxDebugStream( std::ostream& str ) : outStr( str ) {}
47 : : void println( int rank, const char* pfx, const char* str );
48 : : void println( const char* pfx, const char* str );
49 : : };
50 : 0 : void CxxDebugStream::println( int rank, const char* pfx, const char* str )
51 : : {
52 : 0 : outStr.width( 3 );
53 : 0 : outStr << rank << " " << pfx << str << std::endl;
54 : 0 : outStr.flush();
55 : 0 : }
56 : 0 : void CxxDebugStream::println( const char* pfx, const char* str )
57 : : {
58 : 0 : outStr << pfx << str << std::endl;
59 : 0 : outStr.flush();
60 : 0 : }
61 : :
62 : 0 : DebugOutput::DebugOutput( DebugOutputStream* impl, unsigned verbosity )
63 [ # # ][ # # ]: 0 : : outputImpl( impl ), mpiRank( -1 ), verbosityLimit( verbosity )
64 : : {
65 : 0 : impl->referenceCount++;
66 [ # # ]: 0 : assert( impl->referenceCount > 1 );
67 : 0 : }
68 : 0 : DebugOutput::DebugOutput( DebugOutputStream* impl, int rank, unsigned verbosity )
69 [ # # ][ # # ]: 0 : : outputImpl( impl ), mpiRank( rank ), verbosityLimit( verbosity )
70 : : {
71 : 0 : impl->referenceCount++;
72 [ # # ]: 0 : assert( impl->referenceCount > 1 );
73 : 0 : }
74 : 70 : DebugOutput::DebugOutput( FILE* impl, unsigned verbosity )
75 [ + - ][ + - ]: 70 : : outputImpl( new FILEDebugStream( impl ) ), mpiRank( -1 ), verbosityLimit( verbosity )
[ + - ][ + - ]
76 : : {
77 : 70 : }
78 : 0 : DebugOutput::DebugOutput( FILE* impl, int rank, unsigned verbosity )
79 [ # # ][ # # ]: 0 : : outputImpl( new FILEDebugStream( impl ) ), mpiRank( rank ), verbosityLimit( verbosity )
[ # # ][ # # ]
80 : : {
81 : 0 : }
82 : 0 : DebugOutput::DebugOutput( std::ostream& str, unsigned verbosity )
83 [ # # ][ # # ]: 0 : : outputImpl( new CxxDebugStream( str ) ), mpiRank( -1 ), verbosityLimit( verbosity )
[ # # ][ # # ]
84 : : {
85 : 0 : }
86 : 0 : DebugOutput::DebugOutput( std::ostream& str, int rank, unsigned verbosity )
87 [ # # ][ # # ]: 0 : : outputImpl( new CxxDebugStream( str ) ), mpiRank( rank ), verbosityLimit( verbosity )
[ # # ][ # # ]
88 : : {
89 : 0 : }
90 : 0 : DebugOutput::DebugOutput( const char* pfx, DebugOutputStream* impl, unsigned verbosity )
91 [ # # ][ # # ]: 0 : : linePfx( pfx ), outputImpl( impl ), mpiRank( -1 ), verbosityLimit( verbosity )
[ # # ]
92 : : {
93 : 0 : impl->referenceCount++;
94 [ # # ]: 0 : assert( impl->referenceCount > 1 );
95 : 0 : }
96 : 0 : DebugOutput::DebugOutput( const char* pfx, DebugOutputStream* impl, int rank, unsigned verbosity )
97 [ # # ][ # # ]: 0 : : linePfx( pfx ), outputImpl( impl ), mpiRank( rank ), verbosityLimit( verbosity )
[ # # ]
98 : : {
99 : 0 : impl->referenceCount++;
100 [ # # ]: 0 : assert( impl->referenceCount > 1 );
101 : 0 : }
102 : 39 : DebugOutput::DebugOutput( const char* pfx, FILE* impl, unsigned verbosity )
103 [ + - ][ + - ]: 39 : : linePfx( pfx ), outputImpl( new FILEDebugStream( impl ) ), mpiRank( -1 ), verbosityLimit( verbosity )
[ + - ][ + - ]
[ + - ]
104 : : {
105 : 39 : }
106 : 0 : DebugOutput::DebugOutput( const char* pfx, FILE* impl, int rank, unsigned verbosity )
107 [ # # ][ # # ]: 0 : : linePfx( pfx ), outputImpl( new FILEDebugStream( impl ) ), mpiRank( rank ), verbosityLimit( verbosity )
[ # # ][ # # ]
[ # # ]
108 : : {
109 : 0 : }
110 : 66 : DebugOutput::DebugOutput( const char* pfx, std::ostream& str, unsigned verbosity )
111 [ + - ][ + - ]: 66 : : linePfx( pfx ), outputImpl( new CxxDebugStream( str ) ), mpiRank( -1 ), verbosityLimit( verbosity )
[ + - ][ + - ]
[ + - ]
112 : : {
113 : 66 : }
114 : 0 : DebugOutput::DebugOutput( const char* pfx, std::ostream& str, int rank, unsigned verbosity )
115 [ # # ][ # # ]: 0 : : linePfx( pfx ), outputImpl( new CxxDebugStream( str ) ), mpiRank( rank ), verbosityLimit( verbosity )
[ # # ][ # # ]
[ # # ]
116 : : {
117 : 0 : }
118 : :
119 : 0 : DebugOutput::DebugOutput( const DebugOutput& copy )
120 : : : linePfx( copy.linePfx ), outputImpl( copy.outputImpl ), mpiRank( copy.mpiRank ),
121 [ # # ][ # # ]: 0 : verbosityLimit( copy.verbosityLimit )
122 : : {
123 : 0 : outputImpl->referenceCount++;
124 [ # # ]: 0 : assert( outputImpl->referenceCount > 1 );
125 : 0 : }
126 : :
127 : 0 : DebugOutput& DebugOutput::operator=( const DebugOutput& copy )
128 : : {
129 : 0 : linePfx = copy.linePfx;
130 : 0 : outputImpl = copy.outputImpl;
131 : 0 : mpiRank = copy.mpiRank;
132 : 0 : verbosityLimit = copy.verbosityLimit;
133 : 0 : outputImpl->referenceCount++;
134 [ # # ]: 0 : assert( outputImpl->referenceCount > 1 );
135 : 0 : return *this;
136 : : }
137 : :
138 : 344 : DebugOutput::~DebugOutput()
139 : : {
140 [ - + ]: 172 : if( !lineBuffer.empty() )
141 : : {
142 : 0 : lineBuffer.push_back( '\n' );
143 : 0 : process_line_buffer();
144 : : }
145 [ + - ]: 172 : if( outputImpl )
146 : : {
147 [ - + ]: 172 : assert( outputImpl->referenceCount > 0 );
148 [ + - ][ + - ]: 172 : if( !--outputImpl->referenceCount ) delete outputImpl;
149 : 172 : outputImpl = 0;
150 : : }
151 : 172 : }
152 : :
153 : 0 : void DebugOutput::use_world_rank()
154 : : {
155 : 0 : mpiRank = 0;
156 : : #ifdef MOAB_HAVE_MPI
157 : 0 : int flag = 0;
158 [ # # ][ # # ]: 0 : if( MPI_SUCCESS == MPI_Initialized( &flag ) && flag ) MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank );
[ # # ][ # # ]
[ # # ]
159 : : #endif
160 : 0 : }
161 : :
162 : 0 : void DebugOutput::print_real( const char* buffer )
163 : : {
164 : 0 : lineBuffer.insert( lineBuffer.end(), buffer, buffer + strlen( buffer ) );
165 : 0 : process_line_buffer();
166 : 0 : }
167 : :
168 : 0 : void DebugOutput::tprint_real( const char* buffer )
169 : : {
170 : 0 : tprint();
171 : 0 : print_real( buffer );
172 : 0 : }
173 : :
174 : 0 : void DebugOutput::print_real( const std::string& str )
175 : : {
176 : 0 : lineBuffer.insert( lineBuffer.end(), str.begin(), str.end() );
177 : 0 : process_line_buffer();
178 : 0 : }
179 : :
180 : 0 : void DebugOutput::tprint_real( const std::string& str )
181 : : {
182 : 0 : tprint();
183 : 0 : print_real( str );
184 : 0 : }
185 : :
186 : 0 : void DebugOutput::print_real( const char* fmt, va_list args1, va_list args2 )
187 : : {
188 : 0 : size_t idx = lineBuffer.size();
189 : : #ifdef MOAB_HAVE_VSNPRINTF
190 : : // try once with remaining space in buffer
191 : 0 : lineBuffer.resize( lineBuffer.capacity() );
192 : 0 : unsigned size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args1 );
193 : 0 : ++size; // trailing null
194 : : // if necessary, increase buffer size and retry
195 [ # # ]: 0 : if( size > ( lineBuffer.size() - idx ) )
196 : : {
197 : 0 : lineBuffer.resize( idx + size );
198 : 0 : size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args2 );
199 : 0 : ++size; // trailing null
200 : : }
201 : : #else
202 : : // Guess how much space might be required.
203 : : // If every character is a format code then there are len/3 format codes.
204 : : // Guess a random large value of num_chars characters per formatted argument.
205 : : const unsigned num_chars = 180;
206 : : unsigned exp_size = ( num_chars / 3 ) * strlen( fmt );
207 : : lineBuffer.resize( idx + exp_size );
208 : : unsigned size = vsprintf( &lineBuffer[idx], fmt, args1 );
209 : : ++size; // trailing null
210 : : // check if we overflowed the buffer
211 : : if( size > exp_size )
212 : : {
213 : : // crap!
214 : : fprintf( stderr, "ERROR: Buffer overflow at %s:%d\n", __FILE__, __LINE__ );
215 : : lineBuffer.resize( idx + exp_size );
216 : : size = vsprintf( &lineBuffer[idx], fmt, args2 );
217 : : ++size; // trailing null
218 : : }
219 : : #endif
220 : :
221 : : // less one because we don't want the trailing '\0'
222 : 0 : lineBuffer.resize( idx + size - 1 );
223 : 0 : process_line_buffer();
224 : 0 : }
225 : :
226 : 0 : void DebugOutput::tprint_real( const char* fmt, va_list args1, va_list args2 )
227 : : {
228 : 0 : tprint();
229 : 0 : print_real( fmt, args1, args2 );
230 : 0 : }
231 : :
232 : 0 : static void print_range( char* buffer, unsigned long begin, unsigned long end )
233 : : {
234 [ # # ]: 0 : assert( end > begin );
235 : : // begin with a space
236 : 0 : *buffer = ' ';
237 : 0 : char* b1 = buffer + 1;
238 : : // print begin-end, but keep track of where each peice is written
239 : 0 : char* e1 = b1 + sprintf( b1, "%lu", begin );
240 : 0 : *e1 = '-';
241 : 0 : char* b2 = e1 + 1;
242 : 0 : char* e2 = b2 + sprintf( b2, "%lu", end );
243 : : // if the printed strings for both numbers don't contain the same
244 : : // number of digits, don't do anything more
245 [ # # ]: 0 : if( e1 - b1 == e2 - b2 )
246 : : {
247 : : // see how many leading digits the two numbers have in common
248 : 0 : char* p = b2;
249 [ # # ][ # # ]: 0 : while( *p && *p == *b1 )
250 : : {
251 : 0 : ++p;
252 : 0 : ++b1;
253 : : }
254 : : // remove common shared leading digits from second number
255 [ # # ][ # # ]: 0 : if( p > b2 && *p )
256 : : {
257 : : // shift second value down so that common leading digits are not repeated
258 [ # # ]: 0 : while( *p )
259 : : {
260 : 0 : *b2 = *p;
261 : 0 : ++b2;
262 : 0 : ++p;
263 : : }
264 : 0 : e2 = b2;
265 : : }
266 : : }
267 : : // add trailing comma
268 : 0 : *e2 = ',';
269 : 0 : ++e2;
270 : 0 : *e2 = '\0';
271 : 0 : }
272 : :
273 : 0 : void DebugOutput::list_range_real( const char* pfx, const Range& range )
274 : : {
275 [ # # ]: 0 : if( pfx )
276 : : {
277 [ # # ]: 0 : lineBuffer.insert( lineBuffer.end(), pfx, pfx + strlen( pfx ) );
278 [ # # ]: 0 : lineBuffer.push_back( ' ' );
279 : : }
280 : :
281 [ # # ][ # # ]: 0 : if( range.empty() )
282 : : {
283 [ # # ]: 0 : print_real( "<empty>\n" );
284 : 0 : return;
285 : : }
286 : :
287 : : char numbuf[48]; // unsigned 64 bit integer can't have more than 20 decimal digits
288 [ # # ]: 0 : Range::const_pair_iterator i;
289 : 0 : EntityType type = MBMAXTYPE;
290 [ # # ][ # # ]: 0 : for( i = range.const_pair_begin(); i != range.const_pair_end(); ++i )
[ # # ][ # # ]
[ # # ]
291 : : {
292 [ # # ][ # # ]: 0 : if( TYPE_FROM_HANDLE( i->first ) != type )
[ # # ]
293 : : {
294 [ # # ][ # # ]: 0 : type = TYPE_FROM_HANDLE( i->first );
295 [ # # ]: 0 : const char* name = CN::EntityTypeName( type );
296 [ # # ]: 0 : lineBuffer.insert( lineBuffer.end(), name, name + strlen( name ) );
297 : : }
298 [ # # ][ # # ]: 0 : if( i->first == i->second )
[ # # ]
299 [ # # ][ # # ]: 0 : sprintf( numbuf, " %lu,", (unsigned long)( ID_FROM_HANDLE( i->first ) ) );
300 : : else
301 [ # # ][ # # ]: 0 : print_range( numbuf, ID_FROM_HANDLE( i->first ), ID_FROM_HANDLE( i->second ) );
[ # # ][ # # ]
302 [ # # ]: 0 : lineBuffer.insert( lineBuffer.end(), numbuf, numbuf + strlen( numbuf ) );
303 : : }
304 : :
305 [ # # ]: 0 : lineBuffer.push_back( '\n' );
306 [ # # ]: 0 : process_line_buffer();
307 : : }
308 : :
309 : 0 : void DebugOutput::list_ints_real( const char* pfx, const Range& range )
310 : : {
311 [ # # ][ # # ]: 0 : if( range.empty() )
312 : : {
313 [ # # ]: 0 : print_real( "<empty>\n" );
314 : 0 : return;
315 : : }
316 : :
317 [ # # ]: 0 : if( pfx )
318 : : {
319 [ # # ]: 0 : lineBuffer.insert( lineBuffer.end(), pfx, pfx + strlen( pfx ) );
320 [ # # ]: 0 : lineBuffer.push_back( ' ' );
321 : : }
322 : :
323 : : char numbuf[48]; // unsigned 64 bit integer can't have more than 20 decimal digits
324 [ # # ]: 0 : Range::const_pair_iterator i;
325 [ # # ][ # # ]: 0 : for( i = range.const_pair_begin(); i != range.const_pair_end(); ++i )
[ # # ][ # # ]
[ # # ]
326 : : {
327 [ # # ][ # # ]: 0 : if( i->first == i->second )
[ # # ]
328 [ # # ]: 0 : sprintf( numbuf, " %lu,", (unsigned long)( i->first ) );
329 : : else
330 [ # # ][ # # ]: 0 : print_range( numbuf, (unsigned long)( i->first ), (unsigned long)( i->second ) );
331 [ # # ]: 0 : lineBuffer.insert( lineBuffer.end(), numbuf, numbuf + strlen( numbuf ) );
332 : : }
333 : :
334 [ # # ]: 0 : lineBuffer.push_back( '\n' );
335 [ # # ]: 0 : process_line_buffer();
336 : : }
337 : :
338 : 0 : void DebugOutput::process_line_buffer()
339 : : {
340 : 0 : size_t last_idx = 0;
341 : 0 : std::vector< char >::iterator i;
342 [ # # ][ # # ]: 0 : for( i = std::find( lineBuffer.begin(), lineBuffer.end(), '\n' ); i != lineBuffer.end();
[ # # ][ # # ]
343 : 0 : i = std::find( i, lineBuffer.end(), '\n' ) )
344 : : {
345 [ # # ]: 0 : *i = '\0';
346 [ # # ][ # # ]: 0 : if( have_rank() )
347 [ # # ][ # # ]: 0 : outputImpl->println( get_rank(), linePfx.c_str(), &lineBuffer[last_idx] );
[ # # ]
348 : : else
349 [ # # ][ # # ]: 0 : outputImpl->println( linePfx.c_str(), &lineBuffer[last_idx] );
350 [ # # ]: 0 : ++i;
351 [ # # ]: 0 : last_idx = i - lineBuffer.begin();
352 : : }
353 : :
354 [ # # ]: 0 : if( last_idx )
355 : : {
356 [ # # ][ # # ]: 0 : i = std::copy( lineBuffer.begin() + last_idx, lineBuffer.end(), lineBuffer.begin() );
357 [ # # ]: 0 : lineBuffer.erase( i, lineBuffer.end() );
358 : : }
359 : 0 : }
360 : :
361 : 0 : void DebugOutput::tprint()
362 : : {
363 : 0 : size_t s = lineBuffer.size();
364 : 0 : lineBuffer.resize( s + 64 );
365 : 0 : size_t ss = sprintf( &lineBuffer[s], "(%.2f s) ", cpuTi.time_since_birth() );
366 : 0 : lineBuffer.resize( s + ss );
367 : 0 : }
368 : :
369 [ + - ][ + - ]: 228 : } // namespace moab
|