/*! \file log.cpp This is the clas Log implementation. \author Jon A. Lambert \date 05/02/2003 \version 0.30 \warning I'm not sure if all STL stream implementations are indeed threadsafe, therefore it would be prudent to set up separate Logs for each threaded subsystem. */ #include "sysconfig.h" #include "log.h" #include "guard.h" /*! Constructor for Log. \param r_fname A string that names the file to open. An empty string causes cout to be used for logging. \todo Log is opened by default in append mode. A possible feature is to implement a overwrite/append toggle and/or automated log archival. */ Log::Log(string& r_fname) { InitializeCriticalSection(&mMutex); mFileName = r_fname; if (mFileName != "") { // We want to use a file mpFile = new ofstream(mFileName.c_str(),ios_base::out|ios_base::app); } else { // No file - logging will be done to cout (console) mpFile = NULL; } mActive = true; } /*! Constructor for Log. \param fname A pointer to a char array that names the file to open. An empty string causes cout to be used for logging. \todo Log is opened by default in append mode. A possible feature is to implement a overwrite/append toggle and/or automated log archival. */ Log::Log(const char * fname) { InitializeCriticalSection(&mMutex); mFileName = fname; if (mFileName != "") { // We want to use a file mpFile = new ofstream(mFileName.c_str(),ios_base::out|ios_base::app); } else { // No file - logging will be done to cout (console) mpFile = NULL; } mActive = true; } /*! Log destructor. */ Log::~Log() { if (mpFile) { // Nothing to be done for cout logs mpFile->close(); delete mpFile; } DeleteCriticalSection(&mMutex); } /*! SetTime refreshes the log timestamp with the current time. \todo Could be enhanced by allowing the timestamp format to be specfified in the constructor or via a setter. */ void Log::SetTime() { time_t tm_secs = time(&tm_secs); struct tm *tm_time = localtime(&tm_secs); strftime(mTimeStamp, 40, "[%Y-%m-%d %H:%M:%S] ", tm_time); } /*! Write a string message to the log. \param r_msg A string containing the message to be written. */ void Log::Write(const string& r_msg) { Guard g(mMutex); if(mActive) { SetTime(); if (mpFile) *mpFile << mTimeStamp << r_msg << endl; else cout << mTimeStamp << r_msg << endl; } } /*! Write a formatted message to the log. \param fmt A character array containing format specifiers of the message to be written. \param ... Zero or more parameters depending on to the number of format specifiers used in fmt. \warning Like printf, using the wrong number or types of format specifiers can and will be fatal. \bug Log messages that exceed 1024 characters after formatting will crash. */ void Log::Write(const char *fmt, ...) { Guard g(mMutex); if(mActive) { char buf[1024]; va_list args; va_start (args, fmt); vsprintf (buf, fmt, args); va_end (args); SetTime(); if (mpFile) *mpFile << mTimeStamp << buf << endl; else cout << mTimeStamp << buf << endl; } } /*! SetActive turns logging on or off. \param b true sets logging on, false sets logging off. */ void Log::SetActive(bool b) { Guard g(mMutex); mActive = b; } /*! IsActive queries the whether logging is on or off. \return true if logging is on active, false if logging off. */ bool Log::IsActive() { Guard g(mMutex); return mActive; }