Flow123d  release_2.2.0-41-g0958a8d
system.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file system.cc
15  * @ingroup system
16  * @brief Various system-wide functions
17  */
18 
19 #include <cstring>
20 #include <cstdarg>
21 #include <ctime>
22 #include <cstdlib>
23 #include <sys/stat.h>
24 #include <cerrno>
25 #include <sstream>
26 
27 #include <fstream>
28 #include <string>
29 #include "mpi.h"
30 
31 #include "system/system.hh"
32 #include "system/file_path.hh"
33 #include "system/sys_profiler.hh"
34 
35 #include <boost/algorithm/string/predicate.hpp>
36 #include <boost/algorithm/string/trim.hpp>
37 #include <boost/format.hpp>
38 
39 
40 
42 
43 
44 /// @brief INTERNAL DEFINITIONS FOR XPRINTF
45 /// @{
46 
47 struct MsgFmt {
48  int num; ///< format number
49  bool log; ///< log the message - YES/NO
50  bool mpi; ///< treat as global message (invoke MPI_Barrier() when printing)
51  int screen; ///< print to stdout,stderr,NULL
52  bool stop; ///< terminate the program
53  const char * head; ///< message formating string
54 };
55 
56 #define SCR_NONE 0
57 #define SCR_STDOUT 1
58 #define SCR_STDERR 2
59 
60 /// configuration table for individual message types defined in system.h
61 /// Msg type Log mpi screen Stop message header
62 #define NUM_OF_FMTS 8
63 static struct MsgFmt msg_fmt[] = {
64  {Msg, true, false, SCR_STDOUT, false, NULL},
65  {MsgDbg, true, false, SCR_STDOUT, false, " DBG (%s, %s(), %d):"},
66  {MsgLog, true, false, SCR_NONE, false, NULL},
67  {MsgVerb, false, false, SCR_STDOUT, false, NULL},
68  {Warn, true, false, SCR_STDERR, false, "\nWarning (%s, %s(), %d):\n"},
69  {UsrErr, true, false, SCR_NONE, true, "\nUser Error (%s, %s(), %d):\n"},
70  {Err, true, false, SCR_NONE, true, "\nError (%s, %s(), %d):\n"},
71  {PrgErr, true, false, SCR_NONE, true, "\nInternal Error (%s, %s(), %d):\n"}
72 };
73 
74 /// @}
75 
76 /*!
77  * @brief Multi-purpose printing routine: messages, warnings, errors
78  * @param[in] xprintf_file current file
79  * @param[in] xprintf_func current function
80  * @param[in] xprintf_line current line number
81  * @param[in] type message type
82  * @param[in] fmt message format
83  * @return Same as printf, what internal printing routine returns.
84  */
85 int _xprintf(const char * const xprintf_file, const char * const xprintf_func, const int xprintf_line, MessageType type, const char * const fmt, ... )
86 {
87  struct MsgFmt mf;
88  int rc;
89  FILE *screen=NULL;
90 
91  static int mpi_msg_id = 0;
92  int ierr;
93 
94  if ((type == MsgVerb) && (sys_info.verbosity <= 0))
95  return 0;
96 
97  if ((type < 0) || (type >= NUM_OF_FMTS))
98  type = Msg;
99  mf = msg_fmt[type];
100 
101  // determine output stream
102  switch (mf.screen) {
103  case SCR_STDOUT : screen=stdout; break;
104  case SCR_STDERR : screen=stderr; break;
105  case SCR_NONE : screen=NULL; break;
106  default: screen=NULL;
107  }
108 
109  {
110  va_list argptr;
111  if (mf.stop) {
112  char format_message[1024];
113  va_start( argptr, fmt );
114  vsprintf(format_message, fmt, argptr);
115  va_end( argptr );
116 
117  // explicit flush of all streams
118  fflush(NULL);
119  BOOST_THROW_EXCEPTION( ExcXprintfMsg()
120  << EI_XprintfHeader( boost::str(boost::format(mf.head) % xprintf_file % xprintf_func % xprintf_line) )
121  << EI_XprintfMessage( format_message ) );
122  }
123  }
124 
125  ASSERT(false).error("Non error usage of xprintf is not allowed.");
126 
127 #ifdef MPI_PRINTALL
128  //print msg header with mpi_id to distinguish the message origin
129  if (screen)
130  fprintf(screen,"[mpi_id=%d] ", sys_info.my_proc );
131  if (mf.log && sys_info.log)
132  fprintf(sys_info.log,"[mpi_id=%d] ", sys_info.my_proc );
133 #else
134  //if not PRINTALL, allow console output only for MPI master, no need to print mpi_id
135  if ( (screen) && ( sys_info.my_proc != 0 ) )
136  screen = NULL;
137 #endif
138 
139  //generate barrier and unique ID for MPI messages
140  if (mf.mpi) {
141  ierr = MPI_Barrier(sys_info.comm);
142  if (ierr != MPI_SUCCESS ) {
143  printf("MPI_Barrier() error in xprintf()\n"); //can not call xprintf() when xprintf() is failing
144  exit( EXIT_FAILURE );
145  }
146 
147  // print global msg_id
148  if (screen)
149  fprintf(screen,"[msg_id=%d] ", mpi_msg_id );
150  if (mf.log && sys_info.log)
151  fprintf(sys_info.log,"[msg_id=%d] ", mpi_msg_id );
152  mpi_msg_id++;
153  }
154 #ifndef FLOW123D_DEBUG_MESSAGES
155  if (type == Warn) mf.head="\nWarning: ";
156 #endif
157  // print head
158  if (mf.head) {
159  if (screen) fprintf(screen,mf.head,xprintf_file,xprintf_func,xprintf_line);
160  if (mf.log && sys_info.log)
161  fprintf(sys_info.log,mf.head,xprintf_file,xprintf_func,xprintf_line);
162  }
163  // print message
164  {
165  va_list argptr;
166 
167  if (mf.log && sys_info.log)
168  {
169  va_start( argptr, fmt );
170  rc=vfprintf(sys_info.log,fmt,argptr); //rc=char written, <0 if err
171  va_end( argptr );
172  // flush every message (maybe there is a problem in cygwin without that)
173  fflush(sys_info.log);
174  }
175 
176  if (screen)
177  {
178  va_start( argptr, fmt );
179  rc=vfprintf(screen,fmt,argptr);
180  va_end( argptr );
181  // flush every message (maybe there is a problem in cygwin without that)
182  fflush(screen);
183  }
184  }
185 
186  return rc;
187 }
188 
189 
190 /*!
191  * @brief Memory allocation with checking.
192  *
193  * Allocates memory block with checking of correct size and successful allocation.
194  *
195  * @param[in] size New size for the memory block, in bytes.
196  * @return same as ISO C realloc()
197  *//*
198 void *xmalloc( size_t size )
199 {
200  void *rc;
201 
202 
203  if (size == 0 ) size++;
204  rc = malloc( size );
205  if ( rc == NULL ) xprintf(Err ,"Not enough memory for allocating %u bytes\n", size );
206 
207  return(rc);
208 }*/
209 
210 /*!
211  * @brief Reallocation of memory block with checking.
212  *
213  * Reallocates memory block with checking of successful reallocation.
214  * The size of the memory block pointed to by the ptr parameter is changed to the size bytes,
215  * expanding or reducing the amount of memory available in the block.
216  *
217  * The function may move the memory block to a new location, in which case the new location
218  * is returned. The content of the memory block is preserved up to the lesser of
219  * the new and old sizes, even if the block is moved. If the new size is larger, the value
220  * of the newly allocated portion is indeterminate.
221  *
222  * In case that ptr is NULL, the function behaves exactly as malloc,
223  * assigning a new block of size bytes and returning a pointer to the beginning of it.
224  *
225  * In case that the size is 0, the memory previously allocated in ptr is deallocated
226  * as if a call to free was made, and a NULL pointer is returned.
227  *
228  * @param[in] ptr Pointer to a memory block previously allocated
229  * @param[in] size New size for the memory block, in bytes.
230  * @return same as ISO C realloc()
231  */
232 
233 /*
234 void * xrealloc( void * ptr, size_t size )
235 {
236  void * rc;
237 
238  rc = realloc( ptr, size );
239  if ( rc == NULL ) xprintf(Err ,"Not enough memory for allocating %u bytes\n", size );
240 
241  return(rc);
242 }*/
243 
244 /*
245 void *operator new (std::size_t size, const my_new_t &) throw() {
246  return xmalloc(size);
247 }
248 
249 void *operator new[] (std::size_t size, const my_new_t &) throw() {
250  return xmalloc(size);
251 }
252 
253 void operator delete( void *p, const my_new_t &) throw ()
254 {
255  xfree(p);
256 }
257 
258 void operator delete[]( void *p, const my_new_t &) throw ()
259 {
260  xfree(p);
261 }
262 */
263 
264 
265 
266 
267 /*!
268  * @brief SYSTEM with err handling
269  */
270 /*
271 int xsystem( const char *cmd )
272 {
273  int rc;
274 
275  rc = system( cmd );
276  INPUT_CHECK(!( rc != 0 ),"Error executing external command: %s\n", cmd );
277  return(rc);
278 }*/
279 
280 /*!
281  * @brief MAKE BRAND NEW COPY OF STRING
282  */
283 /*
284 char *xstrcpy( const char *src )
285 {
286  char *rc;
287  size_t length;
288 
289  OLD_ASSERT(!( src == NULL ),"NULL pointer as argument of function xstrcpy()\n");
290  length = strlen( src ) + 1;
291  rc = (char*) xmalloc(length * sizeof(char));
292  strcpy( rc, src );
293  return(rc);
294 }*/
295 
296 /*!
297  * @brief STRTOK WITH ERROR HANDLING and whitespace delimiters
298  * @param[in] s strtok string pointer
299  * @param[in] position requested position of the token
300  * @return strtok return
301  */
302 /*
303 char *xstrtok(char *s, int position)
304 {
305  char *rc;
306  const char * const whitespace_delim=" \t\r\n";
307 
308  rc = xstrtok( s, whitespace_delim, position);
309  return(rc);
310 }
311 */
312 
313 /*!
314  * @brief STRTOK WITH ERROR HANDLING and user specified delimiters
315  * @param[in] s1 strtok string pointer
316  * @param[in] delim delimiters
317  * @param[in] position requested position of the token
318  * @return strtok return
319  *
320  * Function behaves like original strtok
321  */
322 /*
323 char *xstrtok( char *s1, const char *delim, int position )
324 {
325  char *rc;
326  static char * full_string = NULL;
327  static int token_count;
328 
329  OLD_ASSERT(!( delim == NULL ),"NULL pointer as delimiter in xstrtok()\n");
330 
331  if ( s1 )
332  {
333  if ( !full_string )
334  {
335  full_string = (char *)xmalloc( LINE_SIZE );
336  full_string[0] = 0x0;
337  }
338 
339  strncpy( full_string, s1, LINE_SIZE );
340  token_count = 0;
341  }
342 
343  INPUT_CHECK( token_count == position || position < 0, "Requested position %d dosn't match token position %d", position, token_count);
344  rc = strtok( s1, delim );
345  token_count++;
346 
347  INPUT_CHECK(!( rc == NULL ),"Missing token no. %d: original string '%s' with delimiters '%s'\n", token_count, full_string, delim );
348 
349  return(rc);
350 }
351 */
352 
353 /*!
354  * @brief Delete trailing whitespace characters (space,tab,CR,NL).
355  * @param[in,out] s string to change
356  * @return number of deleted characters
357  */
358 /*
359 int xchomp( char * s )
360 {
361  int no_erased = 0;
362  char * p;
363 
364  OLD_ASSERT( s, "Can not chomp NULL string.");
365 
366  if ( *s ) //string not empty
367  {
368  p = s;
369  while (*p)
370  p++; //find end of string
371  p--; //set p to the last character
372  while ((p >= s) && ((*p == ' ') || (*p == '\t') || (*p == '\r') || (*p == '\n')))
373  {
374  *p = 0x0;
375  no_erased++;
376  p--;
377  }
378  }
379  return(no_erased);
380 }*/
381 
382 
383 /*!
384  * @brief MKDIR WITH ERROR HANDLING
385  */
386 /*
387 int xmkdir( const char *s )
388 {
389  int rc;
390 
391  OLD_ASSERT(!( s == NULL ),"NULL pointer as argument of function xmkdir()\n");
392  rc = mkdir(s, S_IRWXU); // create dir with rwx perm. for user
393  if (errno == EEXIST)
394  rc = 0;
395  INPUT_CHECK(!( rc != 0 ),"Cannot make directory %s\n", s );
396 
397  return(rc);
398 }*/
399 
400 /*!
401  * @brief RMDIR with err handling
402  */
403 /*
404 int xrmdir( const char *s )
405 {
406  int rc;
407 
408  OLD_ASSERT(!( s == NULL ),"NULL pointer as argument of function xrmdir()\n");
409  rc = rmdir( s );
410  INPUT_CHECK(!( rc != 0 ),"Cannot delete directory %s\n", s );
411  return(rc);
412 }*/
413 
414 /*!
415  * @brief CHDIR WITH ERROR HANDLING
416  */
417 /*
418 int xchdir( const char *s )
419 {
420  int rc;
421 
422  OLD_ASSERT(!( s == NULL ),"NULL pointer as argument of function xchdir()\n");
423  rc = chdir( s );
424  INPUT_CHECK(!( rc != 0 ),"Cannot change directory to %s\n", s );
425  return(rc);
426 }*/
427 
428 /*!
429  * @brief DELETE a FILE with error handling
430  */
431 
432 /*
433 int xremove( const char *fname )
434 {
435  int rc;
436 
437  OLD_ASSERT(!( fname == NULL ),"NULL pointer as argument of function xremove()\n");
438  if( access( fname , F_OK ) == 0 )
439  {
440  rc = remove( fname );
441  INPUT_CHECK(!( rc != 0 ),"Cannot remove file %s\n", fname );
442  }
443  else
444  WarningOut() << "File '" << fname << "' does not exist, can not remove. Ignoring." << std::endl;
445 
446  return(rc);
447 }*/
448 
449 /*!
450  * @brief GET CURRENT WORKING DIRECTORY with error handling
451  */
452 /*
453 char *xgetcwd( void )
454 {
455  char tmp[PATH_MAX];
456  char * rc;
457 
458  rc = getcwd( tmp, PATH_MAX );
459  OLD_ASSERT( rc,"Cannot get name of current working directory\n");
460 
461  return(xstrcpy( tmp ));
462 }*/
463 
bool log
log the message - YES/NO
Definition: system.cc:49
#define MPI_SUCCESS
Definition: mpi.c:17
int my_proc
Definition: system.hh:78
Definition: system.hh:64
FILE * log
Definition: system.hh:75
int num
format number
Definition: system.cc:48
std::string format(CStringRef format_str, ArgList args)
Definition: format.h:3141
int verbosity
Definition: system.hh:72
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
Definition: system.hh:64
System structure for various global variables.
Definition: system.hh:71
Definition: system.hh:64
#define SCR_STDOUT
Definition: system.cc:57
bool stop
terminate the program
Definition: system.cc:52
#define SCR_NONE
Definition: system.cc:56
FMT_FUNC int fprintf(std::ostream &os, CStringRef format, ArgList args)
Definition: ostream.cc:56
int _xprintf(const char *const xprintf_file, const char *const xprintf_func, const int xprintf_line, MessageType type, const char *const fmt,...)
Multi-purpose printing routine: messages, warnings, errors.
Definition: system.cc:85
int screen
print to stdout,stderr,NULL
Definition: system.cc:51
Definition: system.hh:64
INTERNAL DEFINITIONS FOR XPRINTF.
Definition: system.cc:47
Definition: system.hh:64
MessageType
Identifiers for various output messages.
Definition: system.hh:63
Definition: system.hh:64
static struct MsgFmt msg_fmt[]
Definition: system.cc:63
SystemInfo sys_info
Definition: system.cc:41
#define NUM_OF_FMTS
Definition: system.cc:62
Definition: format.cc:82
Definition: system.hh:64
const char * head
message formating string
Definition: system.cc:53
#define MPI_Barrier(comm)
Definition: mpi.h:531
MPI_Comm comm
Definition: system.hh:80
#define SCR_STDERR
Definition: system.cc:58
void printf(BasicWriter< Char > &w, BasicCStringRef< Char > format, ArgList args)
Definition: printf.h:444
bool mpi
treat as global message (invoke MPI_Barrier() when printing)
Definition: system.cc:50