• Main Page
  • Classes
  • Files
  • File List
  • File Members

ath_log.c

Go to the documentation of this file.
00001 #include "copyright.h"
00002 /*============================================================================*/
00003 /*! \file ath_log.c
00004  *  \brief Functions for controlling output to stderr and stdout.
00005  *
00006  * PURPOSE: Functions for controlling output to stderr and stdout.  On many
00007  *   machines, output to stderr and stdout does not scale well (to 10^{4-5}
00008  *   processors).  However, having output from all MPI processes can be useful
00009  *   for debugging.  Thus, some kind of runtime control that allows output to
00010  *   stderr and stdout be turned off for production runs, or redirected to
00011  *   files for debugging, is very helpful.
00012  *
00013  * CONTAINS PUBLIC FUNCTIONS:
00014  * - ath_log_out_open()  - opens out log file
00015  * - ath_log_err_open()  - opens err log file
00016  * - ath_log_set_level() - sets logging level from input arguments
00017  * - ath_log_open()      - calls output/error log file open if lazy == 0
00018  * - ath_log_close()     - closes output/error log file close
00019  * - athout_fp()         - returns pointer to out logfile
00020  * - atherr_fp()         - returns pointer to err logfile
00021  * - ath_flush_out()     - flushes out log file
00022  * - ath_flush_err()     - flushes err log file
00023  * - ath_perr()          - writes to err file
00024  * - ath_pout()          - writes to out file                                 */
00025 /*============================================================================*/
00026 
00027 #include <stdarg.h>
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <sys/types.h>
00032 #include <sys/stat.h>
00033 #include "prototypes.h"
00034 
00035 /* output and error log levels */
00036 static int out_level = 0, err_level = 0;
00037 
00038 /* Simulation output and error file pointers */
00039 static FILE *ath_fp_out = NULL, *ath_fp_err = NULL;
00040 
00041 /* Simulation output and error log file names */
00042 static char *out_fname = NULL, *err_fname = NULL;
00043 
00044 /* Logical flags indicating that the files need to be opened */
00045 static int open_out_flag = 0, open_err_flag = 0;
00046 
00047 /* Mode for which the log files are opened, e.g. "a" or "w" */
00048 static char log_mode[2] = "w";
00049 
00050 
00051 /*----------------------------------------------------------------------------*/
00052 /*! \fn static int ath_log_out_open(void)
00053  *  \brief Opens output log file (containing output to stdout).
00054  */
00055 static int ath_log_out_open(void)
00056 {
00057   int iExist=1;
00058   struct stat statinfo;
00059 
00060   open_out_flag = 0; /* zero the flag to open the file, only 1 try if we fail */
00061 
00062   if(log_mode[0] == 'a')
00063     iExist = stat(out_fname, &statinfo);
00064 
00065 /* open the ath_fp_out file pointer */
00066   if((ath_fp_out = fopen(out_fname, log_mode)) == NULL){
00067     fprintf(stderr,"[ath_log_out_open]: Failed to open ath_fp_out as \"%s\"\n",
00068             out_fname);
00069     return 1;
00070   }
00071 
00072   if(iExist == 0) /* Write a separator */
00073     fprintf(ath_fp_out, "\n***************************** Appending "
00074                         "Output Log *****************************\n\n");
00075 
00076   return 0;
00077 }
00078 
00079 /*----------------------------------------------------------------------------*/
00080 /*! \fn static int ath_log_err_open(void)
00081  *  \brief Opens error log file (containing output to stderr).
00082  */
00083 static int ath_log_err_open(void)
00084 {
00085   int iExist=1;
00086   struct stat statinfo;
00087 
00088   open_err_flag = 0; /* zero the flag to open the file, only 1 try if we fail */
00089 
00090   if(log_mode[0] == 'a')
00091     iExist = stat(err_fname, &statinfo);
00092 
00093 /* open the ath_fp_err file pointer */
00094   if((ath_fp_err = fopen(err_fname, log_mode)) == NULL){
00095     fprintf(stderr,"[ath_log_err_open]: Failed to open ath_fp_err as \"%s\"\n",
00096             err_fname);
00097     return 1;
00098   }
00099 
00100   if(iExist == 0) /* Write a separator */
00101     fprintf(ath_fp_err, "\n***************************** Appending "
00102                         "Error Log ******************************\n\n");
00103 
00104   return 0;
00105 }
00106 
00107 /*----------------------------------------------------------------------------*/
00108 /*! \fn void ath_log_set_level(const int out, const int err)
00109  *  \brief Sets "output level" and "error level" from input 
00110  *   arguments, global parameters used by many functions in this file.
00111  *
00112  *   Called from main(), where the parameters are parsed from athinput.
00113  */
00114 void ath_log_set_level(const int out, const int err)
00115 {
00116   out_level = out;
00117   err_level = err;
00118 
00119   return;
00120 }
00121 
00122 /*----------------------------------------------------------------------------*/
00123 /*! \fn void ath_log_open(const char *basename, const int lazy, 
00124  *                        const char *mode)
00125  *  \brief Opens output and error log files if "lazy" flag is false (0).
00126  *
00127  *   If "lazy" is true, then the ath_log_open() call does not actually open the
00128  *   files, but rather prepares to open them on the first invocation of either
00129  *   ath_pout() ath_perr(), athout_fp() or atherr_fp().  This is useful for
00130  *   parallel jobs where the children, if made sufficiently quiet would
00131  *   otherwise generate a large number of empty files. -- T. A. Gardiner -- 
00132  */
00133 void ath_log_open(const char *basename, const int lazy, const char *mode)
00134 {
00135   size_t size = strlen(basename) + 5; /* 5 = '.' + 'out' or 'err' + '\0' */
00136 
00137 /* ath_fp_out filename */
00138   if((out_fname = (char*)malloc(size*sizeof(char))) == NULL){
00139     fprintf(stderr,"[ath_log_open]: Error constructing filename \"%s.out\"\n",
00140             basename);
00141     exit(EXIT_FAILURE);
00142   }
00143   sprintf(out_fname,"%s.out",basename);
00144 
00145 /* ath_fp_err filename */
00146   if((err_fname = (char*)malloc(size*sizeof(char))) == NULL){
00147     fprintf(stderr,"[ath_log_open]: Error constructing filename \"%s.err\"\n",
00148             basename);
00149     exit(EXIT_FAILURE);
00150   }
00151   sprintf(err_fname,"%s.err",basename);
00152 
00153   /* Copy the mode string - Only "a" and "w" are allowed */
00154   log_mode[0] = (mode[0] == 'a') ? 'a' : 'w';
00155 
00156 /* Indicate that these files should be opened before any action is done. */
00157   open_out_flag = open_err_flag = 1;
00158 
00159   if(lazy == 0){
00160     /* open the files now and exit on failure! */
00161     if(ath_log_out_open() || ath_log_err_open())
00162       exit(EXIT_FAILURE);
00163   }
00164 
00165   return;
00166 }
00167 
00168 /*----------------------------------------------------------------------------*/
00169 /*! \fn void ath_log_close(void)
00170  *  \brief Closes output and error log files.
00171  */
00172 void ath_log_close(void)
00173 {
00174 /* clear the flags to open the log files */
00175   open_out_flag = open_err_flag = 0;
00176 
00177 /* free the log file names */
00178   if(out_fname != NULL){ free(out_fname);  out_fname = NULL; }
00179   if(err_fname != NULL){ free(err_fname);  err_fname = NULL; }
00180 
00181 /* close the files */
00182   if(ath_fp_out != NULL){ fclose(ath_fp_out);  ath_fp_out = NULL; }
00183   if(ath_fp_err != NULL){ fclose(ath_fp_err);  ath_fp_err = NULL; }
00184 
00185   return;
00186 }
00187 
00188 /*----------------------------------------------------------------------------*/
00189 /*! \fn FILE *athout_fp(void)
00190  *  \brief Open output file if needed and return a pointer to file.
00191  */
00192 FILE *athout_fp(void)
00193 {
00194 /* Open the output log file if it needs to be opened */
00195   if(open_out_flag) ath_log_out_open();
00196 
00197 /* Return either the output log file pointer or stdout */
00198   return (ath_fp_out == NULL ? stdout : ath_fp_out);
00199 }
00200 
00201 /*----------------------------------------------------------------------------*/
00202 /*! \fn FILE *atherr_fp(void)
00203  *  \brief Open error file if needed and return a pointer to file.
00204  */
00205 FILE *atherr_fp(void)
00206 {
00207 /* Open the error log file if it needs to be opened */
00208   if(open_err_flag) ath_log_err_open();
00209 
00210 /* Return either the error log file pointer or stderr */
00211   return (ath_fp_err == NULL ? stderr : ath_fp_err);
00212 }
00213 
00214 /*----------------------------------------------------------------------------*/
00215 /*! \fn void ath_flush_out(void)
00216  *  \brief Flush output file buffer.
00217  */
00218 void ath_flush_out(void)
00219 {
00220   FILE *fp;
00221 
00222   /* If the output log file needs to be opened then there's no data on
00223      the stream to flush.  Return with a successful completion. */
00224   if(open_out_flag) return;
00225   fp = (ath_fp_out == NULL ? stdout : ath_fp_out);
00226   fflush(fp);
00227 }
00228 
00229 /*----------------------------------------------------------------------------*/
00230 /*! \fn void ath_flush_err(void)
00231  *  \brief Flush error file buffer.
00232  */
00233 void ath_flush_err(void)
00234 {
00235   FILE *fp;
00236 
00237   /* If the error log file needs to be opened then there's no data on
00238      the stream to flush.  Return with a successful completion. */
00239   if(open_err_flag) return;
00240   fp = (ath_fp_err == NULL ? stderr : ath_fp_err);
00241   fflush(fp);
00242 }
00243 
00244 /*----------------------------------------------------------------------------*/
00245 /*! \fn int ath_perr(const int level, const char *fmt, ...)
00246  *  \brief Foutput variable argument string to "error log file".   
00247  *
00248  *  Should be used in place of printf(stderr,...)
00249  */
00250 int ath_perr(const int level, const char *fmt, ...)
00251 {
00252   va_list ap;
00253   int iret = 0;
00254   FILE *fp;
00255 
00256   if(level <= err_level){
00257     /* Open the error log file if it needs to be opened */
00258     if(open_err_flag) ath_log_err_open();
00259 
00260     /* Use either the error log file pointer or stderr */
00261     fp = (ath_fp_err == NULL ? stderr : ath_fp_err);
00262 
00263     va_start(ap, fmt);            /* ap starts after the fmt parameter */
00264     iret = vfprintf(fp, fmt, ap); /* print the error message to stderr */
00265     va_end(ap);                   /* end stdargs (clean up the va_list ap) */
00266   }
00267 
00268   return iret;
00269 }
00270 
00271 /*----------------------------------------------------------------------------*/
00272 /*! \fn int ath_pout(const int level, const char *fmt, ...)
00273  *  \brief Output variable argument string to "output log file".   
00274  *
00275  *  Should be used in place of printf(stdout,...)
00276  */
00277 int ath_pout(const int level, const char *fmt, ...)
00278 {
00279   va_list ap;
00280   int iret = 0;
00281   FILE *fp;
00282 
00283   if(level <= out_level){
00284     /* Open the output log file if it needs to be opened */
00285     if(open_out_flag) ath_log_out_open();
00286 
00287     /* Use either the output log file pointer or stdout */
00288     fp = (ath_fp_out == NULL ? stdout : ath_fp_out);
00289 
00290     va_start(ap, fmt);            /* ap starts after the fmt parameter */
00291     iret = vfprintf(fp, fmt, ap); /* print the error message to stderr */
00292     va_end(ap);                   /* end stdargs (clean up the va_list ap) */
00293   }
00294 
00295   return iret;
00296 }

Generated on Mon Sep 27 2010 23:03:06 for Athena by  doxygen 1.7.1