![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include "DebugOutput.hpp"
00002 #include "moab/MOABConfig.h"
00003 #include "moab/Range.hpp"
00004 #include "moab/CN.hpp"
00005 #include "Internals.hpp"
00006
00007 #include
00008 #include
00009 #include
00010 #include
00011
00012 namespace moab
00013 {
00014
00015 DebugOutputStream::~DebugOutputStream() {}
00016
00017 class FILEDebugStream : public DebugOutputStream
00018 {
00019 private:
00020 FILE* filePtr;
00021
00022 public:
00023 FILEDebugStream( FILE* filep ) : filePtr( filep ) {}
00024 void println( int rank, const char* pfx, const char* str );
00025 void println( const char* pfx, const char* str );
00026 };
00027 void FILEDebugStream::println( int rank, const char* pfx, const char* str )
00028 {
00029 fprintf( filePtr, "%3d %s%s\n", rank, pfx, str );
00030 fflush( filePtr );
00031 }
00032 void FILEDebugStream::println( const char* pfx, const char* str )
00033 {
00034 fputs( pfx, filePtr );
00035 fputs( str, filePtr );
00036 fputc( '\n', filePtr );
00037 fflush( filePtr );
00038 }
00039
00040 class CxxDebugStream : public DebugOutputStream
00041 {
00042 private:
00043 std::ostream& outStr;
00044
00045 public:
00046 CxxDebugStream( std::ostream& str ) : outStr( str ) {}
00047 void println( int rank, const char* pfx, const char* str );
00048 void println( const char* pfx, const char* str );
00049 };
00050 void CxxDebugStream::println( int rank, const char* pfx, const char* str )
00051 {
00052 outStr.width( 3 );
00053 outStr << rank << " " << pfx << str << std::endl;
00054 outStr.flush();
00055 }
00056 void CxxDebugStream::println( const char* pfx, const char* str )
00057 {
00058 outStr << pfx << str << std::endl;
00059 outStr.flush();
00060 }
00061
00062 DebugOutput::DebugOutput( DebugOutputStream* impl, unsigned verbosity )
00063 : outputImpl( impl ), mpiRank( -1 ), verbosityLimit( verbosity )
00064 {
00065 impl->referenceCount++;
00066 assert( impl->referenceCount > 1 );
00067 }
00068 DebugOutput::DebugOutput( DebugOutputStream* impl, int rank, unsigned verbosity )
00069 : outputImpl( impl ), mpiRank( rank ), verbosityLimit( verbosity )
00070 {
00071 impl->referenceCount++;
00072 assert( impl->referenceCount > 1 );
00073 }
00074 DebugOutput::DebugOutput( FILE* impl, unsigned verbosity )
00075 : outputImpl( new FILEDebugStream( impl ) ), mpiRank( -1 ), verbosityLimit( verbosity )
00076 {
00077 }
00078 DebugOutput::DebugOutput( FILE* impl, int rank, unsigned verbosity )
00079 : outputImpl( new FILEDebugStream( impl ) ), mpiRank( rank ), verbosityLimit( verbosity )
00080 {
00081 }
00082 DebugOutput::DebugOutput( std::ostream& str, unsigned verbosity )
00083 : outputImpl( new CxxDebugStream( str ) ), mpiRank( -1 ), verbosityLimit( verbosity )
00084 {
00085 }
00086 DebugOutput::DebugOutput( std::ostream& str, int rank, unsigned verbosity )
00087 : outputImpl( new CxxDebugStream( str ) ), mpiRank( rank ), verbosityLimit( verbosity )
00088 {
00089 }
00090 DebugOutput::DebugOutput( const char* pfx, DebugOutputStream* impl, unsigned verbosity )
00091 : linePfx( pfx ), outputImpl( impl ), mpiRank( -1 ), verbosityLimit( verbosity )
00092 {
00093 impl->referenceCount++;
00094 assert( impl->referenceCount > 1 );
00095 }
00096 DebugOutput::DebugOutput( const char* pfx, DebugOutputStream* impl, int rank, unsigned verbosity )
00097 : linePfx( pfx ), outputImpl( impl ), mpiRank( rank ), verbosityLimit( verbosity )
00098 {
00099 impl->referenceCount++;
00100 assert( impl->referenceCount > 1 );
00101 }
00102 DebugOutput::DebugOutput( const char* pfx, FILE* impl, unsigned verbosity )
00103 : linePfx( pfx ), outputImpl( new FILEDebugStream( impl ) ), mpiRank( -1 ), verbosityLimit( verbosity )
00104 {
00105 }
00106 DebugOutput::DebugOutput( const char* pfx, FILE* impl, int rank, unsigned verbosity )
00107 : linePfx( pfx ), outputImpl( new FILEDebugStream( impl ) ), mpiRank( rank ), verbosityLimit( verbosity )
00108 {
00109 }
00110 DebugOutput::DebugOutput( const char* pfx, std::ostream& str, unsigned verbosity )
00111 : linePfx( pfx ), outputImpl( new CxxDebugStream( str ) ), mpiRank( -1 ), verbosityLimit( verbosity )
00112 {
00113 }
00114 DebugOutput::DebugOutput( const char* pfx, std::ostream& str, int rank, unsigned verbosity )
00115 : linePfx( pfx ), outputImpl( new CxxDebugStream( str ) ), mpiRank( rank ), verbosityLimit( verbosity )
00116 {
00117 }
00118
00119 DebugOutput::DebugOutput( const DebugOutput& copy )
00120 : linePfx( copy.linePfx ), outputImpl( copy.outputImpl ), mpiRank( copy.mpiRank ),
00121 verbosityLimit( copy.verbosityLimit )
00122 {
00123 outputImpl->referenceCount++;
00124 assert( outputImpl->referenceCount > 1 );
00125 }
00126
00127 DebugOutput& DebugOutput::operator=( const DebugOutput& copy )
00128 {
00129 linePfx = copy.linePfx;
00130 outputImpl = copy.outputImpl;
00131 mpiRank = copy.mpiRank;
00132 verbosityLimit = copy.verbosityLimit;
00133 outputImpl->referenceCount++;
00134 assert( outputImpl->referenceCount > 1 );
00135 return *this;
00136 }
00137
00138 DebugOutput::~DebugOutput()
00139 {
00140 if( !lineBuffer.empty() )
00141 {
00142 lineBuffer.push_back( '\n' );
00143 process_line_buffer();
00144 }
00145 if( outputImpl )
00146 {
00147 assert( outputImpl->referenceCount > 0 );
00148 if( !--outputImpl->referenceCount ) delete outputImpl;
00149 outputImpl = 0;
00150 }
00151 }
00152
00153 void DebugOutput::use_world_rank()
00154 {
00155 mpiRank = 0;
00156 #ifdef MOAB_HAVE_MPI
00157 int flag = 0;
00158 if( MPI_SUCCESS == MPI_Initialized( &flag ) && flag ) MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank );
00159 #endif
00160 }
00161
00162 void DebugOutput::print_real( const char* buffer )
00163 {
00164 lineBuffer.insert( lineBuffer.end(), buffer, buffer + strlen( buffer ) );
00165 process_line_buffer();
00166 }
00167
00168 void DebugOutput::tprint_real( const char* buffer )
00169 {
00170 tprint();
00171 print_real( buffer );
00172 }
00173
00174 void DebugOutput::print_real( const std::string& str )
00175 {
00176 lineBuffer.insert( lineBuffer.end(), str.begin(), str.end() );
00177 process_line_buffer();
00178 }
00179
00180 void DebugOutput::tprint_real( const std::string& str )
00181 {
00182 tprint();
00183 print_real( str );
00184 }
00185
00186 void DebugOutput::print_real( const char* fmt, va_list args1, va_list args2 )
00187 {
00188 size_t idx = lineBuffer.size();
00189 #ifdef MOAB_HAVE_VSNPRINTF
00190 // try once with remaining space in buffer
00191 lineBuffer.resize( lineBuffer.capacity() );
00192 unsigned size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args1 );
00193 ++size; // trailing null
00194 // if necessary, increase buffer size and retry
00195 if( size > ( lineBuffer.size() - idx ) )
00196 {
00197 lineBuffer.resize( idx + size );
00198 size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args2 );
00199 ++size; // trailing null
00200 }
00201 #else
00202 // Guess how much space might be required.
00203 // If every character is a format code then there are len/3 format codes.
00204 // Guess a random large value of num_chars characters per formatted argument.
00205 const unsigned num_chars = 180;
00206 unsigned exp_size = ( num_chars / 3 ) * strlen( fmt );
00207 lineBuffer.resize( idx + exp_size );
00208 unsigned size = vsprintf( &lineBuffer[idx], fmt, args1 );
00209 ++size; // trailing null
00210 // check if we overflowed the buffer
00211 if( size > exp_size )
00212 {
00213 // crap!
00214 fprintf( stderr, "ERROR: Buffer overflow at %s:%d\n", __FILE__, __LINE__ );
00215 lineBuffer.resize( idx + exp_size );
00216 size = vsprintf( &lineBuffer[idx], fmt, args2 );
00217 ++size; // trailing null
00218 }
00219 #endif
00220
00221 // less one because we don't want the trailing '\0'
00222 lineBuffer.resize( idx + size - 1 );
00223 process_line_buffer();
00224 }
00225
00226 void DebugOutput::tprint_real( const char* fmt, va_list args1, va_list args2 )
00227 {
00228 tprint();
00229 print_real( fmt, args1, args2 );
00230 }
00231
00232 static void print_range( char* buffer, unsigned long begin, unsigned long end )
00233 {
00234 assert( end > begin );
00235 // begin with a space
00236 *buffer = ' ';
00237 char* b1 = buffer + 1;
00238 // print begin-end, but keep track of where each peice is written
00239 char* e1 = b1 + sprintf( b1, "%lu", begin );
00240 *e1 = '-';
00241 char* b2 = e1 + 1;
00242 char* e2 = b2 + sprintf( b2, "%lu", end );
00243 // if the printed strings for both numbers don't contain the same
00244 // number of digits, don't do anything more
00245 if( e1 - b1 == e2 - b2 )
00246 {
00247 // see how many leading digits the two numbers have in common
00248 char* p = b2;
00249 while( *p && *p == *b1 )
00250 {
00251 ++p;
00252 ++b1;
00253 }
00254 // remove common shared leading digits from second number
00255 if( p > b2 && *p )
00256 {
00257 // shift second value down so that common leading digits are not repeated
00258 while( *p )
00259 {
00260 *b2 = *p;
00261 ++b2;
00262 ++p;
00263 }
00264 e2 = b2;
00265 }
00266 }
00267 // add trailing comma
00268 *e2 = ',';
00269 ++e2;
00270 *e2 = '\0';
00271 }
00272
00273 void DebugOutput::list_range_real( const char* pfx, const Range& range )
00274 {
00275 if( pfx )
00276 {
00277 lineBuffer.insert( lineBuffer.end(), pfx, pfx + strlen( pfx ) );
00278 lineBuffer.push_back( ' ' );
00279 }
00280
00281 if( range.empty() )
00282 {
00283 print_real( "\n" );
00284 return;
00285 }
00286
00287 char numbuf[48]; // unsigned 64 bit integer can't have more than 20 decimal digits
00288 Range::const_pair_iterator i;
00289 EntityType type = MBMAXTYPE;
00290 for( i = range.const_pair_begin(); i != range.const_pair_end(); ++i )
00291 {
00292 if( TYPE_FROM_HANDLE( i->first ) != type )
00293 {
00294 type = TYPE_FROM_HANDLE( i->first );
00295 const char* name = CN::EntityTypeName( type );
00296 lineBuffer.insert( lineBuffer.end(), name, name + strlen( name ) );
00297 }
00298 if( i->first == i->second )
00299 sprintf( numbuf, " %lu,", (unsigned long)( ID_FROM_HANDLE( i->first ) ) );
00300 else
00301 print_range( numbuf, ID_FROM_HANDLE( i->first ), ID_FROM_HANDLE( i->second ) );
00302 lineBuffer.insert( lineBuffer.end(), numbuf, numbuf + strlen( numbuf ) );
00303 }
00304
00305 lineBuffer.push_back( '\n' );
00306 process_line_buffer();
00307 }
00308
00309 void DebugOutput::list_ints_real( const char* pfx, const Range& range )
00310 {
00311 if( range.empty() )
00312 {
00313 print_real( "\n" );
00314 return;
00315 }
00316
00317 if( pfx )
00318 {
00319 lineBuffer.insert( lineBuffer.end(), pfx, pfx + strlen( pfx ) );
00320 lineBuffer.push_back( ' ' );
00321 }
00322
00323 char numbuf[48]; // unsigned 64 bit integer can't have more than 20 decimal digits
00324 Range::const_pair_iterator i;
00325 for( i = range.const_pair_begin(); i != range.const_pair_end(); ++i )
00326 {
00327 if( i->first == i->second )
00328 sprintf( numbuf, " %lu,", (unsigned long)( i->first ) );
00329 else
00330 print_range( numbuf, (unsigned long)( i->first ), (unsigned long)( i->second ) );
00331 lineBuffer.insert( lineBuffer.end(), numbuf, numbuf + strlen( numbuf ) );
00332 }
00333
00334 lineBuffer.push_back( '\n' );
00335 process_line_buffer();
00336 }
00337
00338 void DebugOutput::process_line_buffer()
00339 {
00340 size_t last_idx = 0;
00341 std::vector< char >::iterator i;
00342 for( i = std::find( lineBuffer.begin(), lineBuffer.end(), '\n' ); i != lineBuffer.end();
00343 i = std::find( i, lineBuffer.end(), '\n' ) )
00344 {
00345 *i = '\0';
00346 if( have_rank() )
00347 outputImpl->println( get_rank(), linePfx.c_str(), &lineBuffer[last_idx] );
00348 else
00349 outputImpl->println( linePfx.c_str(), &lineBuffer[last_idx] );
00350 ++i;
00351 last_idx = i - lineBuffer.begin();
00352 }
00353
00354 if( last_idx )
00355 {
00356 i = std::copy( lineBuffer.begin() + last_idx, lineBuffer.end(), lineBuffer.begin() );
00357 lineBuffer.erase( i, lineBuffer.end() );
00358 }
00359 }
00360
00361 void DebugOutput::tprint()
00362 {
00363 size_t s = lineBuffer.size();
00364 lineBuffer.resize( s + 64 );
00365 size_t ss = sprintf( &lineBuffer[s], "(%.2f s) ", cpuTi.time_since_birth() );
00366 lineBuffer.resize( s + ss );
00367 }
00368
00369 } // namespace moab