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