RooMsgService.cxx

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * Project: RooFit                                                           *
00003  * Package: RooFitCore                                                       *
00004  * @(#)root/roofitcore:$Id: RooMsgService.cxx 37516 2010-12-10 15:16:32Z wouter $
00005  * Authors:                                                                  *
00006  *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
00007  *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
00008  *                                                                           *
00009  * Copyright (c) 2000-2005, Regents of the University of California          *
00010  *                          and Stanford University. All rights reserved.    *
00011  *                                                                           *
00012  * Redistribution and use in source and binary forms,                        *
00013  * with or without modification, are permitted according to the terms        *
00014  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
00015  *****************************************************************************/
00016 
00017 //////////////////////////////////////////////////////////////////////////////
00018 //
00019 // BEGIN_HTML
00020 //
00021 // The RooMsgService class is a singleton class that organizes informational, debugging, 
00022 // warning and errors messages generated by the RooFit core code. 
00023 // <p>
00024 // Each message generated by the core
00025 // has a message level (DEBUG,INFO,PROGRESS,WARNING,ERROR or FATAL), an originating object,
00026 // and a 'topic'. Currently implemented topics are "Generation","Plotting",
00027 // "Integration", "Minimization" and "Workspace" and "ChangeTracking".
00028 // <p>
00029 // The RooMsgService class allows to filter and redirect messages into 'streams' 
00030 // according to message level, topic, (base) class of originating object, name of originating
00031 // object and based on attribute labels attached to individual objects. 
00032 // <p>
00033 // The current default configuration creates streams for all messages at WARNING level
00034 // or higher (e.g. ERROR and FATAL) and for all INFO message on topics Generation,Plotting,
00035 // Integration and Minimization and redirects them to stdout. Users can create additional streams 
00036 // for logging of e.g. DEBUG messages on particular topics or objects and or redirect streams to
00037 // C++ streams or files.
00038 // <p>
00039 // The singleton instance is accessible through RooMsgService::instance() ;
00040 //
00041 // END_HTML
00042 //
00043 
00044 #define INST_MSG_SERVICE
00045 
00046 #include <sys/types.h>
00047 
00048 #include "RooFit.h"
00049 #include "RooAbsArg.h"
00050 #include "TClass.h"
00051 #include "TROOT.h"
00052 
00053 #include "RooMsgService.h"
00054 #include "RooCmdArg.h"
00055 #include "RooCmdConfig.h"
00056 #include "RooGlobalFunc.h"
00057 #include "RooSentinel.h"
00058 #include "RooWorkspace.h"
00059 
00060 #include "TSystem.h"
00061 #include "Riostream.h"
00062 #include <iomanip>
00063 #include <fstream>
00064 using namespace std ;
00065 using namespace RooFit ;
00066 
00067 ClassImp(RooMsgService)
00068 ;
00069 
00070 RooMsgService* RooMsgService::_instance = 0 ;
00071 Int_t RooMsgService::_debugCount = 0 ;
00072 
00073 
00074 //_____________________________________________________________________________
00075 void RooMsgService::cleanup() 
00076 {
00077   // Cleanup function called by atexit() handler installed by RooSentinel
00078   // to delete all global object upon program termination
00079   if (_instance) {
00080     delete _instance ;
00081     _instance = 0 ;
00082   }
00083 }
00084 
00085 
00086 
00087 //_____________________________________________________________________________
00088 RooMsgService::RooMsgService() 
00089 {
00090   // Constructor. Defines names of message levels
00091   // and mapping of topic codes to topic names
00092   // Install default message streams.
00093 
00094   _silentMode = kFALSE ;
00095   _showPid = kFALSE ;
00096   _globMinLevel = DEBUG ;
00097   _lastMsgLevel = DEBUG ;
00098 
00099   _devnull = new ofstream("/dev/null") ;
00100 
00101   _levelNames[DEBUG]="DEBUG" ;
00102   _levelNames[INFO]="INFO" ;
00103   _levelNames[PROGRESS]="PROGRESS" ;
00104   _levelNames[WARNING]="WARNING" ;
00105   _levelNames[ERROR]="ERROR" ;
00106   _levelNames[FATAL]="FATAL" ;
00107 
00108   _topicNames[Generation]="Generation" ;
00109   _topicNames[Minimization]="Minization" ;
00110   _topicNames[Plotting]="Plotting" ;
00111   _topicNames[Fitting]="Fitting" ;
00112   _topicNames[Integration]="Integration" ;
00113   _topicNames[LinkStateMgmt]="LinkStateMgmt" ;
00114   _topicNames[Eval]="Eval" ;
00115   _topicNames[Caching]="Caching" ;
00116   _topicNames[Optimization]="Optimization" ;
00117   _topicNames[ObjectHandling]="ObjectHandling" ;
00118   _topicNames[InputArguments]="InputArguments" ;
00119   _topicNames[Tracing]="Tracing" ;
00120   _topicNames[Contents]="Contents" ;
00121   _topicNames[DataHandling]="DataHandling" ;
00122   _topicNames[NumIntegration]="NumericIntegration" ;
00123 
00124   _instance = this ;
00125   gMsgService = this ;
00126 
00127   _debugWorkspace = 0 ;
00128   _debugCode = 0 ;
00129 
00130   // Old-style streams
00131   addStream(RooFit::PROGRESS) ;
00132   addStream(RooFit::INFO,Topic(RooFit::Eval|RooFit::Plotting|RooFit::Fitting|RooFit::Minimization|RooFit::Caching|RooFit::ObjectHandling|RooFit::NumIntegration|RooFit::InputArguments|RooFit::DataHandling)) ;
00133 }
00134 
00135 
00136 //_____________________________________________________________________________
00137 RooMsgService::~RooMsgService() 
00138 {
00139   // Destructor
00140 
00141   // Delete all ostreams we own ;
00142   map<string,ostream*>::iterator iter = _files.begin() ;
00143   for (; iter != _files.end() ; ++iter) {
00144     delete iter->second ;
00145   }
00146 
00147   if (_debugWorkspace) {
00148     delete _debugWorkspace ;
00149   }
00150 
00151   delete _devnull ;
00152 }
00153 
00154 
00155 
00156 //_____________________________________________________________________________
00157 Bool_t RooMsgService::anyDebug() 
00158 { 
00159   // Returns true if any debug level stream is active
00160   return instance()._debugCount>0 ; 
00161 }
00162 
00163 
00164 
00165 //_____________________________________________________________________________
00166 RooWorkspace* RooMsgService::debugWorkspace() 
00167 {
00168   if (!_debugWorkspace) {
00169     _debugWorkspace = new RooWorkspace("wdebug") ;
00170   }
00171   return _debugWorkspace ;
00172 }
00173 
00174 
00175 
00176 //_____________________________________________________________________________
00177 Int_t RooMsgService::addStream(RooFit::MsgLevel level, const RooCmdArg& arg1, const RooCmdArg& arg2, const RooCmdArg& arg3, 
00178                                                const RooCmdArg& arg4, const RooCmdArg& arg5, const RooCmdArg& arg6) 
00179 {
00180   // Add a message logging stream for message with given RooFit::MsgLevel or higher (i.e. more severe)
00181   // This method accepts the following arguments to configure the stream
00182   //
00183   // Output Style options
00184   // --------------------
00185   // Prefix(Bool_t flag=kTRUE) -- Prefix all messages in this stream with Topic/Originator information
00186   //
00187   // Filtering options
00188   // -----------------
00189   // Topic(const char*)        -- Restrict stream to messages on given topic
00190   // ObjectName(const char*)   -- Restrict stream to messages from object with given name
00191   // ClassName(const char*)    -- Restrict stream to messages from objects with given class name
00192   // BaseClassName(const char*)-- Restrict stream to messages from objects with given base class name
00193   // LabelName(const chat*)    -- Restrict stream to messages from objects setAtrribute(const char*) tag with given name
00194   //
00195   // Output redirection options
00196   // --------------------------
00197   // OutputFile(const char*)  -- Send output to file with given name. Multiple streams can write to same file.
00198   // OutputStream(ostream&)   -- Send output to given C++ stream. Multiple message streams can write to same c++ stream
00199   //
00200   // The return value is the unique ID code of the defined stream
00201 
00202 
00203   // Aggregate all arguments in a list
00204   RooLinkedList l ;
00205   l.Add((TObject*)&arg1) ;  l.Add((TObject*)&arg2) ;  
00206   l.Add((TObject*)&arg3) ;  l.Add((TObject*)&arg4) ;
00207   l.Add((TObject*)&arg5) ;  l.Add((TObject*)&arg6) ;  
00208 
00209   // Define configuration for this method
00210   RooCmdConfig pc(Form("RooMsgService::addReportingStream(%s)",GetName())) ;
00211   pc.defineInt("prefix","Prefix",0,kTRUE) ;
00212   pc.defineInt("color","Color",0,static_cast<Int_t>(kBlack)) ;
00213   pc.defineInt("topic","Topic",0,0xFFFFF) ;
00214   pc.defineString("objName","ObjectName",0,"") ;
00215   pc.defineString("className","ClassName",0,"") ;
00216   pc.defineString("baseClassName","BaseClassName",0,"") ;
00217   pc.defineString("tagName","LabelName",0,"") ;
00218   pc.defineString("outFile","OutputFile",0,"") ;
00219   pc.defineObject("outStream","OutputStream",0,0) ;
00220   pc.defineMutex("OutputFile","OutputStream") ;
00221 
00222   // Process & check varargs 
00223   pc.process(l) ;
00224   if (!pc.ok(kTRUE)) {
00225     return -1 ;
00226   }
00227 
00228   // Extract values from named arguments
00229   RooFit::MsgTopic topic =  (RooFit::MsgTopic) pc.getInt("topic") ;
00230   const char* objName =  pc.getString("objName") ;
00231   const char* className =  pc.getString("className") ;
00232   const char* baseClassName =  pc.getString("baseClassName") ;
00233   const char* tagName =  pc.getString("tagName") ;
00234   const char* outFile = pc.getString("outFile") ;
00235   Bool_t prefix = pc.getInt("prefix") ;
00236   Color_t color = static_cast<Color_t>(pc.getInt("color")) ;
00237   ostream* os = reinterpret_cast<ostream*>(pc.getObject("outStream")) ;
00238 
00239   // Create new stream object
00240   StreamConfig newStream ;
00241 
00242   // Store configuration info
00243   newStream.active = kTRUE ;
00244   newStream.minLevel = level ;
00245   newStream.topic = topic ;
00246   newStream.objectName = (objName ? objName : "" ) ;
00247   newStream.className = (className ? className : "" ) ;
00248   newStream.baseClassName = (baseClassName ? baseClassName : "" ) ;
00249   newStream.tagName = (tagName ? tagName : "" ) ;
00250   newStream.color = color ;
00251   newStream.prefix = prefix ;
00252   newStream.universal = (newStream.objectName=="" && newStream.className=="" && newStream.baseClassName=="" && newStream.tagName=="") ;
00253 
00254   // Update debug stream count 
00255   if (level==DEBUG) {
00256     _debugCount++ ;
00257   }
00258 
00259   // Configure output
00260   if (os) {
00261 
00262     // To given non-owned stream
00263     newStream.os = os ;
00264 
00265   } else if (string(outFile).size()>0) {
00266 
00267     // See if we already opened the file
00268     ostream* os2 = _files["outFile"] ;
00269 
00270     if (!os2) {
00271 
00272       // To given file name, create owned stream for it
00273       os2 = new ofstream(outFile) ;
00274 
00275       if (!*os2) {
00276         cout << "RooMsgService::addReportingStream ERROR: cannot open output log file " << outFile << " reverting stream to stdout" << endl ;
00277         delete os2 ;
00278         newStream.os = &cout ;
00279       } else {
00280         newStream.os = os2 ;
00281       }
00282 
00283     } else {
00284       _files["outFile"] = os2 ;
00285       newStream.os = os2 ;
00286     }
00287 
00288         
00289   } else {
00290 
00291     // To stdout
00292     newStream.os = &cout ;
00293 
00294   }
00295 
00296 
00297   // Add it to list of active streams ;
00298   _streams.push_back(newStream) ;
00299 
00300   // Return stream identifier
00301   return _streams.size()-1 ;
00302 }
00303 
00304 
00305 
00306 //_____________________________________________________________________________
00307 void RooMsgService::deleteStream(Int_t id) 
00308 {
00309   // Delete stream with given unique ID code
00310 
00311   vector<StreamConfig>::iterator iter = _streams.begin() ;
00312   iter += id ;
00313 
00314   // Update debug stream count 
00315   if (iter->minLevel==DEBUG) {
00316     _debugCount-- ;
00317   }
00318 
00319   _streams.erase(iter) ;
00320 }
00321 
00322 
00323 
00324 //_____________________________________________________________________________
00325 void RooMsgService::setStreamStatus(Int_t id, Bool_t flag) 
00326 {
00327   // (De)Activate stream with given unique ID
00328 
00329   if (id<0 || id>=static_cast<Int_t>(_streams.size())) {
00330     cout << "RooMsgService::setStreamStatus() ERROR: invalid stream ID " << id << endl ;
00331     return ;
00332   }
00333 
00334   // Update debug stream count 
00335   if (_streams[id].minLevel==DEBUG) {
00336     _debugCount += flag ? 1 : -1 ;
00337   }
00338 
00339   _streams[id].active = flag ;
00340 }
00341 
00342 
00343 
00344 //_____________________________________________________________________________
00345 Bool_t RooMsgService::getStreamStatus(Int_t id) const 
00346 {
00347   // Get activation status of stream with given unique ID
00348 
00349   if (id<0 || id>= static_cast<Int_t>(_streams.size())) {
00350     cout << "RooMsgService::getStreamStatus() ERROR: invalid stream ID " << id << endl ;
00351     return kFALSE ;
00352   }
00353   return _streams[id].active ;
00354 }
00355 
00356 
00357 
00358 //_____________________________________________________________________________
00359 RooMsgService& RooMsgService::instance() 
00360 {
00361   // Return reference to singleton instance 
00362 
00363   if (!_instance) {
00364     new RooMsgService() ;    
00365     RooSentinel::activate() ;
00366   }
00367   return *_instance ;
00368 }
00369 
00370 
00371 
00372 //_____________________________________________________________________________
00373 void RooMsgService::saveState() 
00374 {
00375   // Save current state of message service
00376   _streamsSaved.push(_streams) ;
00377 }
00378 
00379 
00380 
00381 //_____________________________________________________________________________
00382 void RooMsgService::restoreState() 
00383 {
00384   // Restore last saved state of message service
00385   _streams = _streamsSaved.top() ;
00386   _streamsSaved.pop() ;
00387 }
00388 
00389 
00390 
00391 //_____________________________________________________________________________
00392 Bool_t RooMsgService::isActive(const RooAbsArg* self, RooFit::MsgTopic topic, RooFit::MsgLevel level) 
00393 {
00394   // Check if logging is active for given object/topic/RooFit::MsgLevel combination
00395 
00396   return (activeStream(self,topic,level)>=0) ;
00397 }
00398 
00399 
00400 //_____________________________________________________________________________
00401 Bool_t RooMsgService::isActive(const TObject* self, RooFit::MsgTopic topic, RooFit::MsgLevel level) 
00402 {
00403   // Check if logging is active for given object/topic/RooFit::MsgLevel combination
00404 
00405   return (activeStream(self,topic,level)>=0) ;
00406 }
00407 
00408 
00409 //_____________________________________________________________________________
00410 Int_t RooMsgService::activeStream(const RooAbsArg* self, RooFit::MsgTopic topic, RooFit::MsgLevel level) 
00411 {
00412   // Find appropriate logging stream for message from given object with given topic and message level
00413 
00414   if (level<_globMinLevel) return -1 ;
00415   for (UInt_t i=0 ; i<_streams.size() ; i++) {
00416     if (_streams[i].match(level,topic,self)) {
00417       return i ;
00418     }
00419   }
00420   return -1 ;
00421 }
00422 
00423 
00424 //_____________________________________________________________________________
00425 Int_t RooMsgService::activeStream(const TObject* self, RooFit::MsgTopic topic, RooFit::MsgLevel level) 
00426 {
00427   // Find appropriate logging stream for message from given object with given topic and message level
00428 
00429   if (level<_globMinLevel) return -1 ;
00430   for (UInt_t i=0 ; i<_streams.size() ; i++) {
00431     if (_streams[i].match(level,topic,self)) {
00432       return i ;
00433     }
00434   }
00435   return -1 ;
00436 }
00437 
00438 
00439 //_____________________________________________________________________________
00440 Bool_t RooMsgService::StreamConfig::match(RooFit::MsgLevel level, RooFit::MsgTopic top, const RooAbsArg* obj) 
00441 {
00442   // Determine if message from given object at given level on given topic is logged
00443 
00444   if (!active) return kFALSE ;
00445   if (level<minLevel) return kFALSE ;
00446   if (!(topic&top)) return kFALSE ;
00447 
00448   if (universal) return kTRUE ;
00449 
00450   if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
00451   if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
00452   if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
00453   if (tagName.size()>0 && !obj->getAttribute(tagName.c_str())) return kFALSE ;
00454   
00455   return kTRUE ;
00456 }
00457 
00458 
00459 //_____________________________________________________________________________
00460 Bool_t RooMsgService::StreamConfig::match(RooFit::MsgLevel level, RooFit::MsgTopic top, const TObject* obj) 
00461 {
00462   // Determine if message from given object at given level on given topic is logged
00463 
00464   if (!active) return kFALSE ;
00465   if (level<minLevel) return kFALSE ;
00466   if (!(topic&top)) return kFALSE ;
00467 
00468   if (universal) return kTRUE ;
00469   
00470   if (objectName.size()>0 && objectName != obj->GetName()) return kFALSE ;
00471   if (className.size()>0 && className != obj->IsA()->GetName()) return kFALSE ;
00472   if (baseClassName.size()>0 && !obj->IsA()->InheritsFrom(baseClassName.c_str())) return kFALSE ;
00473   
00474   return kTRUE ;
00475 }
00476 
00477 
00478 
00479 //_____________________________________________________________________________
00480 ostream& RooMsgService::log(const RooAbsArg* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix) 
00481 {
00482   // Log error message associated with RooAbsArg object self at given level and topic. If skipPrefix
00483   // is true the standard RooMsgService prefix is not added.
00484 
00485   if (level>=ERROR) {
00486     _errorCount++ ;
00487   }
00488 
00489   // Return C++ ostream associated with given message configuration
00490   Int_t as = activeStream(self,topic,level) ;
00491 
00492   if (as==-1) {
00493     return *_devnull ;
00494   }
00495 
00496   // Flush any previous messages
00497   (*_streams[as].os).flush() ;
00498 
00499   // Insert an endl if we switch from progress to another level
00500   if (_lastMsgLevel==PROGRESS && level!=PROGRESS) {
00501     (*_streams[as].os) << endl ;
00502   }
00503   _lastMsgLevel=level ;
00504     
00505   if (_streams[as].prefix && !skipPrefix) {
00506     if (_showPid) {
00507       (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
00508     }
00509     (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic]  << " -- " ;
00510   }
00511   return (*_streams[as].os) ;
00512 }
00513 
00514 
00515 
00516 //_____________________________________________________________________________
00517 ostream& RooMsgService::log(const TObject* self, RooFit::MsgLevel level, RooFit::MsgTopic topic, Bool_t skipPrefix) 
00518 {
00519   // Log error message associated with TObject object self at given level and topic. If skipPrefix
00520   // is true the standard RooMsgService prefix is not added.
00521 
00522   if (level>=ERROR) {
00523     _errorCount++ ;
00524   }
00525 
00526   // Return C++ ostream associated with given message configuration
00527   Int_t as = activeStream(self,topic,level) ;
00528   if (as==-1) {
00529     return *_devnull ;
00530   }
00531 
00532   // Flush any previous messages
00533   (*_streams[as].os).flush() ;
00534     
00535   if (_streams[as].prefix && !skipPrefix) {
00536     if (_showPid) {
00537       (*_streams[as].os) << "pid" << gSystem->GetPid() << " " ;
00538     }
00539     (*_streams[as].os) << "[#" << as << "] " << _levelNames[level] << ":" << _topicNames[topic]  << " -- " ;
00540   }
00541   return (*_streams[as].os) ;
00542 }
00543 
00544 
00545 
00546 //_____________________________________________________________________________
00547 void RooMsgService::Print(Option_t *options) const 
00548 {
00549   // Print configuration of message service. If "v" option is given also
00550   // inactive streams are listed
00551 
00552   Bool_t activeOnly = kTRUE ;
00553   if (TString(options).Contains("V") || TString(options).Contains("v")) {
00554     activeOnly = kFALSE ;
00555   }
00556 
00557   cout << (activeOnly?"Active Message streams":"All Message streams") << endl ;
00558   for (UInt_t i=0 ; i<_streams.size() ; i++) {
00559 
00560     // Skip passive streams in active only mode
00561     if (activeOnly && !_streams[i].active) {
00562       continue ;
00563     }
00564 
00565     
00566     map<int,string>::const_iterator is = _levelNames.find(_streams[i].minLevel) ;
00567     cout << "[" << i << "] MinLevel = " << is->second ;
00568 
00569     cout << " Topic = " ;
00570     if (_streams[i].topic != 0xFFFFF) {      
00571       map<int,string>::const_iterator iter = _topicNames.begin() ;
00572       while(iter!=_topicNames.end()) {
00573         if (iter->first & _streams[i].topic) {
00574           cout << iter->second << " " ;
00575         }
00576         ++iter ;
00577       }
00578     } else {
00579       cout << " Any " ;
00580     }
00581     
00582 
00583     if (_streams[i].objectName.size()>0) {
00584       cout << " ObjectName = " << _streams[i].objectName ;
00585     }
00586     if (_streams[i].className.size()>0) {
00587       cout << " ClassName = " << _streams[i].className ;
00588     }
00589     if (_streams[i].baseClassName.size()>0) {
00590       cout << " BaseClassName = " << _streams[i].baseClassName ;
00591     }
00592     if (_streams[i].tagName.size()>0) {
00593       cout << " TagLabel = " << _streams[i].tagName ;
00594     }
00595     
00596     // Postfix status when printing all
00597     if (!activeOnly && !_streams[i].active) {
00598       cout << " (NOT ACTIVE)"  ;
00599     }
00600     
00601     cout << endl ; 
00602   }
00603   
00604 }

Generated on Tue Jul 5 15:06:52 2011 for ROOT_528-00b_version by  doxygen 1.5.1