globalObjects.c

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}

Generated on Tue Jul 13 09:27:13 2010 for IFPACK by  doxygen 1.4.7