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