Mesh Oriented datABase  (version 5.5.1)
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  // try once with remaining space in buffer
114  lineBuffer.resize( lineBuffer.capacity() );
115  unsigned size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args1 );
116  ++size; // trailing null
117  // if necessary, increase buffer size and retry
118  if( size > ( lineBuffer.size() - idx ) )
119  {
120  lineBuffer.resize( idx + size );
121  size = vsnprintf( &lineBuffer[idx], lineBuffer.size() - idx, fmt, args2 );
122  ++size; // trailing null
123  }
124 
125  // less one because we don't want the trailing '\0'
126  lineBuffer.resize( idx + size - 1 );
128 }
129 
131 {
132  size_t last_idx = 0;
133  std::vector< char >::iterator i;
134  for( i = std::find( lineBuffer.begin(), lineBuffer.end(), '\n' ); i != lineBuffer.end();
135  i = std::find( i, lineBuffer.end(), '\n' ) )
136  {
137  *i = '\0';
138  if( have_rank() )
139  outputImpl->println( get_rank(), &lineBuffer[last_idx] );
140  else
141  outputImpl->println( &lineBuffer[last_idx] );
142  ++i;
143  last_idx = i - lineBuffer.begin();
144  }
145 
146  if( last_idx )
147  {
148  i = std::copy( lineBuffer.begin() + last_idx, lineBuffer.end(), lineBuffer.begin() );
149  lineBuffer.erase( i, lineBuffer.end() );
150  }
151 }
152 
153 } // namespace moab