//*-- Author : Joern Wuestenfeld
//*-- Modified : 15/04/2002 by Joern Wuestenfeld
//*-- Modified : 04/04/2002 by Joern Wuestenfeld
//*-- Modified : 28/03/2002 by Joern Wuestenfeld
//*-- Modified : 27/02/2003 by Joern Wuestenfeld
//*-- Modified : 07/05/2003 by Joern Wuestenfeld

//_HADES_CLASS_DESCRIPTION
/////////////////////////////////////////
//
//  HMessageMgr
//
//  This class manages three different outputs for all kind of messages.
//  Besides the standart output, which is the default, one can also
//  write the messages to a file, or via a socket to a remote logging process.
//
//  The usage of this class should be done via the four macros that are defined
//  in the hmessagemgr.h file.
//  DEBUG_msg(level, det, text)
//  ERROR_msg(det, text)
//  WARNING_msg(level, det, text)
//  INFO_msg(level, det, text)
//
//  The meaning of the parameters is:
//  level - level of this message, never set it to zero because this means
//          no message at all will be printed
//  det   - detector which sends this message, can be one of:
//          DET_RICH DET_START DET_MDC DET_TOF DET_TOFINO DET_SHOWER
//          DET_TRIGGER
//  text  - text to print
//
/////////////////////////////////////////////////////
using namespace std;
#include "TSystem.h"
#include "hmessagemgr.h"
#include <iostream>
#include <iomanip>
#include <cstdlib>


/// This is the default constructor inherited from TNamed.
/**
	Sets default logging to stdout and stderr.
	The default levels are: no debugging, but all of error, warning and info.
	\param name Name of the object
	\param title Title of the object
*/
HMessageMgr::HMessageMgr(const Char_t *name, const Char_t *title)
			 : TNamed(name,title)
{
  msgFile = NULL;
  errorFile = NULL;
  msgSocket = NULL;
  errorSocket = NULL;
	file = NULL;

  debugLevel = 0;
  warningLevel = LEVELMAX;
  infoLevel = LEVELMAX;
  detectorMsg = DET_ALL;
  line = 0;
  screen = kFALSE;
  file = new char[80];
}

/// This is the default destructor
/**
 */
HMessageMgr::~HMessageMgr(void)
{
  setDefault();
  delete [] file;
	file = NULL;
}

/// Resets the message logging to ist default.
/**
	 Closses all loggfiles or open sockets, and loggs further messages to
	 stdout and stderr.
	 Also the loglevels are set to the same values as in the constructor.
*/
Bool_t HMessageMgr::setDefault(void)
{
  if(msgFile)
    {
      delete msgFile;
    }
  if(errorFile)
    {
      delete errorFile;
    }
  if(msgSocket)
    {
      msgSocket->Close();
      delete msgSocket;
      msgSocket = NULL;
    }
  if(errorSocket)
    {
      errorSocket->Close();
      delete errorSocket;
      errorSocket = NULL;
    }

  debugLevel = 0;
  warningLevel = LEVELMAX;
  infoLevel = LEVELMAX;
  detectorMsg = DET_ALL;
  screen = kFALSE;

  return kTRUE;
}

/// Sets the logfile.
/**
	Input is the directory to where to log to.
	The filename is derived from the name of this object, that is given
	when creating it.
	Two files are created. One with extension .msg for all messages of
	type info, warning and debug.
	The other one with extension .err fo the error messages.
	\param dir Directory where to store the logfiles.
	\retval setFile Returns kTRUE if file could be opened, otherwise kFALSE.
*/
Bool_t HMessageMgr::setFile(const Char_t *dir)
{
  Char_t *fname;

  fname = (Char_t *)calloc(1,200);
  if(msgFile)
    {
      delete msgFile;
      msgFile = NULL;
    }
  if(errorFile)
    {
      delete errorFile;
      errorFile  = NULL;
    }
  if(!msgFile)
    {
      if((UInt_t)strlen(dir) > (UInt_t)(200 - fName.Length() + 5))
				{
					free(fname);
					return kFALSE;
				}
      else
				{
					sprintf(fname,"%s%s%s",dir,fName.Data(),".msg");
				}
      msgFile = new ofstream(fname,ios::out);
      if(!msgFile)
				{
					free(fname);
					return kFALSE;
				}
    }
  else
    {
      free(fname);
      return kFALSE;
    }
  if(!errorFile)
    {
      if((UInt_t )strlen(dir) > (UInt_t)(200 - fName.Length() + 5))
				{
					free(fname);
					return kFALSE;
				}
      else
				{
					sprintf(fname,"%s%s%s",dir,fName.Data(),".err");
				}
      errorFile = new ofstream(fname,ios::out);
      if(!errorFile)
				{
					free(fname);
					if(msgFile)
						{
							msgFile->close();
							msgFile = NULL;
						}
					return kFALSE;
				}
    }
  else
    {
      free(fname);
      return kFALSE;
    }

  return kTRUE;
}

