Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
ErrorOutput.cpp
Go to the documentation of this file.
1 #include "ErrorOutput.hpp"
2 #include "moab/MOABConfig.h"
3 
4 #include <iostream>
5 #include <cstring>
6 #include <algorithm>
7 #include <cassert>
8 
9 #ifdef MOAB_HAVE_MPI
10 #include "moab_mpi.h"
11 #endif
12 
13 namespace moab
14 {
15 
17 {
18  private:
19  FILE* filePtr;
20 
21  public:
22  FILEErrorStream( FILE* filep ) : filePtr( filep ) {}
23  void println( int rank, const char* str );
24  void println( const char* str );
25 };
26 
27 void FILEErrorStream::println( int rank, const char* str )
28 {
29  fprintf( filePtr, "[%d]MOAB ERROR: %s\n", rank, str );
30  fflush( filePtr );
31 }
32 
33 void FILEErrorStream::println( const char* str )
34 {
35  fprintf( filePtr, "MOAB ERROR: %s\n", str );
36  fflush( filePtr );
37 }
38 
40 {
41  private:
42  std::ostream& outStr;
43 
44  public:
45  CxxErrorStream( std::ostream& str ) : outStr( str ) {}
46  void println( int rank, const char* str );
47  void println( const char* str );
48 };
49 
50 void CxxErrorStream::println( int rank, const char* str )
51 {
52  outStr << "[" << rank << "]MOAB ERROR: " << str << std::endl;
53  outStr.flush();
54 }
55 
56 void CxxErrorStream::println( const char* str )
57 {
58  outStr << "MOAB ERROR: " << str << std::endl;
59  outStr.flush();
60 }
61 
62 ErrorOutput::ErrorOutput( FILE* impl ) : outputImpl( new FILEErrorStream( impl ) ), mpiRank( -1 )
63 {
64  lineBuffer.reserve( 1024 );
65 }
66 
67 ErrorOutput::ErrorOutput( std::ostream& str ) : outputImpl( new CxxErrorStream( str ) ), mpiRank( -1 )
68 {
69  lineBuffer.reserve( 1024 );
70 }
71 
73 {
74  if( !lineBuffer.empty() )
75  {
76  lineBuffer.push_back( '\n' );
78  }
79 
80  if( NULL != outputImpl )
81  {
82  delete outputImpl;
83  outputImpl = NULL;
84  }
85 }
86 
88 {
89 #ifdef MOAB_HAVE_MPI
90  int flag1;
91  MPI_Initialized( &flag1 );
92  int flag2;
93  MPI_Finalized( &flag2 );
94  if( flag1 && !flag2 ) MPI_Comm_rank( MPI_COMM_WORLD, &mpiRank );
95 #endif
96 }
97 
98 void ErrorOutput::print_real( const char* buffer )
99 {
100  lineBuffer.insert( lineBuffer.end(), buffer, buffer + strlen( buffer ) );
102 }
103 
104 void ErrorOutput::print_real( const std::string& str )
105 {
106  lineBuffer.insert( lineBuffer.end(), str.begin(), str.end() );
108 }
109 
110 void ErrorOutput::print_real( const char* fmt, va_list args1, va_list args2 )
111 {
112  size_t idx = lineBuffer.size();
113 #ifdef MOAB_HAVE_VSNPRINTF
114  // try once with remaining space in buffer
115  lineBuffer.resize( lineBuffer.capacity() );
116  unsigned size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args1 );
117  ++size; // trailing null
118  // if necessary, increase buffer size and retry
119  if( size > ( lineBuffer.size() - idx ) )
120  {
121  lineBuffer.resize( idx + size );
122  size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args2 );
123  ++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  lineBuffer.resize( idx + size - 1 );
148 }
149 
151 {
152  size_t last_idx = 0;
153  std::vector< char >::iterator i;
154  for( i = std::find( lineBuffer.begin(), lineBuffer.end(), '\n' ); i != lineBuffer.end();
155  i = std::find( i, lineBuffer.end(), '\n' ) )
156  {
157  *i = '\0';
158  if( have_rank() )
159  outputImpl->println( get_rank(), &lineBuffer[last_idx] );
160  else
161  outputImpl->println( &lineBuffer[last_idx] );
162  ++i;
163  last_idx = i - lineBuffer.begin();
164  }
165 
166  if( last_idx )
167  {
168  i = std::copy( lineBuffer.begin() + last_idx, lineBuffer.end(), lineBuffer.begin() );
169  lineBuffer.erase( i, lineBuffer.end() );
170  }
171 }
172 
173 } // namespace moab