![]() |
Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 #include "ErrorOutput.hpp"
00002 #include "moab/MOABConfig.h"
00003
00004 #include
00005 #include
00006 #include
00007 #include
00008
00009 #ifdef MOAB_HAVE_MPI
00010 #include "moab_mpi.h"
00011 #endif
00012
00013 namespace moab
00014 {
00015
00016 class FILEErrorStream : public ErrorOutputStream
00017 {
00018 private:
00019 FILE* filePtr;
00020
00021 public:
00022 FILEErrorStream( FILE* filep ) : filePtr( filep ) {}
00023 void println( int rank, const char* str );
00024 void println( const char* str );
00025 };
00026
00027 void FILEErrorStream::println( int rank, const char* str )
00028 {
00029 fprintf( filePtr, "[%d]MOAB ERROR: %s\n", rank, str );
00030 fflush( filePtr );
00031 }
00032
00033 void FILEErrorStream::println( const char* str )
00034 {
00035 fprintf( filePtr, "MOAB ERROR: %s\n", str );
00036 fflush( filePtr );
00037 }
00038
00039 class CxxErrorStream : public ErrorOutputStream
00040 {
00041 private:
00042 std::ostream& outStr;
00043
00044 public:
00045 CxxErrorStream( std::ostream& str ) : outStr( str ) {}
00046 void println( int rank, const char* str );
00047 void println( const char* str );
00048 };
00049
00050 void CxxErrorStream::println( int rank, const char* str )
00051 {
00052 outStr << "[" << rank << "]MOAB ERROR: " << str << std::endl;
00053 outStr.flush();
00054 }
00055
00056 void CxxErrorStream::println( const char* str )
00057 {
00058 outStr << "MOAB ERROR: " << str << std::endl;
00059 outStr.flush();
00060 }
00061
00062 ErrorOutput::ErrorOutput( FILE* impl ) : outputImpl( new FILEErrorStream( impl ) ), mpiRank( -1 )
00063 {
00064 lineBuffer.reserve( 1024 );
00065 }
00066
00067 ErrorOutput::ErrorOutput( std::ostream& str ) : outputImpl( new CxxErrorStream( str ) ), mpiRank( -1 )
00068 {
00069 lineBuffer.reserve( 1024 );
00070 }
00071
00072 ErrorOutput::~ErrorOutput()
00073 {
00074 if( !lineBuffer.empty() )
00075 {
00076 lineBuffer.push_back( '\n' );
00077 process_line_buffer();
00078 }
00079
00080 if( NULL != outputImpl )
00081 {
00082 delete outputImpl;
00083 outputImpl = NULL;
00084 }
00085 }
00086
00087 void ErrorOutput::use_world_rank()
00088 {
00089 #ifdef MOAB_HAVE_MPI
00090 int flag1;
00091 MPI_Initialized( &flag1 );
00092 int flag2;
00093 MPI_Finalized( &flag2 );
00094 if( flag1 && !flag2 ) MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank );
00095 #endif
00096 }
00097
00098 void ErrorOutput::print_real( const char* buffer )
00099 {
00100 lineBuffer.insert( lineBuffer.end(), buffer, buffer + strlen( buffer ) );
00101 process_line_buffer();
00102 }
00103
00104 void ErrorOutput::print_real( const std::string& str )
00105 {
00106 lineBuffer.insert( lineBuffer.end(), str.begin(), str.end() );
00107 process_line_buffer();
00108 }
00109
00110 void ErrorOutput::print_real( const char* fmt, va_list args1, va_list args2 )
00111 {
00112 size_t idx = lineBuffer.size();
00113 #ifdef MOAB_HAVE_VSNPRINTF
00114 // try once with remaining space in buffer
00115 lineBuffer.resize( lineBuffer.capacity() );
00116 unsigned size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args1 );
00117 ++size; // trailing null
00118 // if necessary, increase buffer size and retry
00119 if( size > ( lineBuffer.size() - idx ) )
00120 {
00121 lineBuffer.resize( idx + size );
00122 size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args2 );
00123 ++size; // trailing null
00124 }
00125 #else
00126 // Guess how much space might be required.
00127 // If every character is a format code then there are len/3 format codes.
00128 // Guess a random large value of num_chars characters per formatted argument.
00129 const unsigned num_chars = 180;
00130 unsigned exp_size = ( num_chars / 3 ) * strlen( fmt );
00131 lineBuffer.resize( idx + exp_size );
00132 unsigned size = vsprintf( &lineBuffer[idx], fmt, args1 );
00133 ++size; // trailing null
00134 // check if we overflowed the buffer
00135 if( size > exp_size )
00136 {
00137 // crap!
00138 fprintf( stderr, "ERROR: Buffer overflow at %s:%d\n", __FILE__, __LINE__ );
00139 lineBuffer.resize( idx + exp_size );
00140 size = vsprintf( &lineBuffer[idx], fmt, args2 );
00141 ++size; // trailing null
00142 }
00143 #endif
00144
00145 // less one because we don't want the trailing '\0'
00146 lineBuffer.resize( idx + size - 1 );
00147 process_line_buffer();
00148 }
00149
00150 void ErrorOutput::process_line_buffer()
00151 {
00152 size_t last_idx = 0;
00153 std::vector< char >::iterator i;
00154 for( i = std::find( lineBuffer.begin(), lineBuffer.end(), '\n' ); i != lineBuffer.end();
00155 i = std::find( i, lineBuffer.end(), '\n' ) )
00156 {
00157 *i = '\0';
00158 if( have_rank() )
00159 outputImpl->println( get_rank(), &lineBuffer[last_idx] );
00160 else
00161 outputImpl->println( &lineBuffer[last_idx] );
00162 ++i;
00163 last_idx = i - lineBuffer.begin();
00164 }
00165
00166 if( last_idx )
00167 {
00168 i = std::copy( lineBuffer.begin() + last_idx, lineBuffer.end(), lineBuffer.begin() );
00169 lineBuffer.erase( i, lineBuffer.end() );
00170 }
00171 }
00172
00173 } // namespace moab