/// Opens two socket connections to a logging server on the specified host.
/**
	The passed port is used for the message logging. Errors are send to
	the portaddress port + 10.
	eventually opened logfiles are closed, if the connection could be opened.
	Otherwise the current logging stays active.
	\param host Name of the host to send the logmessages to.
	\param port Port to use for communication with remote process.
	\retval setPort Returns kTRUE if remote process could be contacted, otherwise
	kFALSE is returned.
*/
Bool_t HMessageMgr::setPort(const Char_t *host, Int_t port)
{
  msgSocket = new TSocket(host,port);
  errorSocket = new TSocket(host,port+10);
  thisHost = new TString(gSystem->HostName());
  if(msgSocket->IsValid() && errorSocket->IsValid())
    {
      if(msgFile)
				{
					msgFile->close();
					msgFile = NULL;
				}
      if(errorFile)
				{
					errorFile->close();
					errorFile = NULL;
				}
      msgSocket->Send(thisHost->Data());
      errorSocket->Send(thisHost->Data());
      return kTRUE;
    }
  else
    {
      delete msgSocket;
      delete errorSocket;
      msgSocket = NULL;
      errorSocket = NULL;
      return kFALSE;
    }
}

/// Switches of the logging completly by setting the output to /dev/null.
/**
	Could probably done also by redirecting stdout and stderr to /dev/null.
	Currently opened files or sockets are closed.
	\retval switchOff Returns kTRUE on succsess, kFALSE otherwise.
*/
Bool_t HMessageMgr::switchOff(void)
{
  Char_t *fname;

  fname = (Char_t *)calloc(1,200);
  setDefault();
  if(msgFile)
    {
      delete msgFile;
      msgFile = NULL;
    }
  if(errorFile)
    {
      delete errorFile;
      errorFile  = NULL;
    }
  if(!msgFile)
    {
      sprintf(fname,"%s","/dev/null");
    }
  msgFile = new ofstream(fname,ios::out);
  if(!msgFile)
    {
      free(fname);
      return kFALSE;
    }
  else
    {
      free(fname);
      return kFALSE;
    }
  if(!errorFile)
    {
      sprintf(fname,"%s","/dev/null");
    }
  errorFile = new ofstream(fname,ios::out);
  if(!errorFile)
    {
      free(fname);
      return kFALSE;
    }
  else
    {
      free(fname);
      return kFALSE;
    }

  return kTRUE;
}

/// Sets the level of debug messages to level.
/**
	 \param level Level of debugging, max 10 min 0.
 */
void HMessageMgr::setDebugLevel(Char_t level)
{
  if(level > 10)
    debugLevel = 10;
  else
    if(level <= 0)
      debugLevel = 1;
  else
    debugLevel = level;
}

/// Sets the level of info messages to level.
/**
	 \param level Level of information, max 10 min 0.
 */
void HMessageMgr::setInfoLevel(Char_t level)
{
  if(level > 1)
    infoLevel = 10;
  else
    if(level <= 0)
      infoLevel = 1;
  else
    infoLevel = level;
}

/// Sets the level of warning messages to level.
/**
	 \param level Level of warning, max 10 min 0.
 */
void HMessageMgr::setWarningLevel(Char_t level)
{
  if(level > 10)
    warningLevel = 10;
  else
    if(level <= 0)
      warningLevel = 1;
  else
    warningLevel = level;
}

