]>
Commit | Line | Data |
---|---|---|
6ab674bd | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
7 | * Permission to use, copy, modify and distribute this software and its * | |
8 | * documentation strictly for non-commercial purposes is hereby granted * | |
9 | * without fee, provided that the above copyright notice appears in all * | |
10 | * copies and that both the copyright notice and this permission notice * | |
11 | * appear in the supporting documentation. The authors make no claims * | |
12 | * about the suitability of this software for any purpose. It is * | |
13 | * provided "as is" without express or implied warranty. * | |
14 | **************************************************************************/ | |
15 | ||
16 | /* $Id$ */ | |
17 | ||
18 | /////////////////////////////////////////////////////////////////////////////// | |
19 | // // | |
20 | // class for logging debug, info and error messages // | |
21 | // // | |
22 | // The AliLog class is a singleton class. It allows to steer the output // | |
23 | // level and output streams for different types of messages via static // | |
24 | // methods. // | |
25 | // // | |
26 | // It also handles the messages produces by the preprocessor macros defined // | |
27 | // in the header file: AliDebug, AliInfo, AliWarning, AliError, AliFatal. // | |
28 | // // | |
29 | // More details about the message logging can be found on the ALICE Offline // | |
30 | // web page. // | |
31 | // // | |
32 | /////////////////////////////////////////////////////////////////////////////// | |
33 | ||
eeb769e2 | 34 | #include <Riostream.h> |
6ab674bd | 35 | #include <TError.h> |
36 | #include <TNamed.h> | |
37 | #include <TSystem.h> | |
eeb769e2 | 38 | #include <TEnv.h> |
6ab674bd | 39 | |
40 | #include "AliLog.h" | |
41 | ||
42 | ClassImp(AliLog) | |
43 | ||
44 | ||
45 | AliLog* AliLog::fgInstance = NULL; | |
46 | ||
47 | Bool_t AliLog::fgDebugEnabled = kTRUE; | |
48 | ||
49 | ||
50 | //_____________________________________________________________________________ | |
51 | AliLog::AliLog() : | |
52 | TObject(), | |
53 | fGlobalLogLevel(kInfo), | |
54 | fModuleDebugLevels(), | |
55 | fClassDebugLevels() | |
56 | { | |
57 | // default constructor: set default values | |
58 | ||
59 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
60 | fOutputTypes[iType] = 0; | |
61 | fFileNames[iType] = ""; | |
62 | fOutputFiles[iType] = NULL; | |
eeb769e2 | 63 | fOutputStreams[iType] = NULL; |
6ab674bd | 64 | |
65 | fPrintType[iType] = kTRUE; | |
66 | fPrintModule[iType] = kFALSE; | |
67 | fPrintScope[iType] = kTRUE; | |
68 | fPrintLocation[iType] = (iType == kDebug); | |
69 | } | |
70 | ||
71 | SetHandleRootMessages(kTRUE); | |
72 | ||
73 | // replace the previous instance by this one | |
74 | if (fgInstance) delete fgInstance; | |
75 | fgInstance = this; | |
eeb769e2 | 76 | |
77 | // read the .rootrc settings | |
78 | ReadEnvSettings(); | |
6ab674bd | 79 | } |
80 | ||
81 | //_____________________________________________________________________________ | |
82 | AliLog::~AliLog() | |
83 | { | |
84 | // destructor: clean up and reset instance pointer | |
85 | ||
86 | for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++) { | |
87 | if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete(); | |
88 | } | |
89 | fClassDebugLevels.Delete(); | |
90 | for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++) { | |
91 | if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete(); | |
92 | } | |
93 | fClassDebugLevels.Delete(); | |
94 | ||
95 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
96 | CloseFile(iType); | |
97 | } | |
98 | fflush(stderr); | |
99 | fflush(stdout); | |
100 | ||
101 | fgInstance = NULL; | |
102 | } | |
103 | ||
104 | //_____________________________________________________________________________ | |
105 | AliLog::AliLog(const AliLog& log) : | |
106 | TObject(log) | |
107 | { | |
108 | // copy constructor | |
109 | ||
110 | Fatal("AliLog", "copy constructor not implemented"); | |
111 | } | |
112 | ||
113 | //_____________________________________________________________________________ | |
114 | AliLog& AliLog::operator = (const AliLog& /*log*/) | |
115 | { | |
116 | // assignment operator | |
117 | ||
118 | Fatal("operator =", "assignment operator not implemented"); | |
119 | return *this; | |
120 | } | |
121 | ||
122 | ||
eeb769e2 | 123 | //_____________________________________________________________________________ |
124 | void AliLog::ReadEnvSettings() | |
125 | { | |
126 | // load settings from the root configuration file (.rootrc) | |
127 | // and from environment variables | |
128 | ||
129 | static const char* typeNames[kMaxType] = | |
130 | {"kFatal", "kError", "kWarning", "kInfo", "kDebug"}; | |
131 | ||
132 | // debug en- or disabling | |
133 | if (gSystem->Getenv("LOG_NO_DEBUG")) { | |
134 | fgDebugEnabled = kFALSE; | |
135 | } else if (gEnv->Defined("AliRoot.AliLog.EnableDebug")) { | |
136 | fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", | |
137 | fgDebugEnabled); | |
138 | AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis"))); | |
139 | } | |
140 | ||
141 | // global log level | |
142 | if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel")) { | |
143 | const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", ""); | |
144 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
145 | if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType; | |
146 | } | |
147 | AliDebug(3, Form("global log level set to %d", fGlobalLogLevel)); | |
148 | } | |
149 | ||
150 | // global debug level | |
151 | if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel")) { | |
152 | Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel", | |
153 | Int_t(fGlobalLogLevel - kDebugOffset)); | |
154 | if (level < -kDebugOffset) level = kDebugOffset; | |
155 | fGlobalLogLevel = kDebugOffset + level; | |
156 | AliDebug(3, Form("global debug level set to %d", | |
157 | fGlobalLogLevel - kDebugOffset)); | |
158 | } | |
159 | ||
160 | // module debug level | |
161 | if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel")) { | |
162 | TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", ""); | |
163 | char* p = const_cast<char*>(levels.Data()); | |
164 | while (const char* module = strtok(p, " ")) { | |
165 | p = NULL; | |
166 | char* pos = index(module, ':'); | |
167 | if (!pos) continue; | |
168 | *(pos++) = '\0'; | |
169 | Int_t level = atoi(pos); | |
170 | SetModuleDebugLevel(module, level); | |
171 | AliDebug(3, Form("debug level for module %s set to %d", module, level)); | |
172 | } | |
173 | } | |
174 | ||
175 | // class debug level | |
176 | if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel")) { | |
177 | TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", ""); | |
178 | char* p = const_cast<char*>(levels.Data()); | |
179 | while (const char* className = strtok(p, " ")) { | |
180 | p = NULL; | |
181 | char* pos = index(className, ':'); | |
182 | if (!pos) continue; | |
183 | *(pos++) = '\0'; | |
184 | Int_t level = atoi(pos); | |
185 | SetClassDebugLevel(className, level); | |
186 | AliDebug(3, Form("debug level for class %s set to %d", | |
187 | className, level)); | |
188 | } | |
189 | } | |
190 | ||
191 | // general output stream | |
192 | if (gEnv->Defined("AliRoot.AliLog.Output")) { | |
193 | TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard"); | |
194 | if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) { | |
195 | SetStandardOutput(); | |
196 | AliDebug(3, "output stream set to standard output for all types"); | |
197 | } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) { | |
198 | SetErrorOutput(); | |
199 | AliDebug(3, "output stream set to error output for all types"); | |
200 | } else if (!stream.IsNull()) { | |
201 | SetFileOutput(stream); | |
202 | AliDebug(3, Form("output stream set to file %s for all types", | |
203 | stream.Data())); | |
204 | } | |
205 | } | |
206 | ||
207 | // individual output streams | |
208 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
209 | TString name("AliRoot.AliLog.Output."); | |
210 | name += &typeNames[iType][1]; | |
211 | if (gEnv->Defined(name)) { | |
212 | TString stream = gEnv->GetValue(name, "Standard"); | |
213 | if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) { | |
214 | SetStandardOutput(EType(iType)); | |
215 | AliDebug(3, Form("output stream set to standard output for type %s", | |
216 | typeNames[iType])); | |
217 | } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) { | |
218 | SetErrorOutput(EType(iType)); | |
219 | AliDebug(3, Form("output stream set to error output for type %s", | |
220 | typeNames[iType])); | |
221 | } else if (!stream.IsNull()) { | |
222 | SetFileOutput(EType(iType), stream); | |
223 | AliDebug(3, Form("output stream set to file %s for type %s", | |
224 | stream.Data(), typeNames[iType])); | |
225 | } | |
226 | } | |
227 | } | |
228 | ||
229 | // handling of root error messages | |
230 | if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages")) { | |
231 | Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE); | |
232 | SetHandleRootMessages(on); | |
233 | AliDebug(3, Form("handling of root messages %sabled", | |
234 | ((on) ? "en" : "dis"))); | |
235 | } | |
236 | ||
237 | // printout settings | |
238 | static const char* settingNames[4] = | |
239 | {"Type", "Module", "Scope", "Location"}; | |
240 | Bool_t* settings[] = | |
241 | {fPrintType, fPrintModule, fPrintScope, fPrintLocation}; | |
242 | for (Int_t iSetting = 0; iSetting < 4; iSetting++) { | |
243 | TString name("AliRoot.AliLog.Print"); | |
244 | name += settingNames[iSetting]; | |
245 | if (gEnv->Defined(name)) { | |
246 | Bool_t on = gEnv->GetValue(name, settings[iSetting][0]); | |
247 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
248 | settings[iSetting][iType] = on; | |
249 | } | |
250 | AliDebug(3, Form("printing of %s %sabled for all types", | |
251 | settingNames[iSetting], ((on) ? "en" : "dis"))); | |
252 | } | |
253 | ||
254 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
255 | TString nameType = name + "." + &typeNames[iType][1]; | |
256 | if (gEnv->Defined(nameType)) { | |
257 | Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]); | |
258 | settings[iSetting][iType] = on; | |
259 | AliDebug(3, Form("printing of %s %sabled for type %s", | |
260 | settingNames[iSetting], ((on) ? "en" : "dis"), | |
261 | typeNames[iType])); | |
262 | } | |
263 | } | |
264 | } | |
265 | } | |
266 | ||
267 | ||
6ab674bd | 268 | //_____________________________________________________________________________ |
269 | void AliLog::RootErrorHandler(Int_t level, Bool_t abort, | |
270 | const char* location, const char* message) | |
271 | { | |
272 | // new error handler for messages from root | |
273 | ||
274 | switch (level) { | |
275 | case ::kFatal : level = kFatal; break; | |
276 | case ::kSysError : | |
277 | DefaultErrorHandler(level, abort, location, message); | |
278 | return; | |
279 | case ::kBreak : | |
280 | DefaultErrorHandler(level, abort, location, message); | |
281 | return; | |
282 | case ::kError : level = kError; break; | |
283 | case ::kWarning : level = kWarning; break; | |
284 | case ::kInfo : level = kInfo; break; | |
285 | default : level = kDebug; break; | |
286 | } | |
287 | AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0); | |
288 | } | |
289 | ||
290 | ||
291 | //_____________________________________________________________________________ | |
292 | void AliLog::EnableDebug(Bool_t enabled) | |
293 | { | |
294 | // enable or disable debug output | |
295 | ||
296 | fgDebugEnabled = enabled; | |
297 | } | |
298 | ||
299 | //_____________________________________________________________________________ | |
300 | void AliLog::SetGlobalLogLevel(EType type) | |
301 | { | |
302 | // set the global debug level | |
303 | ||
304 | if (!fgInstance) new AliLog; | |
305 | fgInstance->fGlobalLogLevel = type; | |
306 | } | |
307 | ||
308 | //_____________________________________________________________________________ | |
309 | Int_t AliLog::GetGlobalLogLevel() | |
310 | { | |
311 | // get the global debug level | |
312 | ||
313 | if (!fgInstance) new AliLog; | |
314 | return fgInstance->fGlobalLogLevel; | |
315 | } | |
316 | ||
317 | //_____________________________________________________________________________ | |
318 | void AliLog::SetGlobalDebugLevel(Int_t level) | |
319 | { | |
320 | // set the global debug level | |
321 | ||
322 | if (!fgInstance) new AliLog; | |
323 | if (level < -kDebugOffset) level = -kDebugOffset; | |
324 | fgInstance->fGlobalLogLevel = kDebugOffset + level; | |
325 | } | |
326 | ||
327 | //_____________________________________________________________________________ | |
328 | Int_t AliLog::GetGlobalDebugLevel() | |
329 | { | |
330 | // get the global debug level | |
331 | ||
332 | if (!fgInstance) new AliLog; | |
333 | return fgInstance->fGlobalLogLevel - kDebugOffset; | |
334 | } | |
335 | ||
336 | //_____________________________________________________________________________ | |
337 | void AliLog::SetModuleDebugLevel(const char* module, Int_t level) | |
338 | { | |
339 | // set the debug level for the given module | |
340 | ||
341 | if (!module) return; | |
342 | if (!fgInstance) new AliLog; | |
343 | TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module); | |
344 | if (!obj) { | |
345 | obj = new TNamed(module, module); | |
346 | fgInstance->fModuleDebugLevels.Add(obj); | |
347 | } | |
348 | level += kDebugOffset; | |
349 | if (level < kFatal) level = kFatal; | |
350 | obj->SetUniqueID(level); | |
351 | } | |
352 | ||
353 | //_____________________________________________________________________________ | |
354 | void AliLog::ClearModuleDebugLevel(const char* module) | |
355 | { | |
356 | // remove the setting of the debug level for the given module | |
357 | ||
358 | if (!module) return; | |
359 | if (!fgInstance) new AliLog; | |
360 | TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module); | |
361 | if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj); | |
362 | } | |
363 | ||
364 | //_____________________________________________________________________________ | |
365 | void AliLog::SetClassDebugLevel(const char* className, Int_t level) | |
366 | { | |
367 | // set the debug level for the given class | |
368 | ||
369 | if (!className) return; | |
370 | if (!fgInstance) new AliLog; | |
371 | TObject* obj = fgInstance->fClassDebugLevels.FindObject(className); | |
372 | if (!obj) { | |
373 | obj = new TNamed(className, className); | |
374 | fgInstance->fClassDebugLevels.Add(obj); | |
375 | } | |
376 | level += kDebugOffset; | |
377 | if (level < kFatal) level = kFatal; | |
378 | obj->SetUniqueID(level); | |
379 | } | |
380 | ||
381 | //_____________________________________________________________________________ | |
382 | void AliLog::ClearClassDebugLevel(const char* className) | |
383 | { | |
384 | // remove the setting of the debug level for the given class | |
385 | ||
386 | if (!className) return; | |
387 | if (!fgInstance) new AliLog; | |
388 | TObject* obj = fgInstance->fClassDebugLevels.FindObject(className); | |
389 | if (obj) delete fgInstance->fClassDebugLevels.Remove(obj); | |
390 | } | |
391 | ||
392 | ||
393 | //_____________________________________________________________________________ | |
394 | void AliLog::SetStandardOutput() | |
395 | { | |
396 | // write all log messages to the standard output (stdout) | |
397 | ||
398 | if (!fgInstance) new AliLog; | |
399 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
400 | fgInstance->CloseFile(iType); | |
401 | fgInstance->fOutputTypes[iType] = 0; | |
402 | } | |
403 | } | |
404 | ||
405 | //_____________________________________________________________________________ | |
406 | void AliLog::SetStandardOutput(EType type) | |
407 | { | |
408 | // write log messages of the given type to the standard output (stdout) | |
409 | ||
410 | if ((type < kFatal) || (type >= kMaxType)) return; | |
411 | if (!fgInstance) new AliLog; | |
412 | fgInstance->CloseFile(type); | |
413 | fgInstance->fOutputTypes[type] = 0; | |
414 | } | |
415 | ||
416 | //_____________________________________________________________________________ | |
417 | void AliLog::SetErrorOutput() | |
418 | { | |
419 | // write all log messages to the error output (stderr) | |
420 | ||
421 | if (!fgInstance) new AliLog; | |
422 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
423 | fgInstance->CloseFile(iType); | |
424 | fgInstance->fOutputTypes[iType] = 1; | |
425 | } | |
426 | } | |
427 | ||
428 | //_____________________________________________________________________________ | |
429 | void AliLog::SetErrorOutput(EType type) | |
430 | { | |
431 | // write log messages of the given type to the error output (stderr) | |
432 | ||
433 | if ((type < kFatal) || (type >= kMaxType)) return; | |
434 | if (!fgInstance) new AliLog; | |
435 | fgInstance->CloseFile(type); | |
436 | fgInstance->fOutputTypes[type] = 1; | |
437 | } | |
438 | ||
439 | //_____________________________________________________________________________ | |
440 | void AliLog::SetFileOutput(const char* fileName) | |
441 | { | |
442 | // write all log messages to the given file | |
443 | ||
444 | if (!fgInstance) new AliLog; | |
445 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
051599bf | 446 | if ((fgInstance->fOutputTypes[iType] == 2) && |
6ab674bd | 447 | (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) { |
448 | fgInstance->CloseFile(iType); | |
449 | } | |
450 | fgInstance->fOutputTypes[iType] = 2; | |
451 | fgInstance->fFileNames[iType] = fileName; | |
452 | fgInstance->fOutputFiles[iType] = NULL; | |
eeb769e2 | 453 | fgInstance->fOutputStreams[iType] = NULL; |
6ab674bd | 454 | } |
455 | } | |
456 | ||
457 | //_____________________________________________________________________________ | |
458 | void AliLog::SetFileOutput(EType type, const char* fileName) | |
459 | { | |
460 | // write log messages of the given type to the given file | |
461 | ||
462 | if ((type < kFatal) || (type >= kMaxType)) return; | |
463 | if (!fgInstance) new AliLog; | |
051599bf | 464 | if ((fgInstance->fOutputTypes[type] == 2) && |
6ab674bd | 465 | (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) { |
466 | fgInstance->CloseFile(type); | |
467 | } | |
468 | fgInstance->fOutputTypes[type] = 2; | |
469 | fgInstance->fFileNames[type] = fileName; | |
470 | fgInstance->fOutputFiles[type] = NULL; | |
eeb769e2 | 471 | fgInstance->fOutputStreams[type] = NULL; |
6ab674bd | 472 | } |
473 | ||
474 | //_____________________________________________________________________________ | |
475 | void AliLog::CloseFile(Int_t type) | |
476 | { | |
477 | // close the file for the given type if needed | |
478 | ||
479 | if ((fOutputTypes[type] == 2) && fOutputFiles[type]) { | |
480 | Bool_t closeFile = kTRUE; | |
481 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
482 | if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) { | |
483 | closeFile = kFALSE; | |
484 | } | |
485 | } | |
eeb769e2 | 486 | if (closeFile) { |
487 | fclose(fOutputFiles[type]); | |
488 | fOutputStreams[type]->close(); | |
489 | delete fOutputStreams[type]; | |
490 | } | |
6ab674bd | 491 | } |
492 | fOutputFiles[type] = NULL; | |
eeb769e2 | 493 | fOutputStreams[type] = NULL; |
6ab674bd | 494 | fFileNames[type] = ""; |
495 | fOutputTypes[type] = 0; | |
496 | } | |
497 | ||
498 | //_____________________________________________________________________________ | |
499 | FILE* AliLog::GetOutputStream(Int_t type) | |
500 | { | |
501 | // get the output stream for the given type of messages | |
502 | ||
eeb769e2 | 503 | if (type > kDebug) type = kDebug; |
6ab674bd | 504 | if (fOutputTypes[type] == 0) return stdout; |
505 | else if (fOutputTypes[type] == 1) return stderr; | |
506 | else if (fOutputTypes[type] == 2) { | |
507 | if (!fOutputFiles[type]) { | |
508 | FILE* file = NULL; | |
eeb769e2 | 509 | ofstream* stream = NULL; |
6ab674bd | 510 | if (!fFileNames[type].IsNull()) { |
511 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
512 | if ((iType != type) && | |
513 | (fFileNames[iType].CompareTo(fFileNames[type]) == 0) && | |
514 | fOutputFiles[iType]) { | |
515 | file = fOutputFiles[iType]; | |
eeb769e2 | 516 | stream = fOutputStreams[iType]; |
6ab674bd | 517 | break; |
518 | } | |
519 | } | |
eeb769e2 | 520 | if (!file) { |
521 | file = fopen(fFileNames[type], "a"); | |
522 | stream = new ofstream(fFileNames[type], ios::app); | |
523 | } | |
6ab674bd | 524 | } |
525 | fOutputFiles[type] = file; | |
eeb769e2 | 526 | fOutputStreams[type] = stream; |
6ab674bd | 527 | if (!file) CloseFile(type); |
528 | } | |
529 | if (fOutputFiles[type]) return fOutputFiles[type]; | |
530 | } | |
531 | ||
532 | return stdout; | |
533 | } | |
534 | ||
535 | //_____________________________________________________________________________ | |
536 | void AliLog::Flush() | |
537 | { | |
538 | // flush the output streams | |
539 | ||
540 | if (!fgInstance) new AliLog; | |
541 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
542 | if (fgInstance->fOutputFiles[iType]) { | |
543 | fflush(fgInstance->fOutputFiles[iType]); | |
eeb769e2 | 544 | fgInstance->fOutputStreams[iType]->flush(); |
6ab674bd | 545 | } |
546 | } | |
547 | fflush(stderr); | |
548 | fflush(stdout); | |
549 | } | |
550 | ||
551 | ||
552 | //_____________________________________________________________________________ | |
553 | void AliLog::SetHandleRootMessages(Bool_t on) | |
554 | { | |
555 | // enable or disable the handling of messages form root | |
556 | ||
557 | if (on) { | |
558 | SetErrorHandler(RootErrorHandler); | |
559 | } else { | |
560 | SetErrorHandler(DefaultErrorHandler); | |
561 | } | |
562 | } | |
563 | ||
564 | ||
565 | //_____________________________________________________________________________ | |
566 | void AliLog::SetPrintType(Bool_t on) | |
567 | { | |
568 | // switch on or off the printing of the message type for all message types | |
569 | ||
570 | if (!fgInstance) new AliLog; | |
571 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
572 | fgInstance->fPrintType[iType] = on; | |
573 | } | |
574 | } | |
575 | ||
576 | //_____________________________________________________________________________ | |
577 | void AliLog::SetPrintType(EType type, Bool_t on) | |
578 | { | |
579 | // switch on or off the printing of the message type for the given message type | |
580 | ||
581 | if ((type < kFatal) || (type >= kMaxType)) return; | |
582 | if (!fgInstance) new AliLog; | |
583 | fgInstance->fPrintType[type] = on; | |
584 | } | |
585 | ||
586 | //_____________________________________________________________________________ | |
587 | void AliLog::SetPrintModule(Bool_t on) | |
588 | { | |
589 | // switch on or off the printing of the module for all message types | |
590 | ||
591 | if (!fgInstance) new AliLog; | |
592 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
593 | fgInstance->fPrintModule[iType] = on; | |
594 | } | |
595 | } | |
596 | ||
597 | //_____________________________________________________________________________ | |
598 | void AliLog::SetPrintModule(EType type, Bool_t on) | |
599 | { | |
600 | // switch on or off the printing of the module for the given message type | |
601 | ||
602 | if ((type < kFatal) || (type >= kMaxType)) return; | |
603 | if (!fgInstance) new AliLog; | |
604 | fgInstance->fPrintModule[type] = on; | |
605 | } | |
606 | ||
607 | //_____________________________________________________________________________ | |
608 | void AliLog::SetPrintScope(Bool_t on) | |
609 | { | |
610 | // switch on or off the printing of the scope/class name for all message types | |
611 | ||
612 | if (!fgInstance) new AliLog; | |
613 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
614 | fgInstance->fPrintScope[iType] = on; | |
615 | } | |
616 | } | |
617 | ||
618 | //_____________________________________________________________________________ | |
619 | void AliLog::SetPrintScope(EType type, Bool_t on) | |
620 | { | |
621 | // switch on or off the printing of the scope/class name | |
622 | // for the given message type | |
623 | ||
624 | if ((type < kFatal) || (type >= kMaxType)) return; | |
625 | if (!fgInstance) new AliLog; | |
626 | fgInstance->fPrintScope[type] = on; | |
627 | } | |
628 | ||
629 | //_____________________________________________________________________________ | |
630 | void AliLog::SetPrintLocation(Bool_t on) | |
631 | { | |
632 | // switch on or off the printing of the file name and line number | |
633 | // for all message types | |
634 | ||
635 | if (!fgInstance) new AliLog; | |
636 | for (Int_t iType = kFatal; iType < kMaxType; iType++) { | |
637 | fgInstance->fPrintLocation[iType] = on; | |
638 | } | |
639 | } | |
640 | ||
641 | //_____________________________________________________________________________ | |
642 | void AliLog::SetPrintLocation(EType type, Bool_t on) | |
643 | { | |
644 | // switch on or off the printing of the file name and line number | |
645 | // for the given message type | |
646 | ||
647 | if ((type < kFatal) || (type >= kMaxType)) return; | |
648 | if (!fgInstance) new AliLog; | |
649 | fgInstance->fPrintLocation[type] = on; | |
650 | } | |
651 | ||
652 | ||
653 | //_____________________________________________________________________________ | |
654 | void AliLog::Write(const char* name, Int_t option) | |
655 | { | |
656 | // write the log object with the given name and option to the current file | |
657 | ||
658 | if (!fgInstance) new AliLog; | |
659 | fgInstance->TObject::Write(name, option); | |
660 | } | |
661 | ||
662 | ||
663 | //_____________________________________________________________________________ | |
664 | UInt_t AliLog::GetLogLevel(const char* module, const char* className) const | |
665 | { | |
666 | // get the logging level for the given module and class | |
667 | ||
668 | if (!fgInstance) new AliLog; | |
669 | TObject* obj = fgInstance->fClassDebugLevels.FindObject(className); | |
670 | if (obj) return obj->GetUniqueID(); | |
671 | obj = fgInstance->fModuleDebugLevels.FindObject(module); | |
672 | if (obj) return obj->GetUniqueID(); | |
673 | return fgInstance->fGlobalLogLevel; | |
674 | } | |
675 | ||
676 | //_____________________________________________________________________________ | |
677 | Int_t AliLog::GetDebugLevel(const char* module, const char* className) | |
678 | { | |
679 | // get the debug level for the given module and class | |
680 | ||
681 | if (!fgInstance) new AliLog; | |
682 | return fgInstance->GetLogLevel(module, className) - kDebugOffset; | |
683 | } | |
684 | ||
eeb769e2 | 685 | //_____________________________________________________________________________ |
686 | void AliLog::PrintMessage(UInt_t type, const char* message, | |
687 | const char* module, const char* className, | |
688 | const char* function, const char* file, Int_t line) | |
689 | { | |
690 | // print the given message | |
691 | ||
692 | FILE* stream = GetOutputStream(type); | |
693 | static const char* typeNames[kMaxType] = | |
694 | {"Fatal", "Error", "Warning", "Info", "Debug"}; | |
695 | ||
696 | if (fPrintType[type]) { | |
697 | fprintf(stream, "%s in ", typeNames[type]); | |
698 | } | |
699 | fprintf(stream, "<"); | |
700 | if (fPrintModule[type] && module) { | |
701 | fprintf(stream, "%s/", module); | |
702 | } | |
703 | if (fPrintScope[type] && className) { | |
704 | fprintf(stream, "%s::", className); | |
705 | } | |
706 | if (message) { | |
707 | fprintf(stream, "%s>: %s", function, message); | |
708 | } else { | |
709 | fprintf(stream, "%s>", function); | |
710 | } | |
711 | if (fPrintLocation[type] && file) { | |
712 | fprintf(stream, " (%s:%.0d)", file, line); | |
713 | } | |
714 | if (message) { | |
715 | fprintf(stream, "\n"); | |
716 | } else { | |
717 | fprintf(stream, ": "); | |
718 | } | |
719 | } | |
720 | ||
6ab674bd | 721 | //_____________________________________________________________________________ |
722 | void AliLog::Message(UInt_t level, const char* message, | |
723 | const char* module, const char* className, | |
724 | const char* function, const char* file, Int_t line) | |
725 | { | |
726 | // print a log message | |
727 | ||
728 | if (!fgInstance) new AliLog; | |
729 | ||
730 | // get the message type | |
6ab674bd | 731 | UInt_t type = level; |
732 | if (type >= kMaxType) type = kMaxType - 1; | |
733 | ||
734 | // print the message if the debug level allows | |
735 | if (level <= fgInstance->GetLogLevel(module, className)) { | |
eeb769e2 | 736 | fgInstance->PrintMessage(type, message, |
737 | module, className, function, file, line); | |
6ab674bd | 738 | } |
739 | ||
740 | // abort in case of a fatal message | |
741 | if (type == kFatal) { | |
742 | delete fgInstance; | |
743 | if (gSystem) { | |
744 | gSystem->StackTrace(); | |
745 | gSystem->Abort(); | |
746 | } else { | |
747 | ::abort(); | |
748 | } | |
749 | } | |
750 | } | |
751 | ||
752 | //_____________________________________________________________________________ | |
753 | void AliLog::Debug(UInt_t level, const char* message, | |
754 | const char* module, const char* className, | |
755 | const char* function, const char* file, Int_t line) | |
756 | { | |
757 | // print a debug message | |
758 | ||
759 | if (level == 0) level = 1; | |
760 | level += kDebugOffset; | |
761 | Message(level, message, module, className, function, file, line); | |
762 | } | |
eeb769e2 | 763 | |
764 | ||
765 | //_____________________________________________________________________________ | |
766 | Int_t AliLog::RedirectStdoutTo(EType type, UInt_t level, const char* module, | |
767 | const char* className, const char* function, | |
768 | const char* file, Int_t line, Bool_t print) | |
769 | { | |
770 | // redirect the standard output to the stream of the given type | |
771 | ||
772 | if (!fgInstance) new AliLog; | |
773 | return fgInstance->RedirectTo(stdout, type, level, module, className, | |
774 | function, file, line, print); | |
775 | } | |
776 | ||
777 | //_____________________________________________________________________________ | |
778 | Int_t AliLog::RedirectStderrTo(EType type, UInt_t level, const char* module, | |
779 | const char* className, const char* function, | |
780 | const char* file, Int_t line, Bool_t print) | |
781 | { | |
782 | // redirect the standard error output to the stream of the given type | |
783 | ||
784 | if (!fgInstance) new AliLog; | |
785 | return fgInstance->RedirectTo(stderr, type, level, module, className, | |
786 | function, file, line, print); | |
787 | } | |
788 | ||
789 | //_____________________________________________________________________________ | |
790 | Int_t AliLog::RedirectTo(FILE* stream, EType type, UInt_t level, | |
791 | const char* module, const char* className, | |
792 | const char* function, const char* file, Int_t line, | |
793 | Bool_t print) | |
794 | { | |
795 | // redirect the standard (error) output stream to the stream of the given type | |
796 | ||
797 | // get the original file descriptor to be able to restore it later | |
798 | Int_t original = dup(fileno(stream)); | |
799 | fflush(stream); | |
800 | ||
801 | // flush the stream of the selected type | |
802 | FILE* newStream = GetOutputStream(type); | |
803 | fflush(newStream); | |
804 | ||
805 | // redirect stream | |
806 | if ((type == kDebug) && (level > 0)) level--; | |
807 | if (type + level > GetLogLevel(module, className)) { // /dev/null | |
808 | freopen("/dev/null", "a", stream); | |
809 | } else if (fOutputTypes[type] == 0) { // stdout | |
810 | if (stream != stdout) dup2(fileno(stdout), fileno(stream)); | |
811 | } else if (fOutputTypes[type] == 1) { // stderr | |
812 | if (stream != stderr) dup2(fileno(stderr), fileno(stream)); | |
813 | } else if (fOutputTypes[type] == 2) { // file | |
814 | freopen(fFileNames[type], "a", stream); | |
815 | } | |
816 | ||
817 | // print information | |
818 | if (print) { | |
819 | PrintMessage(type, NULL, module, className, function, file, line); | |
820 | fflush(newStream); | |
821 | } | |
822 | ||
823 | return original; | |
824 | } | |
825 | ||
826 | //_____________________________________________________________________________ | |
827 | void AliLog::RestoreStdout(Int_t original) | |
828 | { | |
829 | // restore the standard output | |
830 | ||
831 | fflush(stdout); | |
832 | dup2(original, fileno(stdout)); | |
833 | } | |
834 | ||
835 | //_____________________________________________________________________________ | |
836 | void AliLog::RestoreStderr(Int_t original) | |
837 | { | |
838 | // restore the standard error output | |
839 | ||
840 | fflush(stderr); | |
841 | dup2(original, fileno(stderr)); | |
842 | } | |
843 | ||
844 | ||
845 | //_____________________________________________________________________________ | |
846 | ostream& AliLog::Stream(EType type, UInt_t level, | |
847 | const char* module, const char* className, | |
848 | const char* function, const char* file, Int_t line) | |
849 | { | |
850 | // get the stream object for the given output type | |
851 | ||
852 | if (!fgInstance) new AliLog; | |
853 | return fgInstance->GetStream(type, level, module, className, | |
854 | function, file, line); | |
855 | } | |
856 | ||
857 | //_____________________________________________________________________________ | |
858 | ostream& AliLog::GetStream(EType type, UInt_t level, | |
859 | const char* module, const char* className, | |
860 | const char* function, const char* file, Int_t line) | |
861 | { | |
862 | // get the stream object for the given output type | |
863 | ||
864 | if ((type == kDebug) && (level > 0)) level--; | |
865 | Bool_t noOutput = (type + level > GetLogLevel(module, className)); | |
866 | ||
867 | if (!noOutput) { | |
868 | PrintMessage(type, NULL, module, className, function, file, line); | |
869 | } | |
870 | fflush(GetOutputStream(type)); | |
871 | ||
872 | static ofstream nullStream("/dev/null"); | |
873 | if (noOutput) { | |
874 | return nullStream; | |
875 | } else if (fOutputTypes[type] == 0) { | |
876 | return cout; | |
877 | } else if (fOutputTypes[type] == 1) { | |
878 | return cerr; | |
879 | } else if (fOutputTypes[type] == 2) { | |
880 | return *fOutputStreams[type]; | |
881 | } | |
882 | ||
883 | return nullStream; | |
884 | } | |
885 |