ROOT  6.06/09
Reference Guide
MsgLogger.cxx
Go to the documentation of this file.
1 // @(#)root/tmva $Id$
2 // Author: Attila Krasznahorkay, Andreas Hoecker, Joerg Stelzer, Eckhard von Toerne
3 
4 /**********************************************************************************
5  * Project: TMVA - a Root-integrated toolkit for multivariate data analysis *
6  * Package: TMVA *
7  * Class : MsgLogger *
8  * Web : http://tmva.sourceforge.net *
9  * *
10  * Description: *
11  * Implementation (see header for description) *
12  * *
13  * Author: *
14  * Attila Krasznahorkay <Attila.Krasznahorkay@cern.ch> - CERN, Switzerland *
15  * Andreas Hoecker <Andreas.Hocker@cern.ch> - CERN, Switzerland *
16  * Joerg Stelzer <stelzer@cern.ch> - DESY, Germany *
17  * Eckhard v. Toerne <evt@uni-bonn.de> - U of Bonn, Germany *
18  * *
19  * Copyright (c) 2005-2011: *
20  * CERN, Switzerland *
21  * U. of Victoria, Canada *
22  * MPI-K Heidelberg, Germany *
23  * U. of Bonn, Germany *
24  * *
25  * Redistribution and use in source and binary forms, with or without *
26  * modification, are permitted according to the terms listed in LICENSE *
27  * (http://tmva.sourceforge.net/LICENSE) *
28  **********************************************************************************/
29 
30 // Local include(s):
31 #include "TMVA/MsgLogger.h"
32 #include "TMVA/Config.h"
33 
34 #include "Riostream.h"
35 
36 // STL include(s):
37 #include <iomanip>
38 
39 #include <cstdlib>
40 
41 #include <assert.h>
42 
43 #include <memory>
44 
45 // ROOT include(s):
46 
48 
49 // declaration of global variables
50 // this is the hard-coded maximum length of the source names
51 const UInt_t TMVA::MsgLogger::fgMaxSourceSize = 25;
52 
53 const std::string TMVA::MsgLogger::fgPrefix = "--- ";
54 const std::string TMVA::MsgLogger::fgSuffix = ": ";
55 #if __cplusplus > 199711L
56 std::atomic<Bool_t> TMVA::MsgLogger::fgInhibitOutput{kFALSE};
57 std::atomic<const std::map<TMVA::EMsgType, std::string>*> TMVA::MsgLogger::fgTypeMap{0};
58 std::atomic<const std::map<TMVA::EMsgType, std::string>*> TMVA::MsgLogger::fgColorMap{0};
59 #else
60 Bool_t TMVA::MsgLogger::fgInhibitOutput = kFALSE;
61 const std::map<TMVA::EMsgType, std::string>* TMVA::MsgLogger::fgTypeMap = 0;
62 const std::map<TMVA::EMsgType, std::string>* TMVA::MsgLogger::fgColorMap = 0;
63 #endif
64 static std::auto_ptr<const std::map<TMVA::EMsgType, std::string> > gOwnTypeMap;
65 static std::auto_ptr<const std::map<TMVA::EMsgType, std::string> > gOwnColorMap;
66 
67 
69 void TMVA::MsgLogger::EnableOutput() { fgInhibitOutput = kFALSE; }
70 ////////////////////////////////////////////////////////////////////////////////
71 /// constructor
72 
73 TMVA::MsgLogger::MsgLogger( const TObject* source, EMsgType minType )
74  : fObjSource ( source ),
75  fStrSource ( "" ),
76  fActiveType( kINFO ),
77  fMinType ( minType )
78 {
79  InitMaps();
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// constructor
84 
85 TMVA::MsgLogger::MsgLogger( const std::string& source, EMsgType minType )
86  : fObjSource ( 0 ),
87  fStrSource ( source ),
88  fActiveType( kINFO ),
89  fMinType ( minType )
90 {
91  InitMaps();
92 }
93 
94 ////////////////////////////////////////////////////////////////////////////////
95 /// constructor
96 
98  : fObjSource ( 0 ),
99  fStrSource ( "Unknown" ),
100  fActiveType( kINFO ),
101  fMinType ( minType )
102 {
103  InitMaps();
104 }
105 
106 ////////////////////////////////////////////////////////////////////////////////
107 /// copy constructor
108 
110  : std::basic_ios<MsgLogger::char_type, MsgLogger::traits_type>(),
111  std::ostringstream(),
112  TObject(),
113  fObjSource(0)
114 {
115  InitMaps();
116  *this = parent;
117 }
118 
119 ////////////////////////////////////////////////////////////////////////////////
120 /// destructor
121 
123 {
124 }
125 
126 ////////////////////////////////////////////////////////////////////////////////
127 /// assingment operator
128 
130 {
131  if (&parent != this) {
132  fObjSource = parent.fObjSource;
133  fStrSource = parent.fStrSource;
134  fActiveType = parent.fActiveType;
135  fMinType = parent.fMinType;
136  }
137 
138  return *this;
139 }
140 
141 ////////////////////////////////////////////////////////////////////////////////
142 /// make sure the source name is no longer than fgMaxSourceSize:
143 
145 {
146  std::string source_name;
147  if (fObjSource) source_name = fObjSource->GetName();
148  else source_name = fStrSource;
149 
150  if (source_name.size() > fgMaxSourceSize) {
151  source_name = source_name.substr( 0, fgMaxSourceSize - 3 );
152  source_name += "...";
153  }
154 
155  return source_name;
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// the full logger prefix
160 
162 {
163  std::string source_name = GetFormattedSource();
164  if (source_name.size() < fgMaxSourceSize)
165  for (std::string::size_type i=source_name.size(); i<fgMaxSourceSize; i++) source_name.push_back( ' ' );
166 
167  return fgPrefix + source_name + fgSuffix;
168 }
169 
170 ////////////////////////////////////////////////////////////////////////////////
171 /// activates the logger writer
172 
174 {
175  // make sure the source name is no longer than fgMaxSourceSize:
176  std::string source_name = GetFormattedSource();
177 
178  std::string message = this->str();
179  std::string::size_type previous_pos = 0, current_pos = 0;
180 
181  // slice the message into lines:
182  while (kTRUE) {
183  current_pos = message.find( '\n', previous_pos );
184  std::string line = message.substr( previous_pos, current_pos - previous_pos );
185 
186  std::ostringstream message_to_send;
187  // must call the modifiers like this, otherwise g++ get's confused with the operators...
188  message_to_send.setf( std::ios::adjustfield, std::ios::left );
189  message_to_send.width( fgMaxSourceSize );
190  message_to_send << source_name << fgSuffix << line;
191  this->WriteMsg( fActiveType, message_to_send.str() );
192 
193  if (current_pos == message.npos) break;
194  previous_pos = current_pos + 1;
195  }
196 
197  // reset the stream buffer:
198  this->str( "" );
199  fActiveType = kINFO; // To always print messages that have no level specified...
200  return;
201 }
202 
203 ////////////////////////////////////////////////////////////////////////////////
204 /// putting the output string, the message type, and the color
205 /// switcher together into a single string
206 
207 void TMVA::MsgLogger::WriteMsg( EMsgType type, const std::string& line ) const
208 {
209  if ( (type < fMinType || fgInhibitOutput) && type!=kFATAL ) return; // no output
210 
211  std::map<EMsgType, std::string>::const_iterator stype;
212 
213  if ((stype = fgTypeMap.load()->find( type )) != fgTypeMap.load()->end()) {
214  if (!gConfig().IsSilent() || type==kFATAL) {
215  if (gConfig().UseColor()) {
216  // no text for INFO or VERBOSE
217  if (type == kINFO || type == kVERBOSE)
218  std::cout << fgPrefix << line << std::endl; // no color for info
219  else
220  std::cout << fgColorMap.load()->find( type )->second << fgPrefix << "<"
221  << stype->second << "> " << line << "\033[0m" << std::endl;
222  }
223  else {
224  if (type == kINFO) std::cout << fgPrefix << line << std::endl;
225  else std::cout << fgPrefix << "<" << stype->second << "> " << line << std::endl;
226  }
227  }
228  }
229 
230  // take decision to stop if fatal error
231  if (type == kFATAL) {
232  std::cout << "***> abort program execution" << std::endl;
233  std::exit(1);
234  assert(false);
235  }
236 }
237 
238 ////////////////////////////////////////////////////////////////////////////////
239 /// end line
240 
242 {
243  logger.Send();
244  return logger;
245 }
246 
247 ////////////////////////////////////////////////////////////////////////////////
248 /// Create the message type and color maps
249 
251 {
252  if(!fgTypeMap) {
253  std::map<TMVA::EMsgType, std::string>*tmp = new std::map<TMVA::EMsgType, std::string>();
254 
255  (*tmp)[kVERBOSE] = std::string("VERBOSE");
256  (*tmp)[kDEBUG] = std::string("DEBUG");
257  (*tmp)[kINFO] = std::string("INFO");
258  (*tmp)[kWARNING] = std::string("WARNING");
259  (*tmp)[kERROR] = std::string("ERROR");
260  (*tmp)[kFATAL] = std::string("FATAL");
261  (*tmp)[kSILENT] = std::string("SILENT");
262  const std::map<TMVA::EMsgType, std::string>* expected=0;
263  if(fgTypeMap.compare_exchange_strong(expected,tmp)) {
264  //Have the global own this
265  gOwnTypeMap.reset(tmp);
266  } else {
267  //Another thread beat us in creating the instance
268  delete tmp;
269  }
270  }
271 
272  if(!fgColorMap) {
273  std::map<TMVA::EMsgType, std::string>*tmp = new std::map<TMVA::EMsgType, std::string>();
274 
275  (*tmp)[kVERBOSE] = std::string("");
276  (*tmp)[kDEBUG] = std::string("\033[34m");
277  (*tmp)[kINFO] = std::string("");
278  (*tmp)[kWARNING] = std::string("\033[1;31m");
279  (*tmp)[kERROR] = std::string("\033[31m");
280  (*tmp)[kFATAL] = std::string("\033[37;41;1m");
281  (*tmp)[kSILENT] = std::string("\033[30m");
282 
283  const std::map<TMVA::EMsgType, std::string>* expected=0;
284  if(fgColorMap.compare_exchange_strong(expected,tmp)) {
285  //Have the global own this
286  gOwnColorMap.reset(tmp);
287  } else {
288  //Another thread beat us in creating the instance
289  delete tmp;
290  }
291  }
292 }
Bool_t UseColor() const
Definition: Config.h:60
Bool_t IsSilent() const
Definition: Config.h:63
TLine * line
~MsgLogger()
destructor
Definition: MsgLogger.cxx:122
void WriteMsg(EMsgType type, const std::string &line) const
putting the output string, the message type, and the color switcher together into a single string ...
Definition: MsgLogger.cxx:207
#define assert(cond)
Definition: unittest.h:542
EMsgType fMinType
Definition: MsgLogger.h:133
Config & gConfig()
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
void Send()
activates the logger writer
Definition: MsgLogger.cxx:173
STL namespace.
const TObject * fObjSource
Definition: MsgLogger.h:114
static Bool_t fgInhibitOutput
Definition: MsgLogger.h:128
static void InhibitOutput()
Definition: MsgLogger.cxx:68
const char Int_t const char TProof Int_t stype
Definition: TXSlave.cxx:46
MsgLogger(const TObject *source, EMsgType minType=kINFO)
constructor
Definition: MsgLogger.cxx:73
EMsgType fActiveType
Definition: MsgLogger.h:118
MsgLogger & operator=(const MsgLogger &parent)
assingment operator
Definition: MsgLogger.cxx:129
std::string GetPrintedSource() const
the full logger prefix
Definition: MsgLogger.cxx:161
EMsgType
Definition: Types.h:61
void InitMaps()
Create the message type and color maps.
Definition: MsgLogger.cxx:250
unsigned int UInt_t
Definition: RtypesCore.h:42
std::string fStrSource
Definition: MsgLogger.h:115
#define ClassImp(name)
Definition: Rtypes.h:279
static std::auto_ptr< const std::map< TMVA::EMsgType, std::string > > gOwnColorMap
Definition: MsgLogger.cxx:65
int type
Definition: TGX11.cxx:120
static MsgLogger & Endmsg(MsgLogger &logger)
end line
Definition: MsgLogger.cxx:241
std::string GetFormattedSource() const
make sure the source name is no longer than fgMaxSourceSize:
Definition: MsgLogger.cxx:144
Mother of all ROOT objects.
Definition: TObject.h:58
Abstract ClassifierFactory template that handles arbitrary types.
static void EnableOutput()
Definition: MsgLogger.cxx:69
string message
Definition: ROOT.py:94
const Bool_t kTRUE
Definition: Rtypes.h:91
static std::auto_ptr< const std::map< TMVA::EMsgType, std::string > > gOwnTypeMap
Definition: MsgLogger.cxx:64