Branch data Line data Source code
1 : : #include "ErrorOutput.hpp"
2 : : #include "moab/MOABConfig.h"
3 : :
4 : : #include <iostream>
5 : : #include <string.h>
6 : : #include <algorithm>
7 : : #include <assert.h>
8 : :
9 : : #ifdef MOAB_HAVE_MPI
10 : : #include "moab_mpi.h"
11 : : #endif
12 : :
13 : : namespace moab
14 : : {
15 : :
16 [ - + ]: 1328 : class FILEErrorStream : public ErrorOutputStream
17 : : {
18 : : private:
19 : : FILE* filePtr;
20 : :
21 : : public:
22 : 670 : FILEErrorStream( FILE* filep ) : filePtr( filep ) {}
23 : : void println( int rank, const char* str );
24 : : void println( const char* str );
25 : : };
26 : :
27 : 66 : void FILEErrorStream::println( int rank, const char* str )
28 : : {
29 : 66 : fprintf( filePtr, "[%d]MOAB ERROR: %s\n", rank, str );
30 : 66 : fflush( filePtr );
31 : 66 : }
32 : :
33 : 30 : void FILEErrorStream::println( const char* str )
34 : : {
35 : 30 : fprintf( filePtr, "MOAB ERROR: %s\n", str );
36 : 30 : fflush( filePtr );
37 : 30 : }
38 : :
39 [ # # ]: 0 : class CxxErrorStream : public ErrorOutputStream
40 : : {
41 : : private:
42 : : std::ostream& outStr;
43 : :
44 : : public:
45 : 0 : CxxErrorStream( std::ostream& str ) : outStr( str ) {}
46 : : void println( int rank, const char* str );
47 : : void println( const char* str );
48 : : };
49 : :
50 : 0 : void CxxErrorStream::println( int rank, const char* str )
51 : : {
52 : 0 : outStr << "[" << rank << "]MOAB ERROR: " << str << std::endl;
53 : 0 : outStr.flush();
54 : 0 : }
55 : :
56 : 0 : void CxxErrorStream::println( const char* str )
57 : : {
58 : 0 : outStr << "MOAB ERROR: " << str << std::endl;
59 : 0 : outStr.flush();
60 : 0 : }
61 : :
62 [ + - ]: 670 : ErrorOutput::ErrorOutput( FILE* impl ) : outputImpl( new FILEErrorStream( impl ) ), mpiRank( -1 )
63 : : {
64 [ + - ]: 335 : lineBuffer.reserve( 1024 );
65 : 335 : }
66 : :
67 [ # # ]: 0 : ErrorOutput::ErrorOutput( std::ostream& str ) : outputImpl( new CxxErrorStream( str ) ), mpiRank( -1 )
68 : : {
69 [ # # ]: 0 : lineBuffer.reserve( 1024 );
70 : 0 : }
71 : :
72 : 664 : ErrorOutput::~ErrorOutput()
73 : : {
74 [ - + ]: 332 : if( !lineBuffer.empty() )
75 : : {
76 : 0 : lineBuffer.push_back( '\n' );
77 : 0 : process_line_buffer();
78 : : }
79 : :
80 [ + - ]: 332 : if( NULL != outputImpl )
81 : : {
82 [ + - ]: 332 : delete outputImpl;
83 : 332 : outputImpl = NULL;
84 : : }
85 : 332 : }
86 : :
87 : 335 : void ErrorOutput::use_world_rank()
88 : : {
89 : : #ifdef MOAB_HAVE_MPI
90 : : int flag1;
91 [ + - ]: 335 : MPI_Initialized( &flag1 );
92 : : int flag2;
93 [ + - ]: 335 : MPI_Finalized( &flag2 );
94 [ + + ][ + - ]: 335 : if( flag1 && !flag2 ) MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank );
[ + - ]
95 : : #endif
96 : 335 : }
97 : :
98 : 26 : void ErrorOutput::print_real( const char* buffer )
99 : : {
100 : 26 : lineBuffer.insert( lineBuffer.end(), buffer, buffer + strlen( buffer ) );
101 : 26 : process_line_buffer();
102 : 26 : }
103 : :
104 : 0 : void ErrorOutput::print_real( const std::string& str )
105 : : {
106 : 0 : lineBuffer.insert( lineBuffer.end(), str.begin(), str.end() );
107 : 0 : process_line_buffer();
108 : 0 : }
109 : :
110 : 70 : void ErrorOutput::print_real( const char* fmt, va_list args1, va_list args2 )
111 : : {
112 : 70 : size_t idx = lineBuffer.size();
113 : : #ifdef MOAB_HAVE_VSNPRINTF
114 : : // try once with remaining space in buffer
115 : 70 : lineBuffer.resize( lineBuffer.capacity() );
116 : 70 : unsigned size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args1 );
117 : 70 : ++size; // trailing null
118 : : // if necessary, increase buffer size and retry
119 [ - + ]: 70 : if( size > ( lineBuffer.size() - idx ) )
120 : : {
121 : 0 : lineBuffer.resize( idx + size );
122 : 0 : size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args2 );
123 : 0 : ++size; // trailing null
124 : : }
125 : : #else
126 : : // Guess how much space might be required.
127 : : // If every character is a format code then there are len/3 format codes.
128 : : // Guess a random large value of num_chars characters per formatted argument.
129 : : const unsigned num_chars = 180;
130 : : unsigned exp_size = ( num_chars / 3 ) * strlen( fmt );
131 : : lineBuffer.resize( idx + exp_size );
132 : : unsigned size = vsprintf( &lineBuffer[idx], fmt, args1 );
133 : : ++size; // trailing null
134 : : // check if we overflowed the buffer
135 : : if( size > exp_size )
136 : : {
137 : : // crap!
138 : : fprintf( stderr, "ERROR: Buffer overflow at %s:%d\n", __FILE__, __LINE__ );
139 : : lineBuffer.resize( idx + exp_size );
140 : : size = vsprintf( &lineBuffer[idx], fmt, args2 );
141 : : ++size; // trailing null
142 : : }
143 : : #endif
144 : :
145 : : // less one because we don't want the trailing '\0'
146 : 70 : lineBuffer.resize( idx + size - 1 );
147 : 70 : process_line_buffer();
148 : 70 : }
149 : :
150 : 96 : void ErrorOutput::process_line_buffer()
151 : : {
152 : 96 : size_t last_idx = 0;
153 : 96 : std::vector< char >::iterator i;
154 [ + - ][ + - ]: 288 : for( i = std::find( lineBuffer.begin(), lineBuffer.end(), '\n' ); i != lineBuffer.end();
[ + - ][ + + ]
155 : 192 : i = std::find( i, lineBuffer.end(), '\n' ) )
156 : : {
157 [ + - ]: 96 : *i = '\0';
158 [ + - ][ + + ]: 96 : if( have_rank() )
159 [ + - ][ + - ]: 66 : outputImpl->println( get_rank(), &lineBuffer[last_idx] );
[ + - ]
160 : : else
161 [ + - ][ + - ]: 30 : outputImpl->println( &lineBuffer[last_idx] );
162 [ + - ]: 96 : ++i;
163 [ + - ]: 96 : last_idx = i - lineBuffer.begin();
164 : : }
165 : :
166 [ + - ]: 96 : if( last_idx )
167 : : {
168 [ + - ][ + - ]: 96 : i = std::copy( lineBuffer.begin() + last_idx, lineBuffer.end(), lineBuffer.begin() );
169 [ + - ]: 96 : lineBuffer.erase( i, lineBuffer.end() );
170 : : }
171 : 96 : }
172 : :
173 [ + - ][ + - ]: 228 : } // namespace moab
|