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