Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

MsgService.h

Go to the documentation of this file.
00001 
00002 // $Id: MsgService.h,v 1.29 2008/08/19 19:02:59 gmieg Exp $
00003 //
00004 // MsgService
00005 //
00006 // A class to create and provide access to various named, filtered, and
00007 // formatted output streams
00008 //
00009 // messier@huhepl.harvard.edu
00011 #ifndef MSGSERVICE_H
00012 #define MSGSERVICE_H
00013 #ifndef IOSFWD
00014 #include <iosfwd>
00015 #define IOSFWD
00016 #endif
00017 #ifndef MAP
00018 #include <map>
00019 #define MAP
00020 #endif
00021 #ifndef STRING
00022 #define STRING
00023 #include <string>
00024 #endif
00025 #ifndef STDEXCEPT
00026 #define STDEXCEPT
00027 #include <stdexcept>
00028 #endif
00029 #ifndef MSG_H
00030 #include "MessageService/Msg.h"
00031 #endif
00032 #ifndef MSGSTREAM_H
00033 #include "MessageService/MsgStream.h"
00034 #endif
00035 #ifndef MSGCATSTREAM_H
00036 #include "MessageService/MsgCatStream.h"
00037 #endif
00038 
00039 using namespace std;
00040 
00041 class MSGException : public std::runtime_error
00042 {
00043  public:
00044   MSGException() : std::runtime_error("MSGException") {}
00045 };
00046 
00047 //......................................................................
00048 class MsgService 
00049 {
00050   friend std::ostream& operator<<(std::ostream& os, const MsgService& m);
00051 public:
00052   ~MsgService();
00053   static MsgService* Instance();
00054   
00055   // Is this stream active at this level?
00056   bool IsActive(const char* str_name, Msg::LogLevel_t lvl) {
00057     if (lvl < fsGlobalLogLevel ) return false; // Is ANY stream active at this level?
00058     if (MsgStream* m = this->GetStream(str_name)) return m->IsActive(lvl);
00059     return false;
00060   }
00061   
00062   static void StackTrace(const char* stream, Msg::LogLevel_t lvl, int depth = 100, int ignore = 0);
00063 
00064   static void SetGlobalLevel(); // Resets the global level.
00065 
00066   void       AddCatStream(const char* fileName, 
00067                           const char* streamName, Msg::LogLevel_t lvl);
00068   MsgStream* GetStream(const char* name) {
00069     std::string msgName(name);
00070     MsgStream* m;
00071     if ((m = fMsgStreamTable[msgName])!=0) return m;
00072     return this->CreateStream(name);
00073   }
00074   void PrintStatistics();
00075   void PrintStatistics(std::ostream& os);
00076 
00077   void SetDefaultFormat(int fmt, int level=99); // 99=all levels
00078 
00079   void SetCurrentRunSnarl( int  run, int  snarl ) { fCurrentRun = run; fCurrentSnarl = snarl; };
00080   void GetCurrentRunSnarl( int& run, int& snarl ) { run = fCurrentRun; snarl = fCurrentSnarl; };
00081 
00082   void SetkFatalAbort(int abortflag = 1) {fkFatalAbort = abortflag;}
00083   int  GetkFatalAbort() {return fkFatalAbort;}
00084 
00085 
00086   // A helper class to handle begin/end initializations of the MsgService
00087   // This ensures that the message service outlives all of its clients
00088   class Init
00089   {
00090   public:
00091     static int count;
00092     Init()  { ++count; }
00093     ~Init() { if (--count==0) { delete fInstance; fInstance=0; } }
00094   };
00095 
00096 private:
00097   // MsgService is a singleton
00098   MsgService();
00099   const char* GetTmpCatFileName(const char *streamName, int lvl);
00100   MsgStream*  CreateStream(const char* name);
00101 
00102 private:  
00103   static MsgService *fInstance; // The sole instance of the message service
00104   
00105   Msg::LogLevel_t fDefaultLogLevel;                     // The log level
00106   char            fDefaultOStream[Msg::kNLogLevel][64]; // Default output
00107   int             fDefaultFormat[Msg::kNLogLevel];      // Default format
00108   std::map<std::string,MsgStream*> fMsgStreamTable;     // Streams
00109   std::vector<MsgCatStream>        fMsgCatList; // Streams to concatenate
00110 
00111   static Msg::LogLevel_t fsGlobalLogLevel; // The lowest log level currently on.
00112   int fCurrentRun;   // Current run number
00113   int fCurrentSnarl; // Current snarl number
00114   int fkFatalAbort;  // kFatal has set flag to abort job at opportunity
00115 };
00116 
00117 #ifdef MACOSX
00118 static string __CVSID__ = "__CVSID__ undefined";
00119 
00120 class SetMsgCVSID {
00121 public:
00122   SetMsgCVSID(const char* cvsid) { __CVSID__ = cvsid; }
00123 };
00124 #endif
00125 
00126 //......................................................................
00127 
00128 // This adds to the count of message servce clients - one per #include
00129 static struct MsgService::Init __msginit;
00130 
00131 //......................................................................
00132 
00133 // Utility macros:
00134 // Macro to concatenate two symbols:
00135 #define TOKCAT(x,y) x##y
00136 
00137 // Macro to expand preprocessor variables and concatenate:
00138 #define TOKCAT2(x,y) TOKCAT(x,y)
00139 
00140 // Macro to concatenate source line with a symbol:
00141 #define LINECAT(x) TOKCAT2(x, __LINE__ )
00142 
00143 // Macros to simplify the use of the Message Service
00144 #ifdef MACOSX
00145   #define CVSID(x) static SetMsgCVSID setmsgcvsid(x)
00146   #else
00147   #if (( __GNUC__ >= 3) && !(__CINT__))
00148     // This defines the variable in such a way that it doesn't generate compiler errors if unused.
00149     #define CVSID(x) static const char* __CVSID__  __attribute__ ((__unused__)) = x
00150   #else
00151     #define CVSID(x) static const char* __CVSID__ = x
00152   #endif
00153 #endif
00154 
00155 // MSG uses negative test so that so that this "if" 
00156 // doesn't steal any trailing "else"'s
00157 #ifdef MACOSX
00158 #define MSG(s,l) \
00159 if ( !MsgService::Instance()->IsActive(s,l) ) { ; } else \
00160    ((*(MsgService::Instance())->GetStream(s))(l,__FILE__,__CVSID__.c_str(),__LINE__))
00161 #define MSGSTREAM(s,l) \
00162    ((*(MsgService::Instance())->GetStream(s))(l,__FILE__,__CVSID__.c_str(),__LINE__))
00163 #else
00164 #define MSG(s,l) \
00165 if ( !MsgService::Instance()->IsActive(s,l) ) { ; } else \
00166    ((*(MsgService::Instance())->GetStream(s))(l,__FILE__,__CVSID__,__LINE__))
00167 #define MSGSTREAM(s,l) \
00168    ((*(MsgService::Instance())->GetStream(s))(l,__FILE__,__CVSID__,__LINE__))
00169 #endif
00170 
00171 // MAXMSG can be used just like the MSG macro, but will print 
00172 // it's output only c times.  The last time it prepends 
00173 // "..Last Mesage.. " before the message.
00174 // (Cunning preprocessor magic here allows multiple use in the same source file.)
00175 // Added R1.4 by Nathaniel n.tagg1@physics.ox.ac.uk
00176 //
00177 // Note from bv: if you get compile time errors involving MSGCNT when
00178 // using MAXMSG you probably are using a one line branch/loop like:
00179 //
00180 // if (foo) MAXMSG(...) << "bar\n";
00181 //
00182 // this runs afoul of the "cunning cpp magic".  To fix it you must put
00183 // braces:
00184 //
00185 // if (foo) { MAXMSG(...) << "bar\n"; }
00186 //
00187 // This must be done in the code that uses MAXMSG, there's no way to
00188 // fix it here.
00190 #define MSG_ONLY_COUNT(s,l) \
00191 if ( !MsgService::Instance()->IsActive(s,l) ) { ; } else \
00192    ((MsgService::Instance())->GetStream(s)->LogPrint(l,__FILE__))
00193 
00194 #define MAXMSG(s,l,c)  \
00195   static int LINECAT(MSGCNT) =0; \
00196   const char* LINECAT(MSGADD) = (++LINECAT(MSGCNT)==c)?"..Last Message (counting continues).. ":""; \
00197   if(LINECAT(MSGCNT) > c || LINECAT(MSGCNT) < 0) {MSG_ONLY_COUNT(s,l);} else MSG(s,l) << LINECAT(MSGADD) 
00198 
00199 #endif // MSGSERVICE_H

Generated on Sat Nov 21 22:46:46 2009 for loon by  doxygen 1.3.9.1