//
// The RooMsgService class is a singleton class that organizes informational, debugging, 
// warning and errors messages generated by the RooFit core code. 
// <p>
// Each message generated by the core
// has a message level (DEBUG,INFO,PROGRESS,WARNING,ERROR or FATAL), an originating object,
// and a 'topic'. Currently implemented topics are "Generation","Plotting",
// "Integration", "Minimization" and "Workspace" and "ChangeTracking".
// <p>
// The RooMsgService class allows to filter and redirect messages into 'streams' 
// according to message level, topic, (base) class of originating object, name of originating
// object and based on attribute labels attached to individual objects. 
// <p>
// The current default configuration creates streams for all messages at WARNING level
// or higher (e.g. ERROR and FATAL) and for all INFO message on topics Generation,Plotting,
// Integration and Minimization and redirects them to stdout. Users can create additional streams 
// for logging of e.g. DEBUG messages on particular topics or objects and or redirect streams to
// C++ streams or files.
// <p>
// The singleton instance is accessible through RooMsgService::instance() ;
//
// END_HTML
#define INST_MSG_SERVICE
#include <sys/types.h>
#include "RooFit.h"
#include "RooAbsArg.h"
#include "TClass.h"
#include "TROOT.h"
#include "RooMsgService.h"
#include "RooCmdArg.h"
#include "RooCmdConfig.h"
#include "RooGlobalFunc.h"
#include "RooSentinel.h"
#include "TSystem.h"
#include "Riostream.h"
#include <iomanip>
#include <fstream>
using namespace std ;
using namespace RooFit ;
ClassImp(RooMsgService)
;
RooMsgService* RooMsgService::_instance = 0 ;
Int_t RooMsgService::_debugCount = 0 ;
void RooMsgService::cleanup() 
{
  
  
  if (_instance) {
    delete _instance ;
    _instance = 0 ;
  }
}
RooMsgService::RooMsgService() 
{
  
  
  
  _silentMode = kFALSE ;
  _showPid = kFALSE ;
  _globMinLevel = DEBUG ;
  _lastMsgLevel = DEBUG ;
  _devnull = new ofstream("/dev/null") ;
  _levelNames[DEBUG]="DEBUG" ;
  _levelNames[INFO]="INFO" ;
  _levelNames[PROGRESS]="PROGRESS" ;
  _levelNames[WARNING]="WARNING" ;
  _levelNames[ERROR]="ERROR" ;
  _levelNames[FATAL]="FATAL" ;
  _topicNames[Generation]="Generation" ;
  _topicNames[Minimization]="Minization" ;
  _topicNames[Plotting]="Plotting" ;
  _topicNames[Fitting]="Fitting" ;
  _topicNames[Integration]="Integration" ;
  _topicNames[LinkStateMgmt]="LinkStateMgmt" ;
  _topicNames[Eval]="Eval" ;
  _topicNames[Caching]="Caching" ;
  _topicNames[Optimization]="Optimization" ;
  _topicNames[ObjectHandling]="ObjectHandling" ;
  _topicNames[InputArguments]="InputArguments" ;
  _topicNames[Tracing]="Tracing" ;
  _topicNames[NumIntegration]="NumericIntegration" ;
  _instance = this ;
  gMsgService = this ;
  addStream(RooMsgService::PROGRESS) ;
  addStream(RooMsgService::INFO,Topic(RooMsgService::Eval|RooMsgService::Plotting|RooMsgService::Fitting|RooMsgService::Minimization|RooMsgService::Caching|RooMsgService::ObjectHandling|RooMsgService::NumIntegration|RooMsgService::InputArguments|RooMsgService::DataHandling)) ;
}
RooMsgService::~RooMsgService() 
{
  
  
  map<string,ostream*>::iterator iter = _files.begin() ;
  for (; iter != _files.end() ; ++iter) {
    delete iter->second ;
  }
  delete _devnull ;
}
Bool_t RooMsgService::anyDebug() 
{ 
  
  return instance()._debugCount>0 ; 
}
Int_t RooMsgService::addStream(MsgLevel level, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, 
    	      			               const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6) 
{
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  RooLinkedList l ;
  l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
  l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
  l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
  
  RooCmdConfig pc(Form("RooMsgService::addReportingStream(%s)",GetName())) ;
  pc.defineInt("prefix","Prefix",0,kTRUE) ;
  pc.defineInt("color","Color",0,static_cast<Int_t>(kBlack)) ;
  pc.defineInt("topic","Topic",0,0xFFFFF) ;
  pc.defineString("objName","ObjectName",0,"") ;
  pc.defineString("className","ClassName",0,"") ;
  pc.defineString("baseClassName","BaseClassName",0,"") ;
  pc.defineString("tagName","LabelName",0,"") ;
  pc.defineString("outFile","OutputFile",0,"") ;
  pc.defineObject("outStream","OutputStream",0,0) ;
  pc.defineMutex("OutputFile","OutputStream") ;
  
  pc.process(l) ;
  if (!pc.ok(kTRUE)) {
    return -1 ;
  }
  
  MsgTopic topic =  (MsgTopic) pc.getInt("topic") ;
  const char* objName =  pc.getString("objName") ;
  const char* className =  pc.getString("className") ;
  const char* baseClassName =  pc.getString("baseClassName") ;
  const char* tagName =  pc.getString("tagName") ;
  const char* outFile = pc.getString("outFile") ;
  Bool_t prefix = pc.getInt("prefix") ;
  Color_t color = static_cast<Color_t>(pc.getInt("color")) ;
  ostream* os = reinterpret_cast<ostream*>(pc.getObject("outStream")) ;
  
  StreamConfig newStream ;
  
  newStream.active = kTRUE ;
  newStream.minLevel = level ;
  newStream.topic = topic ;
  newStream.objectName = (objName ? objName : "" ) ;
  newStream.className = (className ? className : "" ) ;
  newStream.baseClassName = (baseClassName ? baseClassName : "" ) ;
  newStream.tagName = (tagName ? tagName : "" ) ;
  newStream.color = color ;
  newStream.prefix = prefix ;
  newStream.universal = (newStream.objectName=="" && newStream.className=="" && newStream.baseClassName=="" && newStream.tagName=="") ;
  
  if (level==DEBUG) {
    _debugCount++ ;
  }
  
  if (os) {
    
    newStream.os = os ;
  } else if (string(outFile).size()>0) {
    
    ostream* os2 = _files["outFile"] ;
    if (!os2) {
      
      os2 = new ofstream(outFile) ;
      if (!*os2) {
	cout << "RooMsgService::addReportingStream ERROR: cannot open output log file " << outFile << " reverting stream to stdout" << endl ;
	delete os2 ;
	newStream.os = &cout ;
      }
    }
    _files["outFile"] = os2 ;
    newStream.os = os2 ;
        
  } else {
    
    newStream.os = &cout ;
  }
  
  _streams.push_back(newStream) ;
  
  return _streams.size()-1 ;
}
void RooMsgService::deleteStream(Int_t id) 
{
  
  vector<StreamConfig>::iterator iter = _streams.begin() ;
  iter += id ;
  
  if (iter->minLevel==DEBUG) {
    _debugCount-- ;
  }
  _streams.erase(iter) ;
}
void RooMsgService::setStreamStatus(Int_t id, Bool_t flag) 
{
  
  if (id<0 || id>=static_cast<Int_t>(_streams.size())) {
    cout << "RooMsgService::setStreamStatus() ERROR: invalid stream ID " << id << endl ;
    return ;
  }
  
  if (_streams[id].minLevel==DEBUG) {
    _debugCount += flag ? 1 : -1 ;
  }
  _streams[id].active = flag ;
}
Bool_t RooMsgService::getStreamStatus(Int_t id) const 
{
  
  if (id<0 || id>= static_cast<Int_t>(_streams.size())) {
    cout << "RooMsgService::getStreamStatus() ERROR: invalid stream ID " << id << endl ;
    return kFALSE ;
  }
  return _streams[id].active ;
}
RooMsgService& RooMsgService::instance() 
{
  
  if (!_instance) {
    new RooMsgService() ;    
    RooSentinel::activate() ;
  }
  return *_instance ;
}
Bool_t RooMsgService::isActive(const RooAbsArg* self, MsgTopic topic, MsgLevel level) 
{
  
  return (activeStream(self,topic,level)>=0) ;
}
Bool_t RooMsgService::isActive(const TObject* self, MsgTopic topic, MsgLevel level) 
{
  
  return (activeStream(self,topic,level)>=0) ;
}
Int_t RooMsgService::activeStream(const RooAbsArg* self, MsgTopic topic, MsgLevel level) 
{
  
  if (level<_globMinLevel) return -1 ;
  for (UInt_t i=0 ; i<_streams.size() ; i++) {
    if (_streams[i].match(level,topic,self)) {
      return i ;
    }
  }
  return -1 ;
}
Int_t RooMsgService::activeStream(const TObject* self, MsgTopic topic, MsgLevel level) 
{
  
  if (level<_globMinLevel) return -1 ;
  for (UInt_t i=0 ; i<_streams.size() ; i++) {
    if (_streams[i].match(level,topic,self)) {
      return i ;
    }
  }
  return -1 ;
}
Bool_t RooMsgService::StreamConfig::match(MsgLevel level, MsgTopic top, const RooAbsArg* obj) 
{
  
  if (!active) return kFALSE ;
  if (level<minLevel) return kFALSE ;
  if (!(topic&top)) return kFALSE ;
  if (universal) return kTRUE ;
  if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
  if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
  if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
  if (tagName.size()>0 && !obj->getAttribute(tagName.c_str())) return kFALSE ;
  
  return kTRUE ;
}
Bool_t RooMsgService::StreamConfig::match(MsgLevel level, MsgTopic top, const TObject* obj) 
{
  
  if (!active) return kFALSE ;
  if (level<minLevel) return kFALSE ;
  if (!(topic&top)) return kFALSE ;
  if (universal) return kTRUE ;
  
  if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
  if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
  if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
  
  return kTRUE ;
}
ostream& RooMsgService::log(const RooAbsArg* self, MsgLevel level, MsgTopic topic, Bool_t skipPrefix) 
{
  
  
  if (level>=ERROR) {
    _errorCount++ ;
  }
  
  Int_t as = activeStream(self,topic,level) ;
  if (as==-1) {
    return *_devnull ;
  }
  
  (*_streams[as].os).flush() ;
  
  if (_lastMsgLevel==PROGRESS && level!=PROGRESS) {
    (*_streams[as].os) << endl ;
  }
  _lastMsgLevel=level ;
    
  if (_streams[as].prefix && !skipPrefix) {
    if (_showPid) {
      (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
    }
    (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic]  << " -- " ;
  }
  return (*_streams[as].os) ;
}
ostream& RooMsgService::log(const TObject* self, MsgLevel level, MsgTopic topic, Bool_t skipPrefix) 
{
  
  
  if (level>=ERROR) {
    _errorCount++ ;
  }
  
  Int_t as = activeStream(self,topic,level) ;
  if (as==-1) {
    return *_devnull ;
  }
  
  (*_streams[as].os).flush() ;
    
  if (_streams[as].prefix && !skipPrefix) {
    if (_showPid) {
      (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
    }
    (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic]  << " -- " ;
  }
  return (*_streams[as].os) ;
}
void RooMsgService::Print(Option_t *options) const 
{
  
  
  Bool_t activeOnly = kTRUE ;
  if (TString(options).Contains("V") || TString(options).Contains("v")) {
    activeOnly = kFALSE ;
  }
  cout << (activeOnly?"Active Message streams":"All Message streams") << endl ;
  for (UInt_t i=0 ; i<_streams.size() ; i++) {
    
    if (activeOnly && !_streams[i].active) {
      continue ;
    }
    
    map<int,string>::const_iterator is = _levelNames.find(_streams[i].minLevel) ;
    cout << "[" << i << "] MinLevel = " << is->second ;
    cout << " Topic = " ;
    if (_streams[i].topic != 0xFFFFF) {      
      map<int,string>::const_iterator iter = _topicNames.begin() ;
      while(iter!=_topicNames.end()) {
	if (iter->first & _streams[i].topic) {
	  cout << iter->second << " " ;
	}
	++iter ;
      }
    } else {
      cout << " Any " ;
    }
    
    if (_streams[i].objectName.size()>0) {
      cout << " ObjectName = " << _streams[i].objectName ;
    }
    if (_streams[i].className.size()>0) {
      cout << " ClassName = " << _streams[i].className ;
    }
    if (_streams[i].baseClassName.size()>0) {
      cout << " BaseClassName = " << _streams[i].baseClassName ;
    }
    if (_streams[i].tagName.size()>0) {
      cout << " TagLabel = " << _streams[i].tagName ;
    }
    
    
    if (!activeOnly && !_streams[i].active) {
      cout << " (NOT ACTIVE)"  ;
    }
    
    cout << endl ; 
  }
  
}
Last change: Mon Aug 25 11:36:38 2008
Last generated: 2008-08-25 11:36
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.