LCOV - code coverage report
Current view: top level - src - DebugOutput.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 22 207 10.6 %
Date: 2020-12-16 07:07:30 Functions: 11 38 28.9 %
Branches: 24 294 8.2 %

           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

Generated by: LCOV version 1.11