vtf-logo

CLESLog.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 #ifndef AMROC_CLESLOG_H
00003 #define AMROC_CLESLOG_H
00004 
00005 //
00006 // Created: 4/1/06
00007 // Author : C. Pantano
00008 // Purpose: Simple logging system
00009 //
00010 
00011 #include <string>
00012 #include <stdlib.h>
00013 #include <stdio.h>
00014 #include <ctype.h>
00015 #include "DAGH.h"
00016 #include "../weno/src/generic/cles.h"
00017 
00018 #define CLESLOG_MSGMAXLEN 256
00019 #define CLESLOG_KEYMAXLEN 24
00020 #define CLESLOG_MAXINDENT 100
00021 #define CLESLOG_HEADERLEN 72
00022 
00023 #define CLESLOG_DEBUG   0
00024 #define CLESLOG_WARNING 1
00025 #define CLESLOG_ERROR   2
00026 
00027 #define CLESLOG_CBC         1
00028 #define CLESLOG_CBC_EIGENSYSTEM 1
00029 #define CLESLOG_CBC_REFPRESSURE 2
00030 
00031 #define CLESLOG_ROE         2
00032 #define CLESLOG_ROE_STATES      1
00033 
00034 #define CLESLOG_TCD         3
00035 #define CLESLOG_TCD_STENCIL     1
00036 
00037 class CLESLog {
00038 
00039 public:
00040 
00041 // main datastructure containing log messages
00042 struct ldtype {
00043     int _active;  // is this message activated
00044     int _mod;     // module ID
00045     int _loc;     // locatio ID
00046     int _lev;     // level or type of message
00047     char _msg[CLESLOG_MSGMAXLEN];      // message text
00048     char _mod_msg[CLESLOG_KEYMAXLEN];  // module name
00049     char _loc_msg[CLESLOG_KEYMAXLEN];  // location name
00050 };
00051 
00052   void register_at(ControlDevice& Ctrl, const std::string& prefix) {
00053     ControlDevice LocCtrl = Ctrl.getSubDevice(prefix+"Logging");
00054     
00055     RegisterAt(LocCtrl,"ActiveLogs",_DefFile);
00056     RegisterAt(LocCtrl,"Trace",_trace);
00057     
00058   }
00059 
00060 // report errors to stderr
00061 void jerror(const char* msg) {
00062     fprintf(stderr, "Error: ");
00063     fprintf(stderr, msg);
00064     fprintf(stderr, "\n");
00065     fflush(stderr);
00066 }
00067 
00068 char* trim(char* input) {
00069     // search beggining spaces
00070     int len = std::strlen(input);
00071     for ( int i = 0 ; i < len && isspace(input[i]) ; i ++ ) 
00072         input ++;
00073     
00074     len = std::strlen(input);
00075     for ( int i = len-1; i>=0 && isspace(input[i]) ; i-- ) 
00076         input[i] = '\0';
00077     return input;
00078 }
00079 
00080 // lookup log messages structures
00081 ldtype* lookup(int mod, int loc) {
00082     for ( int i=0 ; i < log_table_size ; i++ ) {
00083         ldtype* p = &(logtable[i]);
00084         if ( p->_mod == mod && p->_loc == loc )
00085             return p;
00086     }
00087 
00088     return NULL;
00089 }
00090 
00091 ldtype* lookup(char* mod, char* loc) {
00092     for ( int i=0 ; i < log_table_size ; i++ ) {
00093         ldtype* p = &(logtable[i]);
00094         if ( std::strncmp(p->_mod_msg,mod,CLESLOG_KEYMAXLEN-1) == 0 && 
00095              std::strncmp(p->_loc_msg, loc,CLESLOG_KEYMAXLEN-1) == 0 ) 
00096             return p;
00097     }
00098 
00099     return NULL;
00100 }
00101 
00102 // print a nice header
00103  void header() {
00104      char header[CLESLOG_HEADERLEN+1];
00105      header[0] = '#';
00106      for ( int i = 1; i < CLESLOG_HEADERLEN-1 ; i++ )
00107          header[i] = ( i%2 == 0 ? '/' : '\\' );
00108      header[CLESLOG_HEADERLEN-1] = '#';
00109      header[CLESLOG_HEADERLEN] = 0;
00110      for ( int i = 0 ; i < log_indent ; i++ )
00111          comm_service::log() << "   " ;
00112      // print msg header 
00113      (comm_service::log() << header << "\n").flush();
00114  }
00115 
00116  void mark(ldtype* p) {
00117      log_indent ++;
00118      requested_last[log_indent] = p;
00119  }
00120 
00121   void unmark() {
00122       requested_last[log_indent] = NULL;
00123       log_indent --;
00124   }
00125 
00126 // static variables
00127 static int reporting_level ; 
00128 static bool active_log ;
00129 static ldtype* requested_last[CLESLOG_MAXINDENT];
00130 static ldtype logtable[];
00131 static std::string _DefFile;
00132 static int log_table_size;
00133 static int log_indent;
00134 static int _trace;
00135 static int trace_indent;
00136 
00137  CLESLog() { } 
00138  ~CLESLog() { }
00139 
00140 // test if a log is active
00141  int inactive() {
00142      if ( active_log == false ) return 1;
00143      if ( requested_last[log_indent] == NULL ) return 1;
00144      if ( requested_last[log_indent]->_active == false ) return 1;
00145      return 0;
00146  }
00147 
00148 // read input keys and initialize
00149  void initialize() {
00150      for ( int i = 0 ; i < CLESLOG_MAXINDENT ; i ++ )
00151         requested_last[i] = NULL;
00152 
00153      if ( _DefFile.length() ) {
00154          active_log = true;
00155          
00156          FILE* pfile = fopen(_DefFile.c_str(), "r");
00157          if ( pfile == NULL ) return;
00158 
00159          char mod[CLESLOG_KEYMAXLEN];
00160          char loc[CLESLOG_KEYMAXLEN];
00161 
00162          while(feof(pfile) == 0) {
00163              if ( fscanf(pfile, "%s %s", mod, loc) == EOF ) break;
00164              
00165              ldtype* entry = lookup(mod, loc);
00166              if ( entry != NULL ) entry->_active = true;
00167          }
00168          fclose(pfile);
00169      }
00170  }
00171 
00172 // cleanup
00173  void finalize() {
00174      
00175  }
00176 
00177 };
00178 
00179 // tracing activation
00180 int  CLESLog::_trace = 0;
00181 int  CLESLog::trace_indent = 0;
00182 
00183 // default is error level
00184 int CLESLog::reporting_level = CLESLOG_ERROR;
00185 // default is inactive
00186 bool CLESLog::active_log = false;
00187 // nothing requested
00188 CLESLog::ldtype* CLESLog::requested_last[CLESLOG_MAXINDENT];
00189 // master table of message descriptions
00190 CLESLog::ldtype  CLESLog::logtable[] = { 
00191     {false, CLESLOG_CBC, CLESLOG_CBC_EIGENSYSTEM, CLESLOG_DEBUG, 
00192      "CBC->EIGENSYSTEM", "CBC", "EIGENSYSTEM" },
00193     {false, CLESLOG_CBC, CLESLOG_CBC_REFPRESSURE, CLESLOG_DEBUG,
00194      "CBC->REFPRESSURE", "CBC", "REFPRESSURE" },
00195     {false, CLESLOG_ROE, CLESLOG_ROE_STATES, CLESLOG_DEBUG,
00196      "ROE->STATES", "ROE", "STATES" },
00197     {false, CLESLOG_TCD, CLESLOG_TCD_STENCIL, CLESLOG_DEBUG,
00198      "TCD->STENCIL", "TCD", "STENCIL" }};
00199 
00200 // size of the table
00201 int CLESLog::log_table_size = sizeof(CLESLog::logtable)/sizeof(CLESLog::ldtype);
00202 int CLESLog::log_indent = -1;
00203 // activation file
00204 std::string CLESLog::_DefFile = "";
00205 
00206 extern "C" {
00207 
00208     // test if a log message is active
00209 #define f_cleslog_active FORTRAN_NAME_(cleslog_active, CLESLOG_ACTIVE)
00210     int f_cleslog_active(int& module, int& loc) {
00211         CLESLog me;
00212         CLESLog::ldtype* p;
00213 
00214         if ( me.active_log == false ) return CLES_FALSE;        
00215         if ( (p=me.lookup(module, loc)) == NULL ) return CLES_FALSE;
00216         if ( p->_active == false ) return CLES_FALSE;
00217         
00218         me.mark(p);
00219         me.header();
00220 
00221         char * header;
00222         switch ( me.requested_last[me.log_indent]->_lev ) {
00223             case CLESLOG_DEBUG:   header = "DEBUG:   "; break;
00224             case CLESLOG_WARNING: header = "WARNING: "; break;
00225             case CLESLOG_ERROR:   header = "ERROR:   "; break;
00226             default: header = "UNKNOWN: ";
00227         }
00228         for ( int i = 0 ; i < me.log_indent ; i++ )
00229             comm_service::log() << "\t" ;
00230         (comm_service::log() << header << 
00231          me.requested_last[me.log_indent]->_msg << "\n").flush();
00232         return CLES_TRUE;
00233     }
00234 
00235     // test if a log message is active for warning and error messages
00236 #define f_cleslog_activate FORTRAN_NAME_(cleslog_activate, CLESLOG_ACTIVATE)
00237     int f_cleslog_activate(int& module, int& loc) {
00238         CLESLog me;
00239         CLESLog::ldtype* p;
00240 
00241         if ( (p=me.lookup(module, loc)) == NULL ) return CLES_FALSE;
00242         if ( p->_lev > CLESLOG_DEBUG ) {
00243             me.active_log = true;
00244             p->_active = true;
00245             return f_cleslog_active(module, loc);
00246         }
00247         return CLES_FALSE;
00248     }
00249 
00250     // write log
00251 #define f_cleslog_log FORTRAN_NAME_(cleslog_log, CLESLOG_LOG)
00252     void f_cleslog_log(char* msg) {
00253         CLESLog me;
00254 
00255         if ( me.inactive() ) return;
00256         
00257         for ( int i = 0 ; i < me.log_indent ; i++ )
00258             comm_service::log() << "   " ;
00259         //char *lmsg = (char*)malloc(std::strlen(msg)+1);
00260         //char *tmsg;
00261         //strcpy(lmsg, msg);
00262         //tmsg = me.trim(lmsg);
00263         (comm_service::log() << msg  << "\n").flush();
00264         //free(lmsg);
00265     }
00266 
00267     // close log
00268 #define f_cleslog_log_flush FORTRAN_NAME_(cleslog_log_flush, CLESLOG_LOG)
00269     void f_cleslog_log_flush(void) {
00270         CLESLog me;
00271         
00272         if ( me.inactive() ) return;
00273 
00274         me.header();
00275         me.unmark();
00276     }
00277 
00278 #define f_cleslog_trace_enter FORTRAN_NAME_(cleslog_trace_enter, CLESLOG_TRACE_ENTER)
00279     void f_cleslog_trace_enter(char* msg) {
00280         CLESLog me;
00281 
00282         if ( me._trace == 0 ) return;
00283 
00284         for ( int i = 0 ; i < me.trace_indent ; i++ )
00285             comm_service::log() << "\t" ;
00286         
00287         (comm_service::log() << "<*> Entering: " << msg << "\n").flush();
00288         me.trace_indent ++;
00289     }
00290 
00291 #define f_cleslog_trace_exit FORTRAN_NAME_(cleslog_trace_exit, CLESLOG_TRACE_EXIT)
00292     void f_cleslog_trace_exit(char* msg) {
00293         CLESLog me;
00294 
00295         if ( me._trace == 0 ) return;
00296         
00297         me.trace_indent --;
00298         for ( int i = 0 ; i < me.trace_indent ; i++ )
00299             comm_service::log() << "\t" ;
00300         
00301         (comm_service::log() << "<*> Exiting:  " << msg << "\n").flush();
00302         
00303     }
00304 
00305 }
00306 
00307 #endif