/*! \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;
}