Ifpack Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
globalObjects.c
Go to the documentation of this file.
1 /*@HEADER
2 // ***********************************************************************
3 //
4 // Ifpack: Object-Oriented Algebraic Preconditioner Package
5 // Copyright (2002) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 //@HEADER
41 */
42 
43 /* Contains definitions of globally scoped objects;
44  * Also, functions for error handling and message logging.
45  */
46 
47 #include "euclid_common.h"
48 #include "Parser_dh.h"
49 #include "Mem_dh.h"
50 #include "TimeLog_dh.h"
51 extern void sigRegister_dh (); /* use sig_dh.h if not for euclid_signals_len */
52 
53 /*-------------------------------------------------------------------------
54  * Globally scoped variables, flags, and objects
55  *-------------------------------------------------------------------------*/
56 bool errFlag_dh = false; /* set to "true" by functions encountering errors */
57 Parser_dh parser_dh = NULL; /* for setting/getting runtime options */
58 TimeLog_dh tlog_dh = NULL; /* internal timing functionality */
59 Mem_dh mem_dh = NULL; /* memory management */
60 FILE *logFile = NULL;
61 char msgBuf_dh[MSG_BUF_SIZE_DH]; /* for internal use */
62 int np_dh = 1; /* number of processors and subdomains */
63 int myid_dh = 0; /* rank of this processor (and subdomain) */
64 MPI_Comm comm_dh = 0;
65 
66 
67  /* Each processor (may) open a logfile.
68  * The bools are switches for controlling the amount of informational
69  * output, and where it gets written to. Function logging is only enabled
70  * when compiled with the debugging (-g) option.
71  */
72 FILE *logFile;
73 void openLogfile_dh (int argc, char *argv[]);
74 void closeLogfile_dh ();
75 bool logInfoToStderr = false;
76 bool logInfoToFile = false;
77 bool logFuncsToStderr = false;
78 bool logFuncsToFile = false;
79 
80 bool ignoreMe = true;
81 int ref_counter = 0;
82 
83 
84 /*-------------------------------------------------------------------------
85  * End of global definitions.
86  * Error and info functions follow.
87  *-------------------------------------------------------------------------*/
88 
89 #define MAX_MSG_SIZE 1024
90 #define MAX_STACK_SIZE 20
91 
93 static int errCount_private = 0;
94 
96 /* static int priority_private[MAX_STACK_SIZE]; */
97 static int calling_stack_count = 0;
98 
99 /* static char errMsg[MAX_MSG_SIZE]; */
100 
101 void
102 openLogfile_dh (int argc, char *argv[])
103 {
104  char buf[1024];
105 
106  /* this doesn't really belong here, but it's gotta go someplace! */
107 /* strcpy(errMsg, "error msg was never set -- ??"); */
108 
109  if (logFile != NULL)
110  return;
111 
112  /* set default logging filename */
113  sprintf (buf, "logFile");
114 
115  /* set user supplied logging filename, if one was specified */
116  if (argc && argv != NULL)
117  {
118  int j;
119  for (j = 1; j < argc; ++j)
120  {
121  if (strcmp (argv[j], "-logFile") == 0)
122  {
123  if (j + 1 < argc)
124  {
125  sprintf (buf, "%s", argv[j + 1]);
126  break;
127  }
128  }
129  }
130  }
131 
132  /* attempt to open logfile, unless the user entered "-logFile none" */
133  if (strcmp (buf, "none"))
134  {
135  char a[5];
136  sprintf (a, ".%i", myid_dh);
137  strcat (buf, a);
138 
139  if ((logFile = fopen (buf, "w")) == NULL)
140  {
141  fprintf (stderr, "can't open >%s< for writing; continuing anyway\n",
142  buf);
143  }
144  }
145 }
146 
147 void
149 {
150  if (logFile != NULL)
151  {
152  if (fclose (logFile))
153  {
154  fprintf (stderr, "Error closing logFile\n");
155  }
156  logFile = NULL;
157  }
158 }
159 
160 void
161 setInfo_dh (char *msg, char *function, char *file, int line)
162 {
163  if (logInfoToFile && logFile != NULL)
164  {
165  fprintf (logFile, "INFO: %s;\n function= %s file=%s line=%i\n",
166  msg, function, file, line);
167  fflush (logFile);
168  }
169  if (logInfoToStderr)
170  {
171  fprintf (stderr, "INFO: %s;\n function= %s file=%s line=%i\n",
172  msg, function, file, line);
173  }
174 }
175 
176 /*----------------------------------------------------------------------
177  * Error handling stuph follows
178  *----------------------------------------------------------------------*/
179 
180 void
181 dh_StartFunc (char *function, char *file, int line, int priority)
182 {
183  if (priority == 1)
184  {
186  "[%i] %s file= %s line= %i", myid_dh, function, file,
187  line);
188  /* priority_private[calling_stack_count] = priority; */
190 
191  if (calling_stack_count == MAX_STACK_SIZE)
192  {
193  fprintf (stderr,
194  "_____________ dh_StartFunc: OVERFLOW _____________________\n");
195  if (logFile != NULL)
196  {
197  fprintf (logFile,
198  "_____________ dh_StartFunc: OVERFLOW _____________________\n");
199  }
201  }
202  }
203 }
204 
205 void
206 dh_EndFunc (char *function, int priority)
207 {
208  if (priority == 1)
209  {
211 
212  if (calling_stack_count < 0)
213  {
215  fprintf (stderr,
216  "_____________ dh_EndFunc: UNDERFLOW _____________________\n");
217  if (logFile != NULL)
218  {
219  fprintf (logFile,
220  "_____________ dh_EndFunc: UNDERFLOW _____________________\n");
221  }
222  }
223  }
224 }
225 
226 
227 void
228 setError_dh (char *msg, char *function, char *file, int line)
229 {
230  errFlag_dh = true;
231  if (!strcmp (msg, ""))
232  {
234  "[%i] called from: %s file= %s line= %i",
235  myid_dh, function, file, line);
236  }
237  else
238  {
240  "[%i] ERROR: %s\n %s file= %s line= %i\n",
241  myid_dh, msg, function, file, line);
242  }
244 
245  /* shouldn't do things like this; but we're not building
246  for the ages: all the world's a stage, this is merely a
247  prop to be bonfired at play's end.
248  */
251 }
252 
253 void
254 printErrorMsg (FILE * fp)
255 {
256  if (!errFlag_dh)
257  {
258  fprintf (fp, "errFlag_dh is not set; nothing to print!\n");
259  fflush (fp);
260  }
261  else
262  {
263  int i;
264  fprintf (fp,
265  "\n============= error stack trace ====================\n");
266  for (i = 0; i < errCount_private; ++i)
267  {
268  fprintf (fp, "%s\n", errMsg_private[i]);
269  }
270  fprintf (fp, "\n");
271  fflush (fp);
272  }
273 }
274 
275 void
277 {
278  int i;
279  for (i = 0; i < calling_stack_count; ++i)
280  {
281  fprintf (fp, "%s\n", calling_stack[i]);
282  }
283  fprintf (fp, "\n");
284  fflush (fp);
285 }
286 
287 
288 /*----------------------------------------------------------------------
289  * function call tracing support follows
290  *----------------------------------------------------------------------*/
291 
292 #define MAX_ERROR_SPACES 200
294 static int nesting = 0;
295 static bool initSpaces = true;
296 #define INDENT_DH 3
297 
298 void
299 Error_dhStartFunc (char *function, char *file, int line)
300 {
301  if (initSpaces)
302  {
303  memset (spaces, ' ', MAX_ERROR_SPACES * sizeof (char));
304  initSpaces = false;
305  }
306 
307  /* get rid of string null-terminator from last
308  * call (if any) to Error_dhStartFunc()
309  */
310  spaces[INDENT_DH * nesting] = ' ';
311 
312  /* add null-terminator, so the correct number of spaces will be printed */
313  ++nesting;
314  if (nesting > MAX_ERROR_SPACES - 1)
316  spaces[INDENT_DH * nesting] = '\0';
317 
318  if (logFuncsToStderr)
319  {
320  fprintf (stderr, "%s(%i) %s [file= %s line= %i]\n",
321  spaces, nesting, function, file, line);
322  }
323  if (logFuncsToFile && logFile != NULL)
324  {
325  fprintf (logFile, "%s(%i) %s [file= %s line= %i]\n",
326  spaces, nesting, function, file, line);
327  fflush (logFile);
328  }
329 }
330 
331 void
332 Error_dhEndFunc (char *function)
333 {
334  nesting -= 1;
335  if (nesting < 0)
336  nesting = 0;
337  spaces[INDENT_DH * nesting] = '\0';
338 }
339 
340 /*----------------------------------------------------------------------
341  * Euclid initialization and shutdown
342  *----------------------------------------------------------------------*/
343 
344 static bool EuclidIsActive = false;
345 
346 #undef __FUNC__
347 #define __FUNC__ "EuclidIsInitialized"
348 bool
350 {
351  return EuclidIsActive;
352 }
353 
354 #undef __FUNC__
355 #define __FUNC__ "EuclidInitialize"
356 void
357 EuclidInitialize (int argc, char *argv[], char *help)
358 {
359  if (!EuclidIsActive)
360  {
361  MPI_Comm_size (comm_dh, &np_dh);
362  MPI_Comm_rank (comm_dh, &myid_dh);
363  openLogfile_dh (argc, argv);
364  if (mem_dh == NULL)
365  {
366  Mem_dhCreate (&mem_dh);
368  }
369  if (tlog_dh == NULL)
370  {
371  TimeLog_dhCreate (&tlog_dh);
373  }
374  if (parser_dh == NULL)
375  {
376  Parser_dhCreate (&parser_dh);
378  }
379  Parser_dhInit (parser_dh, argc, argv);
381  if (Parser_dhHasSwitch (parser_dh, "-sig_dh"))
382  {
383  sigRegister_dh ();
385  }
386  if (Parser_dhHasSwitch (parser_dh, "-help"))
387  {
388  if (myid_dh == 0)
389  printf ("%s\n\n", help);
390  EUCLID_EXIT;
391  }
392  if (Parser_dhHasSwitch (parser_dh, "-logFuncsToFile"))
393  {
394  logFuncsToFile = true;
395  }
396  if (Parser_dhHasSwitch (parser_dh, "-logFuncsToStderr"))
397  {
398  logFuncsToStderr = true;
399  }
400 
401  EuclidIsActive = true;
402  }
403 
404 }
405 
406 
407 /* to do: should restore the signal handler that we preempted above! */
408 #undef __FUNC__
409 #define __FUNC__ "EuclidFinalize"
410 void
412 {
413  if (ref_counter)
414  return;
415 
416  if (EuclidIsActive)
417  {
418  if (parser_dh != NULL)
419  {
420  Parser_dhDestroy (parser_dh);
422  }
423  if (tlog_dh != NULL)
424  {
425  TimeLog_dhDestroy (tlog_dh);
427  }
428  if (logFile != NULL)
429  {
430  Mem_dhPrint (mem_dh, logFile, true);
432  }
433 /* Mem_dhPrint(mem_dh, stderr, false); CHECK_V_ERROR; */
434  if (mem_dh != NULL)
435  {
436  Mem_dhDestroy (mem_dh);
438  }
439  if (logFile != NULL)
440  {
441  closeLogfile_dh ();
443  }
444  EuclidIsActive = false;
445  }
446 }
447 
448 
449 /*----------------------------------------------------------------------
450  * msc. support functions
451  *----------------------------------------------------------------------*/
452 
453 #undef __FUNC__
454 #define __FUNC__ "printf_dh"
455 void
456 printf_dh (char *fmt, ...)
457 {
458  START_FUNC_DH va_list args;
459  char *buf = msgBuf_dh;
460 
461  va_start (args, fmt);
462  vsprintf (buf, fmt, args);
463  if (myid_dh == 0)
464  {
465  fprintf (stdout, "%s", buf);
466  }
467  va_end (args);
469 
470 #undef __FUNC__
471 #define __FUNC__ "fprintf_dh"
472 void
473 fprintf_dh (FILE * fp, char *fmt, ...)
474 {
475  START_FUNC_DH va_list args;
476  char *buf = msgBuf_dh;
477 
478  va_start (args, fmt);
479  vsprintf (buf, fmt, args);
480  if (myid_dh == 0)
481  {
482  fprintf (fp, "%s", buf);
483  }
484  va_end (args);
486 
487 
488 #undef __FUNC__
489 #define __FUNC__ "echoInvocation_dh"
490 void
491 echoInvocation_dh (MPI_Comm comm, char *prefix, int argc, char *argv[])
492 {
493  START_FUNC_DH int i, id;
494 
495  MPI_Comm_rank (comm, &id);
496 
497  if (prefix != NULL)
498  {
499  printf_dh ("\n%s ", prefix);
500  }
501  else
502  {
503  printf_dh ("\n");
504  }
505 
506  printf_dh ("program invocation: ");
507  for (i = 0; i < argc; ++i)
508  {
509  printf_dh ("%s ", argv[i]);
510  }
511  printf_dh ("\n");
void Parser_dhCreate(Parser_dh *p)
Definition: Parser_dh.c:68
void Mem_dhDestroy(Mem_dh m)
Definition: Mem_dh.c:91
#define CHECK_V_ERROR
Definition: macros_dh.h:138
bool logFuncsToStderr
Definition: globalObjects.c:77
bool ignoreMe
Definition: globalObjects.c:80
bool errFlag_dh
Definition: globalObjects.c:56
void TimeLog_dhCreate(TimeLog_dh *t)
Definition: TimeLog_dh.c:62
static bool initSpaces
static char calling_stack[MAX_STACK_SIZE][MAX_MSG_SIZE]
Definition: globalObjects.c:95
#define END_FUNC_DH
Definition: macros_dh.h:187
void openLogfile_dh(int argc, char *argv[])
#define MAX_MSG_SIZE
Definition: globalObjects.c:89
void dh_StartFunc(char *function, char *file, int line, int priority)
Parser_dh parser_dh
Definition: globalObjects.c:57
void TimeLog_dhDestroy(TimeLog_dh t)
Definition: TimeLog_dh.c:78
bool Parser_dhHasSwitch(Parser_dh p, char *s)
Definition: Parser_dh.c:213
int np_dh
Definition: globalObjects.c:62
static int calling_stack_count
Definition: globalObjects.c:97
void printFunctionStack(FILE *fp)
TimeLog_dh tlog_dh
Definition: globalObjects.c:58
#define EUCLID_EXIT
Definition: euclid_config.h:69
void printf_dh(char *fmt,...)
static bool EuclidIsActive
void echoInvocation_dh(MPI_Comm comm, char *prefix, int argc, char *argv[])
void Parser_dhDestroy(Parser_dh p)
Definition: Parser_dh.c:94
MPI_Comm comm_dh
Definition: globalObjects.c:64
static char spaces[MAX_ERROR_SPACES]
void fprintf_dh(FILE *fp, char *fmt,...)
void Error_dhEndFunc(char *function)
static int errCount_private
Definition: globalObjects.c:93
void dh_EndFunc(char *function, int priority)
void EuclidInitialize(int argc, char *argv[], char *help)
#define START_FUNC_DH
Definition: macros_dh.h:181
void setInfo_dh(char *msg, char *function, char *file, int line)
void Parser_dhInit(Parser_dh p, int argc, char *argv[])
Definition: Parser_dh.c:148
void closeLogfile_dh()
#define INDENT_DH
bool logInfoToStderr
Definition: globalObjects.c:75
void printErrorMsg(FILE *fp)
#define MAX_STACK_SIZE
Definition: globalObjects.c:90
FILE * logFile
Definition: globalObjects.c:72
void Mem_dhCreate(Mem_dh *m)
Definition: Mem_dh.c:73
bool logInfoToFile
Definition: globalObjects.c:76
int ref_counter
Definition: globalObjects.c:81
bool EuclidIsInitialized()
int myid_dh
Definition: globalObjects.c:63
Definition: Mem_dh.c:60
void EuclidFinalize()
static char errMsg_private[MAX_STACK_SIZE][MAX_MSG_SIZE]
Definition: globalObjects.c:92
static int nesting
Mem_dh mem_dh
Definition: globalObjects.c:59
#define MAX_ERROR_SPACES
void Mem_dhPrint(Mem_dh m, FILE *fp, bool allPrint)
Definition: Mem_dh.c:163
void Error_dhStartFunc(char *function, char *file, int line)
char msgBuf_dh[MSG_BUF_SIZE_DH]
Definition: globalObjects.c:61
bool logFuncsToFile
Definition: globalObjects.c:78
void setError_dh(char *msg, char *function, char *file, int line)
#define MSG_BUF_SIZE_DH
void sigRegister_dh()
Definition: sig_dh.c:89