LifeV
LifeDebug.cpp
Go to the documentation of this file.
1 //@HEADER
2 /*
3 *******************************************************************************
4 
5 Copyright (C) 2004, 2005, 2007 EPFL, Politecnico di Milano, INRIA
6 Copyright (C) 2010 EPFL, Politecnico di Milano, Emory University
7 
8 This file is part of LifeV.
9 
10 LifeV is free software; you can redistribute it and/or modify
11 it under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation, either version 3 of the License, or
13 (at your option) any later version.
14 
15 LifeV is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19 
20 You should have received a copy of the GNU Lesser General Public License
21 along with LifeV. If not, see <http://www.gnu.org/licenses/>.
22 
23 *******************************************************************************
24 */
25 //@HEADER
26 /*!
27  @file
28  @brief Classes for debugging
29 
30  @date 13-12-2010
31  @author Christophe Prud'homme <christophe.prudhomme@epfl.ch>
32 
33  @maintainer Radu Popescu <radu.popescu@epfl.ch>
34 */
35 
36 #include <algorithm>
37 #include <cstdlib>
38 #include <cstring>
39 #include <errno.h>
40 #include <fstream>
41 #include <iterator>
42 
43 
44 #include <boost/lexical_cast.hpp>
45 
46 #ifdef HAVE_BACKTRACE
47 # include <execinfo.h>
48 #endif
49 
50 
51 #include <lifev/core/LifeV.hpp>
52 #include <lifev/core/util/LifeDebug.hpp>
53 
54 
55 namespace LifeV
56 {
57 
59 {
64 };
65 
66 // ===============================================
67 // Private data struct declaration for DebugStream
68 // ===============================================
69 
71 {
72  Private() :
73  debug ( false ),
74  flushFunction ( 0 )
75  {}
76 
77  bool debug;
78  std::ostringstream M_output;
79 
81 
82  static bool S_attached;
83  static std::ofstream S_logfile;
84 
85 };
86 
87 //
88 // getDescription
89 //
90 static std::map<unsigned int, std::string>* DebugAreas = 0;
91 static std::string* StringNull = 0;
92 static std::list<int>* AREAS;
93 static std::string* DEBUG_AREA = 0;
94 
95 namespace
96 {
97 
99 {
100  static bool alloc = false;
101  if ( alloc == false )
102  {
103  DEBUG_AREA = new std::string ( "" );
104  AREAS = new std::list<int>;
105  StringNull = new std::string ( "" );
106  DebugAreas = new std::map<unsigned int, std::string>;
107  alloc = true;
108 
109 
110  // read entries in sdebug.areas
111  std::ostringstream path;
112  path << LIFEV_PREFIX << "/share/lifev/debug.areas";
113 
114  std::ifstream fin ( path.str().c_str() );
115  if ( fin.fail () )
116  {
117  fin.open ( "../debug.areas" );
118  if ( fin.fail() )
119  {
120  Warning() << "The file debug.areas was not found.\n"
121  << " searched at ../debug.areas and\n"
122  << " " << path.str() << "\n";
123  }
124  }
125  while ( fin )
126  {
127  char line[256];
128  fin.getline ( line, 256 );
129  if ( line[ 0 ] == '\0' ||
130  line[ 0 ] == '\n' ||
131  line[ 0 ] == '#' ||
132  isspace ( line[ 0 ] ) )
133  {
134  continue;
135  }
136  std::istringstream sentry ( line );
137  std::vector<std::string> l;
138  std::copy ( std::istream_iterator<std::string, char> ( sentry ),
139  std::istream_iterator<std::string, char> (),
140  std::back_inserter ( l ) );
141  DebugAreas->insert ( std::make_pair ( std::atoi ( l[0].c_str() ), l[2] ) );
142  }
143 
144  char* env = getenv ("DEBUG");
145  if ( env )
146  {
147  *DEBUG_AREA = env;
148  }
149  std::istringstream is ( *DEBUG_AREA );
150 
151 
152  std::copy ( std::istream_iterator<int, char> ( is ),
153  std::istream_iterator<int, char> (),
154  std::back_inserter ( *AREAS ) );
155 
156  DebugAreas->insert ( std::make_pair ( 0, "" ) );
157 
158  }
159 }
160 std::string getDescription ( unsigned int area )
161 {
162  if ( DebugAreas->empty() )
163  {
164  return std::string ( "Area " ) + std::to_string (area);
165  }
166 
167  std::map<unsigned int, std::string>::iterator entry_it = DebugAreas->find ( area );
168 
169  if ( entry_it != DebugAreas->end() )
170  {
171  return entry_it->second;
172  }
173  else
174  {
175  return std::string ( "Area " ) + std::to_string (area);
176  }
177 
178 
179 }
180 }
181 
182 // =============================================
183 // DebugStream - Constructors
184 // =============================================
185 
186 DebugStream::DebugStream ( int area, int /*level*/, bool print )
187  :
188  M_data ( new Private )
189 {
191 
192  if ( DEBUG_AREA && ! DEBUG_AREA->empty() )
193  {
194  M_data->debug = ( std::find ( AREAS->begin (), AREAS->end (), area ) != AREAS->end() &&
195  print ) ||
196  ( !area );
197  }
198  else
199  {
200  M_data->debug = ( print && !area );
201  }
202  if ( M_data->debug )
203  {
204  M_data->M_output << getDescription ( area ) << ": ";
205  }
206 
207 }
208 
209 DebugStream::DebugStream ( const char* initialString, int area, int /*level*/, bool print )
210  :
211  M_data ( new Private )
212 {
214  if ( DEBUG_AREA && ! DEBUG_AREA->empty() )
215  {
216  M_data->debug = ( std::find ( AREAS->begin (), AREAS->end (), area ) != AREAS->end() &&
217  print ) ||
218  ( !area );
219  }
220  else
221  {
222  M_data->debug = ( print && !area );
223  }
224  if ( M_data->debug )
225  M_data->M_output << getDescription ( area ) << ": "
226  << initialString;
227 }
228 
230  :
231  M_data ( new Private )
232 {
235 }
237 {
238  delete M_data;
239 }
240 
241 // ========================================
242 // DebugStream Operators
243 // ========================================
244 
245 DebugStream& DebugStream::operator<< ( char const* s)
246 {
247  if ( M_data->debug )
248  {
249  M_data->M_output << s;
250  }
251  if ( s[strlen (s) - 1] == '\n')
252  {
253  flush();
254  }
255  return *this;
256 }
257 
258 DebugStream& DebugStream::operator<< ( double s)
259 {
260  if ( M_data->debug )
261  {
262  M_data->M_output << s;
263  flush();
264  }
265  return *this;
266 }
267 
268 DebugStream& DebugStream::operator<< ( std::string const& s)
269 {
270  if ( M_data->debug )
271  {
272  M_data->M_output << s;
273  }
274  if ( s[s.size() - 1] == '\n')
275  {
276  flush();
277  }
278  return *this;
279 }
280 
281 DebugStream& DebugStream::operator<< ( LifeV::LManipFunction f )
282 {
283  if ( M_data->debug )
284  {
285  (*f) ( *this );
286  }
287  return *this;
288 }
289 
290 // ==============================================
291 // DebugStream Public Methods
292 // ==============================================
293 
295 {
296  M_data->flushFunction = func;
297 }
298 
300 {
301  if ( !M_data->M_output.str().empty() )
302  {
303  if ( Private::S_attached )
304  {
305  Private::S_logfile << M_data->M_output.str();
306  }
307  else if ( M_data->flushFunction == 0 )
308  {
309  std::cerr << M_data->M_output.str();
310  }
311  else
312  {
313  M_data->flushFunction ( "%s", M_data->M_output.str().c_str() );
314  }
315  M_data->M_output.str ( "" );
316  }
317 
318 }
319 
320 // ==============================================
321 // DebugStream Static Methods
322 // ==============================================
323 
324 bool DebugStream::Private::S_attached = false;
325 std::ofstream DebugStream::Private::S_logfile;
326 
327 void DebugStream::attach ( std::string const& logfile )
328 {
329  std::ostringstream filename;
330  filename << logfile;
331 
332  if ( Private::S_logfile.is_open() )
333  {
334  Private::S_logfile.close();
335  }
336 
337  Private::S_logfile.open ( filename.str().c_str(), std::ios::out );
338 
339  if ( Private::S_logfile.fail() )
340  {
341  Warning() << "DebugStream::attach( " << logfile.c_str() << " ) failed to open " << filename.str() << "\n";
342  Warning() << "Redirecting to default output\n";
343  Private::S_attached = false;
344  }
345  else if ( Private::S_logfile.is_open() )
346  {
347  Private::S_logfile << filename.str() << " is opened for debug" << std::endl;
348  Private::S_attached = true;
349  }
350 }
351 
352 void DebugStream::attach ( std::string const& /*logfile*/, int /*area*/ )
353 {
354 }
355 
356 void DebugStream::detach ( std::string const& /*logfile*/, int /*area*/ )
357 {
358 }
359 
361 {
362 }
363 
364 #ifdef HAVE_LIFEV_DEBUG
367 {
368  return debugStream ( area, func );
369 }
370 
373 {
375  s.setFlush ( func );
376  return s;
377 }
378 
380 Debug ( bool cond, int area, DebugStream::stprintf func )
381 {
382  return debugStream ( cond, area, func );
383 }
384 
385 DebugStream debugStream ( bool cond, int area, DebugStream::stprintf /*func*/ )
386 {
387  if ( cond )
388  {
389  return DebugStream ( area, DEBUG_INFO );
390  }
391  else
392  {
393  return DebugStream ( 0, 0, false );
394  }
395 }
396 #endif
397 
398 DebugStream Warning ( int area )
399 {
400  return DebugStream ( "WARNING: ", area, DEBUG_WARN );
401 }
402 
403 DebugStream Warning ( bool cond, int area )
404 {
405  if ( cond )
406  {
407  return DebugStream ( "WARNING: ", area, DEBUG_WARN );
408  }
409  else
410  {
411  return DebugStream ( 0, 0, false );
412  }
413 
414 }
415 
416 DebugStream Error ( int area )
417 {
418  //debugStream () << LBacktrace() << "\n";
419  return DebugStream ( "ERROR: ", area, DEBUG_ERROR );
420 }
421 
422 DebugStream Error ( bool cond, int area )
423 {
424  //debugStream () << LBacktrace() << "\n";
425  if ( cond )
426  {
427  return DebugStream ( "ERROR: ", area, DEBUG_ERROR );
428  }
429  else
430  {
431  return DebugStream ( 0, 0, false );
432  }
433 
434 }
435 
436 DebugStream Fatal ( int area )
437 {
438  //LBacktrace();
439  return DebugStream ( "FATAL: ", area, DEBUG_FATAL );
440 }
441 
442 DebugStream Fatal ( bool cond, int area )
443 {
444  //LBacktrace();
445  if ( cond )
446  {
447  return DebugStream ( "FATAL: ", area, DEBUG_FATAL );
448  }
449  else
450  {
451  return DebugStream ( 0, 0, false );
452  }
453 }
454 
455 #ifdef HAVE_BACKTRACE
456 std::string backtrace ()
457 {
458  // show all backtrace
459  return backtrace ( -1 );
460 }
461 
462 std::string backtrace ( int levels )
463 {
465 
466  void* trace[256];
467  int n = backtrace ( trace, 256 );
468  char** strings = backtrace_symbols ( trace, n );
469 
470  if ( levels != -1 )
471  {
472  n = ( std::min ) ( n, levels );
473  }
474  os << "[\n";
475 
476  for (int i = 0; i < n; ++i)
477  {
478  os << i << ": " << strings[i] << "\n";
479  }
480  os << "]\n";
481  free (strings);
482 
483  return os.str();
484 }
485 #endif
486 
487 } // Namespace LifeV
488 
490 {
491  s << " " << strerror ( errno );
492  return s;
493 }
494 
496 {
497  s << "\n";
498  return s;
499 }
500 
502 {
503  s.flush();
504  return s;
505 }
DebugStream Warning(bool cond, int area=0)
Definition: LifeDebug.cpp:403
DebugStream Fatal(int area=0)
Definition: LifeDebug.cpp:436
static std::list< int > * AREAS
Definition: LifeDebug.cpp:92
DebugStream(DebugStream const &)
Definition: LifeDebug.cpp:229
static void detachAll()
Definition: LifeDebug.cpp:360
std::ostringstream M_output
Definition: LifeDebug.cpp:78
DebugStream(int area=0, int level=1, bool print=true)
Definition: LifeDebug.cpp:186
void setFlush(stprintf=0)
Definition: LifeDebug.cpp:294
LifeV::DebugStream & flush(LifeV::DebugStream &s)
Definition: LifeDebug.cpp:501
LifeV::DebugStream & perror(LifeV::DebugStream &s)
Definition: LifeDebug.cpp:489
std::string getDescription(unsigned int area)
Definition: LifeDebug.cpp:160
DebugStream Warning(int area=0)
Definition: LifeDebug.cpp:398
void updateInverseJacobian(const UInt &iQuadPt)
DebugStream Error(bool cond, int area=0)
Definition: LifeDebug.cpp:422
int(* stprintf)(const char *format,...)
Definition: LifeDebug.hpp:69
static std::string * StringNull
Definition: LifeDebug.cpp:91
DebugStream Fatal(bool cond, int area=0)
Definition: LifeDebug.cpp:442
static std::map< unsigned int, std::string > * DebugAreas
Definition: LifeDebug.cpp:90
DebugStream Error(int area=0)
Definition: LifeDebug.cpp:416
static std::ofstream S_logfile
Definition: LifeDebug.cpp:83
DebugLevels
Definition: LifeDebug.cpp:58
DebugStream(const char *initialString, int area=0, int level=1, bool print=true)
Definition: LifeDebug.cpp:209
static std::string * DEBUG_AREA
Definition: LifeDebug.cpp:93
LifeV::DebugStream & endl(LifeV::DebugStream &s)
Definition: LifeDebug.cpp:495