|
IFPACK Development
|
00001 /*@HEADER 00002 // *********************************************************************** 00003 // 00004 // Ifpack: Object-Oriented Algebraic Preconditioner Package 00005 // Copyright (2009) Sandia Corporation 00006 // 00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive 00008 // license for use of this work by or on behalf of the U.S. Government. 00009 // 00010 // This library is free software; you can redistribute it and/or modify 00011 // it under the terms of the GNU Lesser General Public License as 00012 // published by the Free Software Foundation; either version 2.1 of the 00013 // License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, but 00016 // WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 00023 // USA 00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00025 // 00026 // *********************************************************************** 00027 //@HEADER 00028 */ 00029 00030 /* Contains definitions of globally scoped objects; 00031 * Also, functions for error handling and message logging. 00032 */ 00033 00034 #include "euclid_common.h" 00035 #include "Parser_dh.h" 00036 #include "Mem_dh.h" 00037 #include "TimeLog_dh.h" 00038 extern void sigRegister_dh (); /* use sig_dh.h if not for euclid_signals_len */ 00039 00040 /*------------------------------------------------------------------------- 00041 * Globally scoped variables, flags, and objects 00042 *-------------------------------------------------------------------------*/ 00043 bool errFlag_dh = false; /* set to "true" by functions encountering errors */ 00044 Parser_dh parser_dh = NULL; /* for setting/getting runtime options */ 00045 TimeLog_dh tlog_dh = NULL; /* internal timing functionality */ 00046 Mem_dh mem_dh = NULL; /* memory management */ 00047 FILE *logFile = NULL; 00048 char msgBuf_dh[MSG_BUF_SIZE_DH]; /* for internal use */ 00049 int np_dh = 1; /* number of processors and subdomains */ 00050 int myid_dh = 0; /* rank of this processor (and subdomain) */ 00051 MPI_Comm comm_dh = 0; 00052 00053 00054 /* Each processor (may) open a logfile. 00055 * The bools are switches for controlling the amount of informational 00056 * output, and where it gets written to. Function logging is only enabled 00057 * when compiled with the debugging (-g) option. 00058 */ 00059 FILE *logFile; 00060 void openLogfile_dh (int argc, char *argv[]); 00061 void closeLogfile_dh (); 00062 bool logInfoToStderr = false; 00063 bool logInfoToFile = false; 00064 bool logFuncsToStderr = false; 00065 bool logFuncsToFile = false; 00066 00067 bool ignoreMe = true; 00068 int ref_counter = 0; 00069 00070 00071 /*------------------------------------------------------------------------- 00072 * End of global definitions. 00073 * Error and info functions follow. 00074 *-------------------------------------------------------------------------*/ 00075 00076 #define MAX_MSG_SIZE 1024 00077 #define MAX_STACK_SIZE 20 00078 00079 static char errMsg_private[MAX_STACK_SIZE][MAX_MSG_SIZE]; 00080 static int errCount_private = 0; 00081 00082 static char calling_stack[MAX_STACK_SIZE][MAX_MSG_SIZE]; 00083 /* static int priority_private[MAX_STACK_SIZE]; */ 00084 static int calling_stack_count = 0; 00085 00086 /* static char errMsg[MAX_MSG_SIZE]; */ 00087 00088 void 00089 openLogfile_dh (int argc, char *argv[]) 00090 { 00091 char buf[1024]; 00092 00093 /* this doesn't really belong here, but it's gotta go someplace! */ 00094 /* strcpy(errMsg, "error msg was never set -- ??"); */ 00095 00096 if (logFile != NULL) 00097 return; 00098 00099 /* set default logging filename */ 00100 sprintf (buf, "logFile"); 00101 00102 /* set user supplied logging filename, if one was specified */ 00103 if (argc && argv != NULL) 00104 { 00105 int j; 00106 for (j = 1; j < argc; ++j) 00107 { 00108 if (strcmp (argv[j], "-logFile") == 0) 00109 { 00110 if (j + 1 < argc) 00111 { 00112 sprintf (buf, "%s", argv[j + 1]); 00113 break; 00114 } 00115 } 00116 } 00117 } 00118 00119 /* attempt to open logfile, unless the user entered "-logFile none" */ 00120 if (strcmp (buf, "none")) 00121 { 00122 char a[5]; 00123 sprintf (a, ".%i", myid_dh); 00124 strcat (buf, a); 00125 00126 if ((logFile = fopen (buf, "w")) == NULL) 00127 { 00128 fprintf (stderr, "can't open >%s< for writing; continuing anyway\n", 00129 buf); 00130 } 00131 } 00132 } 00133 00134 void 00135 closeLogfile_dh () 00136 { 00137 if (logFile != NULL) 00138 { 00139 if (fclose (logFile)) 00140 { 00141 fprintf (stderr, "Error closing logFile\n"); 00142 } 00143 logFile = NULL; 00144 } 00145 } 00146 00147 void 00148 setInfo_dh (char *msg, char *function, char *file, int line) 00149 { 00150 if (logInfoToFile && logFile != NULL) 00151 { 00152 fprintf (logFile, "INFO: %s;\n function= %s file=%s line=%i\n", 00153 msg, function, file, line); 00154 fflush (logFile); 00155 } 00156 if (logInfoToStderr) 00157 { 00158 fprintf (stderr, "INFO: %s;\n function= %s file=%s line=%i\n", 00159 msg, function, file, line); 00160 } 00161 } 00162 00163 /*---------------------------------------------------------------------- 00164 * Error handling stuph follows 00165 *----------------------------------------------------------------------*/ 00166 00167 void 00168 dh_StartFunc (char *function, char *file, int line, int priority) 00169 { 00170 if (priority == 1) 00171 { 00172 sprintf (calling_stack[calling_stack_count], 00173 "[%i] %s file= %s line= %i", myid_dh, function, file, 00174 line); 00175 /* priority_private[calling_stack_count] = priority; */ 00176 ++calling_stack_count; 00177 00178 if (calling_stack_count == MAX_STACK_SIZE) 00179 { 00180 fprintf (stderr, 00181 "_____________ dh_StartFunc: OVERFLOW _____________________\n"); 00182 if (logFile != NULL) 00183 { 00184 fprintf (logFile, 00185 "_____________ dh_StartFunc: OVERFLOW _____________________\n"); 00186 } 00187 --calling_stack_count; 00188 } 00189 } 00190 } 00191 00192 void 00193 dh_EndFunc (char *function, int priority) 00194 { 00195 if (priority == 1) 00196 { 00197 --calling_stack_count; 00198 00199 if (calling_stack_count < 0) 00200 { 00201 calling_stack_count = 0; 00202 fprintf (stderr, 00203 "_____________ dh_EndFunc: UNDERFLOW _____________________\n"); 00204 if (logFile != NULL) 00205 { 00206 fprintf (logFile, 00207 "_____________ dh_EndFunc: UNDERFLOW _____________________\n"); 00208 } 00209 } 00210 } 00211 } 00212 00213 00214 void 00215 setError_dh (char *msg, char *function, char *file, int line) 00216 { 00217 errFlag_dh = true; 00218 if (!strcmp (msg, "")) 00219 { 00220 sprintf (errMsg_private[errCount_private], 00221 "[%i] called from: %s file= %s line= %i", 00222 myid_dh, function, file, line); 00223 } 00224 else 00225 { 00226 sprintf (errMsg_private[errCount_private], 00227 "[%i] ERROR: %s\n %s file= %s line= %i\n", 00228 myid_dh, msg, function, file, line); 00229 } 00230 ++errCount_private; 00231 00232 /* shouldn't do things like this; but we're not building 00233 for the ages: all the world's a stage, this is merely a 00234 prop to be bonfired at play's end. 00235 */ 00236 if (errCount_private == MAX_STACK_SIZE) 00237 --errCount_private; 00238 } 00239 00240 void 00241 printErrorMsg (FILE * fp) 00242 { 00243 if (!errFlag_dh) 00244 { 00245 fprintf (fp, "errFlag_dh is not set; nothing to print!\n"); 00246 fflush (fp); 00247 } 00248 else 00249 { 00250 int i; 00251 fprintf (fp, 00252 "\n============= error stack trace ====================\n"); 00253 for (i = 0; i < errCount_private; ++i) 00254 { 00255 fprintf (fp, "%s\n", errMsg_private[i]); 00256 } 00257 fprintf (fp, "\n"); 00258 fflush (fp); 00259 } 00260 } 00261 00262 void 00263 printFunctionStack (FILE * fp) 00264 { 00265 int i; 00266 for (i = 0; i < calling_stack_count; ++i) 00267 { 00268 fprintf (fp, "%s\n", calling_stack[i]); 00269 } 00270 fprintf (fp, "\n"); 00271 fflush (fp); 00272 } 00273 00274 00275 /*---------------------------------------------------------------------- 00276 * function call tracing support follows 00277 *----------------------------------------------------------------------*/ 00278 00279 #define MAX_ERROR_SPACES 200 00280 static char spaces[MAX_ERROR_SPACES]; 00281 static int nesting = 0; 00282 static bool initSpaces = true; 00283 #define INDENT_DH 3 00284 00285 void 00286 Error_dhStartFunc (char *function, char *file, int line) 00287 { 00288 if (initSpaces) 00289 { 00290 memset (spaces, ' ', MAX_ERROR_SPACES * sizeof (char)); 00291 initSpaces = false; 00292 } 00293 00294 /* get rid of string null-terminator from last 00295 * call (if any) to Error_dhStartFunc() 00296 */ 00297 spaces[INDENT_DH * nesting] = ' '; 00298 00299 /* add null-terminator, so the correct number of spaces will be printed */ 00300 ++nesting; 00301 if (nesting > MAX_ERROR_SPACES - 1) 00302 nesting = MAX_ERROR_SPACES - 1; 00303 spaces[INDENT_DH * nesting] = '\0'; 00304 00305 if (logFuncsToStderr) 00306 { 00307 fprintf (stderr, "%s(%i) %s [file= %s line= %i]\n", 00308 spaces, nesting, function, file, line); 00309 } 00310 if (logFuncsToFile && logFile != NULL) 00311 { 00312 fprintf (logFile, "%s(%i) %s [file= %s line= %i]\n", 00313 spaces, nesting, function, file, line); 00314 fflush (logFile); 00315 } 00316 } 00317 00318 void 00319 Error_dhEndFunc (char *function) 00320 { 00321 nesting -= 1; 00322 if (nesting < 0) 00323 nesting = 0; 00324 spaces[INDENT_DH * nesting] = '\0'; 00325 } 00326 00327 /*---------------------------------------------------------------------- 00328 * Euclid initialization and shutdown 00329 *----------------------------------------------------------------------*/ 00330 00331 static bool EuclidIsActive = false; 00332 00333 #undef __FUNC__ 00334 #define __FUNC__ "EuclidIsInitialized" 00335 bool 00336 EuclidIsInitialized () 00337 { 00338 return EuclidIsActive; 00339 } 00340 00341 #undef __FUNC__ 00342 #define __FUNC__ "EuclidInitialize" 00343 void 00344 EuclidInitialize (int argc, char *argv[], char *help) 00345 { 00346 if (!EuclidIsActive) 00347 { 00348 MPI_Comm_size (comm_dh, &np_dh); 00349 MPI_Comm_rank (comm_dh, &myid_dh); 00350 openLogfile_dh (argc, argv); 00351 if (mem_dh == NULL) 00352 { 00353 Mem_dhCreate (&mem_dh); 00354 CHECK_V_ERROR; 00355 } 00356 if (tlog_dh == NULL) 00357 { 00358 TimeLog_dhCreate (&tlog_dh); 00359 CHECK_V_ERROR; 00360 } 00361 if (parser_dh == NULL) 00362 { 00363 Parser_dhCreate (&parser_dh); 00364 CHECK_V_ERROR; 00365 } 00366 Parser_dhInit (parser_dh, argc, argv); 00367 CHECK_V_ERROR; 00368 if (Parser_dhHasSwitch (parser_dh, "-sig_dh")) 00369 { 00370 sigRegister_dh (); 00371 CHECK_V_ERROR; 00372 } 00373 if (Parser_dhHasSwitch (parser_dh, "-help")) 00374 { 00375 if (myid_dh == 0) 00376 printf ("%s\n\n", help); 00377 EUCLID_EXIT; 00378 } 00379 if (Parser_dhHasSwitch (parser_dh, "-logFuncsToFile")) 00380 { 00381 logFuncsToFile = true; 00382 } 00383 if (Parser_dhHasSwitch (parser_dh, "-logFuncsToStderr")) 00384 { 00385 logFuncsToStderr = true; 00386 } 00387 00388 EuclidIsActive = true; 00389 } 00390 00391 } 00392 00393 00394 /* to do: should restore the signal handler that we preempted above! */ 00395 #undef __FUNC__ 00396 #define __FUNC__ "EuclidFinalize" 00397 void 00398 EuclidFinalize () 00399 { 00400 if (ref_counter) 00401 return; 00402 00403 if (EuclidIsActive) 00404 { 00405 if (parser_dh != NULL) 00406 { 00407 Parser_dhDestroy (parser_dh); 00408 CHECK_V_ERROR; 00409 } 00410 if (tlog_dh != NULL) 00411 { 00412 TimeLog_dhDestroy (tlog_dh); 00413 CHECK_V_ERROR; 00414 } 00415 if (logFile != NULL) 00416 { 00417 Mem_dhPrint (mem_dh, logFile, true); 00418 CHECK_V_ERROR; 00419 } 00420 /* Mem_dhPrint(mem_dh, stderr, false); CHECK_V_ERROR; */ 00421 if (mem_dh != NULL) 00422 { 00423 Mem_dhDestroy (mem_dh); 00424 CHECK_V_ERROR; 00425 } 00426 if (logFile != NULL) 00427 { 00428 closeLogfile_dh (); 00429 CHECK_V_ERROR; 00430 } 00431 EuclidIsActive = false; 00432 } 00433 } 00434 00435 00436 /*---------------------------------------------------------------------- 00437 * msc. support functions 00438 *----------------------------------------------------------------------*/ 00439 00440 #undef __FUNC__ 00441 #define __FUNC__ "printf_dh" 00442 void 00443 printf_dh (char *fmt, ...) 00444 { 00445 START_FUNC_DH va_list args; 00446 char *buf = msgBuf_dh; 00447 00448 va_start (args, fmt); 00449 vsprintf (buf, fmt, args); 00450 if (myid_dh == 0) 00451 { 00452 fprintf (stdout, "%s", buf); 00453 } 00454 va_end (args); 00455 END_FUNC_DH} 00456 00457 #undef __FUNC__ 00458 #define __FUNC__ "fprintf_dh" 00459 void 00460 fprintf_dh (FILE * fp, char *fmt, ...) 00461 { 00462 START_FUNC_DH va_list args; 00463 char *buf = msgBuf_dh; 00464 00465 va_start (args, fmt); 00466 vsprintf (buf, fmt, args); 00467 if (myid_dh == 0) 00468 { 00469 fprintf (fp, "%s", buf); 00470 } 00471 va_end (args); 00472 END_FUNC_DH} 00473 00474 00475 #undef __FUNC__ 00476 #define __FUNC__ "echoInvocation_dh" 00477 void 00478 echoInvocation_dh (MPI_Comm comm, char *prefix, int argc, char *argv[]) 00479 { 00480 START_FUNC_DH int i, id; 00481 00482 MPI_Comm_rank (comm, &id); 00483 00484 if (prefix != NULL) 00485 { 00486 printf_dh ("\n%s ", prefix); 00487 } 00488 else 00489 { 00490 printf_dh ("\n"); 00491 } 00492 00493 printf_dh ("program invocation: "); 00494 for (i = 0; i < argc; ++i) 00495 { 00496 printf_dh ("%s ", argv[i]); 00497 } 00498 printf_dh ("\n"); 00499 END_FUNC_DH}
1.7.4