/// Selects for which detector messages should be displayed.
/**
	\param det An or'd pattern of the DET_* constants.
*/
void HMessageMgr::enableDetectorMsg(Int_t det)
{
  detectorMsg = det;
}

/// This function prints a line with character seperator.
/**
 The seperator character is repeated num times on this line.
 \param seperator character to be used as seperator
 \param num How often the character is to be repeated on the same line.
*/
void HMessageMgr::messageSeperator(const Char_t *seperator, Int_t num)
{
  Int_t i;

  msg1 = (Char_t *)calloc(1,num+2);
  for(i=0;i<num;i++)
    {
      strcat(msg1,seperator);
    }
  write(msg1);
  free(msg1);
}

/// Message handler for ROOT. Can be installed via gSystem->SetErrorHandler()
/**
	Used by all ROOT classes to do message logging.
	Gives a common message layout.
	\param level Level of logging
	\param abort Wether to abort the execution after the printing of the message
	\param location Location of the message
	\param msg Text to be printed.
*/
void HMessageMgr::hydraErrorHandler(Int_t level, Bool_t abort, const Char_t *location, const Char_t *msg)
{
  if (level < gErrorIgnoreLevel)
		return;

  if((level >= kError) | (level >= kSysError) | (level >= kFatal))
		{
			gHades->getMsg()->error(10,DET_ALL,location,msg);
		}
  else
    if(level >= kWarning)
      {
				gHades->getMsg()->warning(10,DET_ALL,location,msg);
      }
    else
      if(level >= kInfo)
				{
					gHades->getMsg()->info(10,DET_ALL,location,msg);
				}
}

/// This function should never be called directly, use the DEBUG macro instead.
/**
	This function writes a debug message to the output.
	It looks like this example:<br>
	debug  <Hades          >:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to 'print.
*/
void HMessageMgr::debug(Char_t level, Int_t det, const Char_t *className, const Char_t *text)
{
  if(level <= 0)
    level = 1;
  if((level <= debugLevel) && (detectorMsg & det))
    {
      msg1 = (Char_t*)calloc(1,strlen((Char_t *)text)+30);
      if(msg1)
				{
					if(line == 0)
						sprintf(msg1,"%7s%s%s%s%s","debug","<",className,">: ",text);
					else
						sprintf(msg1,"%7s%s%s %s%s%d%s%s","debug","<",className,file,":",line,">:",text);
					write(msg1);
					free(msg1);
				}
    }
}

/// This function should never be called directly, use the ERROR macro instead.
/**
	This function writes a error message to the output.
	It looks like this example:<br>
	error  <Hades          >:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to print.
*/
void HMessageMgr::error(Char_t level, Int_t det, const Char_t *className, const Char_t *text)
{
  if(level <= 0)
    level = 1;
  if(detectorMsg & det)
    {
      msg1 = (Char_t*)calloc(1,strlen((Char_t *)text)+30);
      if(msg1)
				{
					sprintf(msg1,"%7s%s%s%s%s","error","<",className,">: ",text);
					ewrite(msg1);
					free(msg1);
				}
    }
}

/// This function should never be called directly, use the WARNING macro instead.
/**
	This function writes a warning message to the output.
	It looks like this example:<br>
	warning<Hades          >:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to print.
*/
void HMessageMgr::warning(Char_t level, Int_t det, const Char_t *className, const Char_t *text)
{
  if(level <= 0)
    level = 1;
  if((level <= warningLevel)  && (detectorMsg & det))
    {
      msg1 = (Char_t*)calloc(1,strlen((Char_t *)text)+strlen(className)+15);
      if(msg1)
				{
					sprintf(msg1,"%7s%s%s%s%s","warning","<",className,">: ",text);
					write(msg1);
					free(msg1);
				}
    }
}

/// This function should never be called directly, use the INFO macro instead.
/**
	This function writes a info message to the output.
	It looks like this example:<br>
	info<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to print.
*/
void HMessageMgr::info(Char_t level, Int_t det, const Char_t *className, const Char_t *text)
{
  if(level <= 0)
    level = 1;
  if((level <= infoLevel)  && (detectorMsg & det))
    {
      msg1 = (Char_t*)calloc(1,strlen((Char_t *)text)+30);
      if(msg1)
				{
					sprintf(msg1,"%7s%s%s%s%s","info","<",className,">: ",text);
					write(msg1);
					free(msg1);
				}
    }
}

/// This function put out an error message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	debug<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::debug(Int_t level, Int_t det, const Char_t *className, const Char_t *text, ...)
{
  va_list ap;

  if(level <= 0)
    level = 1;
  if((level <= debugLevel)  && (detectorMsg & det))
    {
      msg1 = (Char_t *)calloc(1,200);
      msg2 = (Char_t *)calloc(1,200);
      if(line == 0)
				sprintf(msg1,"%7s%s%s%s","debug","<",className,">:");
      else
				sprintf(msg1,"%7s%s%s %s%s%d%s","debug","<",className,file,":",line,">: ");
      va_start(ap,text);
      vsprintf(msg2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      write(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an error message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	error<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::error(Int_t level, Int_t det, const Char_t *className, const Char_t *text, ...)
{
  va_list ap;

  if(level <= 0)
    level = 1;
  if(detectorMsg & det)
    {
      msg1 = (Char_t *)calloc(1,200);
      msg2 = (Char_t *)calloc(1,200);
      sprintf(msg1,"%7s%s%s%s","error","<",className,">: ");
      va_start(ap,text);
      vsprintf(msg2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      ewrite(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an warning message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	warning<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::warning(Int_t level, Int_t det, const Char_t *className, const Char_t *text, ...)
{
  va_list ap;
  UInt_t size1,size2;

  if(level <= 0)
    level = 1;
  if((level <= warningLevel)  && (detectorMsg & det))
    {
      size2 = strlen(text)+200;
      size1 = strlen(className) + size2 + 15;
      msg2 = (Char_t *)calloc(1,size2);
      msg1 = (Char_t *)calloc(1,size1);
      sprintf(msg1,"%7s%s%s%s","warning","<",className,">: ");
      va_start(ap,text);
      vsnprintf(msg2,size2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      write(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an info message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	info<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::info(Int_t level, Int_t det, const Char_t *className, const Char_t *text, ...)
{
  va_list ap;

  if(level <= 0)
    level = 1;
  if((level <= infoLevel)  && (detectorMsg & det))
    {
      msg1 = (Char_t *)calloc(1,200);
      msg2 = (Char_t *)calloc(1,200);
      sprintf(msg1,"%7s%s%s%s","info","<",className,">: ");
      va_start(ap,text);
      vsprintf(msg2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      write(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an error message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	debug<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param className Name of the class that prints this message.
	\param file Filename that prints the message.
	\param line Linenumber from where the message is printed.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::debugB(Char_t level, Int_t det, const Char_t *text, ...)
{
  va_list ap;

  if(level <= 0)
    level = 1;
  if((level <= debugLevel)  && (detectorMsg & det))
    {
      msg1 = (Char_t *)calloc(1,200);
      msg2 = (Char_t *)calloc(1,200);
      sprintf(msg1,"%7s%s%s %s%d%s","debug","<",file,":",line,">: ");
      va_start(ap,text);
      vsprintf(msg2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      write(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an error message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	error<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::errorB(Char_t level, Int_t det, const Char_t *text, ...)
{
  va_list ap;

  if(level <= 0)
    level = 1;
  if(detectorMsg & det)
    {
      msg1 = (Char_t *)calloc(1,200);
      msg2 = (Char_t *)calloc(1,200);
      sprintf(msg1,"%7s","error :");
      va_start(ap,text);
      vsprintf(msg2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      ewrite(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an warning message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	warning<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::warningB(Char_t level, Int_t det, const Char_t *text, ...)
{
  va_list ap;
  UInt_t size1,size2;

  if(level <= 0)
    level = 1;
  if((level <= warningLevel)  && (detectorMsg & det))
    {
      size2 = strlen(text)+200;
      size1 = size2 + 15;
      msg2 = (Char_t *)calloc(1,size2);
      msg1 = (Char_t *)calloc(1,size1);
      sprintf(msg1,"%7s","warning : ");
      va_start(ap,text);
      vsnprintf(msg2,size2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      write(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an info message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	info<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::infoB(Char_t level, Int_t det, const Char_t *text, ...)
{
  va_list ap;

  if(level <= 0)
    level = 1;
  if((level <= infoLevel)  && (detectorMsg & det))
    {
      msg1 = (Char_t *)calloc(1,200);
      msg2 = (Char_t *)calloc(1,200);
      sprintf(msg1,"%7s","info : ");
      va_start(ap,text);
      vsprintf(msg2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      write(msg1);
      free(msg1);
      free(msg2);
    }
}

/// This function put out an error message including some variable arguments.
/**
	The text parameter takes the standart parameters as in printf().
	The output looks like:<br>
	debug<         Hades>:No input specified<p>
	\param level Level of message logging
	\param det One of the DET_* constants that defines the detector printing this message.
	\param file Filename that prints the message.
	\param line Linenumber from where the message is printed.
	\param text Text to print.
	\param ... Variable number of arguments, that will be used to fill the text
*/
void HMessageMgr::debug(Int_t level, Int_t det, const Char_t * className, const Char_t *file, Int_t line, const Char_t *text, ...)
{
  va_list ap;

  if(level <= 0)
    level = 1;
  if((level <= debugLevel)  && (detectorMsg & det))
    {
      msg1 = (Char_t *)calloc(1,200);
      msg2 = (Char_t *)calloc(1,200);
      sprintf(msg1,"%7s%s%s %s%s%d%s","debug","<",className,file,":",line,">: ");
      va_start(ap,text);
      vsprintf(msg2,text,ap);
      va_end(ap);
      strcat(msg1,msg2);
      write(msg1);
      free(msg1);
      free(msg2);
    }
}


/// Internal function used to write to the correct output.
/**
	Used for info, warning and debug messages.
	Adds the name of the host the code is running on, if output is send via
	socket to a remote logging process.
	If screen is set to kTRUE the output is writen to stdout in addition to
	the logfile.
	\param text Text to be writen to specified target.
*/
void HMessageMgr::write(const Char_t *text)
{
  Char_t *msg;

  if(msgFile)
    {
      msgFile->write(text,strlen(text));
 			if(screen)
				cout << text << endl;
    }
  else
    {
      if(msgSocket)
				{
					msg =(Char_t *)calloc(1,strlen(text) + 20);
					sprintf(msg,"<%10s>%s",thisHost->Data(),text);
					msgSocket->Send(msg);
					free(msg);
				}
      else
				{
					cout << text << endl;
				}
    }
}

/// Internal function used to write to the correct output.
/**
	Used for error messages.
	Adds the name of the host the code is running on, if output is send via
	socket to a remote logging process.
	If screen is set to kTRUE the output is writen to stdout in addition to
 the logfile.
	\param text Text to be writen to specified target.
*/
void HMessageMgr::ewrite(const Char_t *text)
{
  Char_t *msg;

  if(errorFile)
    {
      errorFile->write(text,strlen(text));
 			if(screen)
				cout << text << endl;
    }
  else
    {
      if(errorSocket)
				{
					msg =(Char_t *)calloc(1,strlen(text) + 20);
					sprintf(msg,"<%10s>%s",thisHost->Data(),text);
					errorSocket->Send(msg);
					free(msg);
				}
      else
				{
					cerr << text << endl;
				}
    }
}

/// Sets the filename for the debug messages.
/**
	The filenames are printed when the debug level is set.
	\param name Name of the file that wants to print a message soon.
*/
void HMessageMgr::setF(const Char_t *name)
{
  if(name && (strlen(name) != 0))
    strncpy(file, name,79);
  else strcpy(file, "");
}

/// Sets the linenumber for the debug message.
/**
	The linenumber is printed when the debug level is set.
	\param num Linenumber of message.
*/
void HMessageMgr::setL(Int_t num)
{
  line = num;
}

ClassImp(HMessageMgr)

Last change: Sat May 22 13:04:32 2010
Last generated: 2010-05-22 13:04

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.