bugfix
[u/mrichter/AliRoot.git] / STEER / AliLog.cxx
CommitLineData
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
34#include <TError.h>
35#include <TNamed.h>
36#include <TSystem.h>
37
38#include "AliLog.h"
39
40ClassImp(AliLog)
41
42
43AliLog* AliLog::fgInstance = NULL;
44
45Bool_t AliLog::fgDebugEnabled = kTRUE;
46
47
48//_____________________________________________________________________________
49AliLog::AliLog() :
50 TObject(),
51 fGlobalLogLevel(kInfo),
52 fModuleDebugLevels(),
53 fClassDebugLevels()
54{
55// default constructor: set default values
56
57 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
58 fOutputTypes[iType] = 0;
59 fFileNames[iType] = "";
60 fOutputFiles[iType] = NULL;
61
62 fPrintType[iType] = kTRUE;
63 fPrintModule[iType] = kFALSE;
64 fPrintScope[iType] = kTRUE;
65 fPrintLocation[iType] = (iType == kDebug);
66 }
67
68 SetHandleRootMessages(kTRUE);
69
70 // replace the previous instance by this one
71 if (fgInstance) delete fgInstance;
72 fgInstance = this;
73}
74
75//_____________________________________________________________________________
76AliLog::~AliLog()
77{
78// destructor: clean up and reset instance pointer
79
80 for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++) {
81 if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
82 }
83 fClassDebugLevels.Delete();
84 for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++) {
85 if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
86 }
87 fClassDebugLevels.Delete();
88
89 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
90 CloseFile(iType);
91 }
92 fflush(stderr);
93 fflush(stdout);
94
95 fgInstance = NULL;
96}
97
98//_____________________________________________________________________________
99AliLog::AliLog(const AliLog& log) :
100 TObject(log)
101{
102// copy constructor
103
104 Fatal("AliLog", "copy constructor not implemented");
105}
106
107//_____________________________________________________________________________
108AliLog& AliLog::operator = (const AliLog& /*log*/)
109{
110// assignment operator
111
112 Fatal("operator =", "assignment operator not implemented");
113 return *this;
114}
115
116
117//_____________________________________________________________________________
118void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
119 const char* location, const char* message)
120{
121// new error handler for messages from root
122
123 switch (level) {
124 case ::kFatal : level = kFatal; break;
125 case ::kSysError :
126 DefaultErrorHandler(level, abort, location, message);
127 return;
128 case ::kBreak :
129 DefaultErrorHandler(level, abort, location, message);
130 return;
131 case ::kError : level = kError; break;
132 case ::kWarning : level = kWarning; break;
133 case ::kInfo : level = kInfo; break;
134 default : level = kDebug; break;
135 }
136 AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
137}
138
139
140//_____________________________________________________________________________
141void AliLog::EnableDebug(Bool_t enabled)
142{
143// enable or disable debug output
144
145 fgDebugEnabled = enabled;
146}
147
148//_____________________________________________________________________________
149void AliLog::SetGlobalLogLevel(EType type)
150{
151// set the global debug level
152
153 if (!fgInstance) new AliLog;
154 fgInstance->fGlobalLogLevel = type;
155}
156
157//_____________________________________________________________________________
158Int_t AliLog::GetGlobalLogLevel()
159{
160// get the global debug level
161
162 if (!fgInstance) new AliLog;
163 return fgInstance->fGlobalLogLevel;
164}
165
166//_____________________________________________________________________________
167void AliLog::SetGlobalDebugLevel(Int_t level)
168{
169// set the global debug level
170
171 if (!fgInstance) new AliLog;
172 if (level < -kDebugOffset) level = -kDebugOffset;
173 fgInstance->fGlobalLogLevel = kDebugOffset + level;
174}
175
176//_____________________________________________________________________________
177Int_t AliLog::GetGlobalDebugLevel()
178{
179// get the global debug level
180
181 if (!fgInstance) new AliLog;
182 return fgInstance->fGlobalLogLevel - kDebugOffset;
183}
184
185//_____________________________________________________________________________
186void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
187{
188// set the debug level for the given module
189
190 if (!module) return;
191 if (!fgInstance) new AliLog;
192 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
193 if (!obj) {
194 obj = new TNamed(module, module);
195 fgInstance->fModuleDebugLevels.Add(obj);
196 }
197 level += kDebugOffset;
198 if (level < kFatal) level = kFatal;
199 obj->SetUniqueID(level);
200}
201
202//_____________________________________________________________________________
203void AliLog::ClearModuleDebugLevel(const char* module)
204{
205// remove the setting of the debug level for the given module
206
207 if (!module) return;
208 if (!fgInstance) new AliLog;
209 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
210 if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
211}
212
213//_____________________________________________________________________________
214void AliLog::SetClassDebugLevel(const char* className, Int_t level)
215{
216// set the debug level for the given class
217
218 if (!className) return;
219 if (!fgInstance) new AliLog;
220 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
221 if (!obj) {
222 obj = new TNamed(className, className);
223 fgInstance->fClassDebugLevels.Add(obj);
224 }
225 level += kDebugOffset;
226 if (level < kFatal) level = kFatal;
227 obj->SetUniqueID(level);
228}
229
230//_____________________________________________________________________________
231void AliLog::ClearClassDebugLevel(const char* className)
232{
233// remove the setting of the debug level for the given class
234
235 if (!className) return;
236 if (!fgInstance) new AliLog;
237 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
238 if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
239}
240
241
242//_____________________________________________________________________________
243void AliLog::SetStandardOutput()
244{
245// write all log messages to the standard output (stdout)
246
247 if (!fgInstance) new AliLog;
248 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
249 fgInstance->CloseFile(iType);
250 fgInstance->fOutputTypes[iType] = 0;
251 }
252}
253
254//_____________________________________________________________________________
255void AliLog::SetStandardOutput(EType type)
256{
257// write log messages of the given type to the standard output (stdout)
258
259 if ((type < kFatal) || (type >= kMaxType)) return;
260 if (!fgInstance) new AliLog;
261 fgInstance->CloseFile(type);
262 fgInstance->fOutputTypes[type] = 0;
263}
264
265//_____________________________________________________________________________
266void AliLog::SetErrorOutput()
267{
268// write all log messages to the error output (stderr)
269
270 if (!fgInstance) new AliLog;
271 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
272 fgInstance->CloseFile(iType);
273 fgInstance->fOutputTypes[iType] = 1;
274 }
275}
276
277//_____________________________________________________________________________
278void AliLog::SetErrorOutput(EType type)
279{
280// write log messages of the given type to the error output (stderr)
281
282 if ((type < kFatal) || (type >= kMaxType)) return;
283 if (!fgInstance) new AliLog;
284 fgInstance->CloseFile(type);
285 fgInstance->fOutputTypes[type] = 1;
286}
287
288//_____________________________________________________________________________
289void AliLog::SetFileOutput(const char* fileName)
290{
291// write all log messages to the given file
292
293 if (!fgInstance) new AliLog;
294 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
051599bf 295 if ((fgInstance->fOutputTypes[iType] == 2) &&
6ab674bd 296 (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
297 fgInstance->CloseFile(iType);
298 }
299 fgInstance->fOutputTypes[iType] = 2;
300 fgInstance->fFileNames[iType] = fileName;
301 fgInstance->fOutputFiles[iType] = NULL;
302 }
303}
304
305//_____________________________________________________________________________
306void AliLog::SetFileOutput(EType type, const char* fileName)
307{
308// write log messages of the given type to the given file
309
310 if ((type < kFatal) || (type >= kMaxType)) return;
311 if (!fgInstance) new AliLog;
051599bf 312 if ((fgInstance->fOutputTypes[type] == 2) &&
6ab674bd 313 (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
314 fgInstance->CloseFile(type);
315 }
316 fgInstance->fOutputTypes[type] = 2;
317 fgInstance->fFileNames[type] = fileName;
318 fgInstance->fOutputFiles[type] = NULL;
319}
320
321//_____________________________________________________________________________
322void AliLog::CloseFile(Int_t type)
323{
324// close the file for the given type if needed
325
326 if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
327 Bool_t closeFile = kTRUE;
328 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
329 if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
330 closeFile = kFALSE;
331 }
332 }
333 if (closeFile) fclose(fOutputFiles[type]);
334 }
335 fOutputFiles[type] = NULL;
336 fFileNames[type] = "";
337 fOutputTypes[type] = 0;
338}
339
340//_____________________________________________________________________________
341FILE* AliLog::GetOutputStream(Int_t type)
342{
343// get the output stream for the given type of messages
344
345 if (fOutputTypes[type] == 0) return stdout;
346 else if (fOutputTypes[type] == 1) return stderr;
347 else if (fOutputTypes[type] == 2) {
348 if (!fOutputFiles[type]) {
349 FILE* file = NULL;
350 if (!fFileNames[type].IsNull()) {
351 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
352 if ((iType != type) &&
353 (fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
354 fOutputFiles[iType]) {
355 file = fOutputFiles[iType];
356 break;
357 }
358 }
359 if (!file) file = fopen(fFileNames[type], "a");
360 }
361 fOutputFiles[type] = file;
362 if (!file) CloseFile(type);
363 }
364 if (fOutputFiles[type]) return fOutputFiles[type];
365 }
366
367 return stdout;
368}
369
370//_____________________________________________________________________________
371void AliLog::Flush()
372{
373// flush the output streams
374
375 if (!fgInstance) new AliLog;
376 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
377 if (fgInstance->fOutputFiles[iType]) {
378 fflush(fgInstance->fOutputFiles[iType]);
379 }
380 }
381 fflush(stderr);
382 fflush(stdout);
383}
384
385
386//_____________________________________________________________________________
387void AliLog::SetHandleRootMessages(Bool_t on)
388{
389// enable or disable the handling of messages form root
390
391 if (on) {
392 SetErrorHandler(RootErrorHandler);
393 } else {
394 SetErrorHandler(DefaultErrorHandler);
395 }
396}
397
398
399//_____________________________________________________________________________
400void AliLog::SetPrintType(Bool_t on)
401{
402// switch on or off the printing of the message type for all message types
403
404 if (!fgInstance) new AliLog;
405 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
406 fgInstance->fPrintType[iType] = on;
407 }
408}
409
410//_____________________________________________________________________________
411void AliLog::SetPrintType(EType type, Bool_t on)
412{
413// switch on or off the printing of the message type for the given message type
414
415 if ((type < kFatal) || (type >= kMaxType)) return;
416 if (!fgInstance) new AliLog;
417 fgInstance->fPrintType[type] = on;
418}
419
420//_____________________________________________________________________________
421void AliLog::SetPrintModule(Bool_t on)
422{
423// switch on or off the printing of the module for all message types
424
425 if (!fgInstance) new AliLog;
426 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
427 fgInstance->fPrintModule[iType] = on;
428 }
429}
430
431//_____________________________________________________________________________
432void AliLog::SetPrintModule(EType type, Bool_t on)
433{
434// switch on or off the printing of the module for the given message type
435
436 if ((type < kFatal) || (type >= kMaxType)) return;
437 if (!fgInstance) new AliLog;
438 fgInstance->fPrintModule[type] = on;
439}
440
441//_____________________________________________________________________________
442void AliLog::SetPrintScope(Bool_t on)
443{
444// switch on or off the printing of the scope/class name for all message types
445
446 if (!fgInstance) new AliLog;
447 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
448 fgInstance->fPrintScope[iType] = on;
449 }
450}
451
452//_____________________________________________________________________________
453void AliLog::SetPrintScope(EType type, Bool_t on)
454{
455// switch on or off the printing of the scope/class name
456// for the given message type
457
458 if ((type < kFatal) || (type >= kMaxType)) return;
459 if (!fgInstance) new AliLog;
460 fgInstance->fPrintScope[type] = on;
461}
462
463//_____________________________________________________________________________
464void AliLog::SetPrintLocation(Bool_t on)
465{
466// switch on or off the printing of the file name and line number
467// for all message types
468
469 if (!fgInstance) new AliLog;
470 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
471 fgInstance->fPrintLocation[iType] = on;
472 }
473}
474
475//_____________________________________________________________________________
476void AliLog::SetPrintLocation(EType type, Bool_t on)
477{
478// switch on or off the printing of the file name and line number
479// for the given message type
480
481 if ((type < kFatal) || (type >= kMaxType)) return;
482 if (!fgInstance) new AliLog;
483 fgInstance->fPrintLocation[type] = on;
484}
485
486
487//_____________________________________________________________________________
488void AliLog::Write(const char* name, Int_t option)
489{
490// write the log object with the given name and option to the current file
491
492 if (!fgInstance) new AliLog;
493 fgInstance->TObject::Write(name, option);
494}
495
496
497//_____________________________________________________________________________
498UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
499{
500// get the logging level for the given module and class
501
502 if (!fgInstance) new AliLog;
503 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
504 if (obj) return obj->GetUniqueID();
505 obj = fgInstance->fModuleDebugLevels.FindObject(module);
506 if (obj) return obj->GetUniqueID();
507 return fgInstance->fGlobalLogLevel;
508}
509
510//_____________________________________________________________________________
511Int_t AliLog::GetDebugLevel(const char* module, const char* className)
512{
513// get the debug level for the given module and class
514
515 if (!fgInstance) new AliLog;
516 return fgInstance->GetLogLevel(module, className) - kDebugOffset;
517}
518
519//_____________________________________________________________________________
520void AliLog::Message(UInt_t level, const char* message,
521 const char* module, const char* className,
522 const char* function, const char* file, Int_t line)
523{
524// print a log message
525
526 if (!fgInstance) new AliLog;
527
528 // get the message type
529 static const char* typeNames[kMaxType] =
530 {"Fatal", "Error", "Warning", "Info", "Debug"};
531 UInt_t type = level;
532 if (type >= kMaxType) type = kMaxType - 1;
533
534 // print the message if the debug level allows
535 if (level <= fgInstance->GetLogLevel(module, className)) {
536 if (fgInstance->fPrintType[type]) {
537 fprintf(fgInstance->GetOutputStream(type), "%s in ", typeNames[type]);
538 }
539 fprintf(fgInstance->GetOutputStream(type), "<");
540 if (fgInstance->fPrintModule[type] && module) {
541 fprintf(fgInstance->GetOutputStream(type), "%s/", module);
542 }
543 if (fgInstance->fPrintScope[type] && className) {
544 fprintf(fgInstance->GetOutputStream(type), "%s::", className);
545 }
546 fprintf(fgInstance->GetOutputStream(type), "%s>: %s", function, message);
547 if (fgInstance->fPrintLocation[type] && file) {
548 fprintf(fgInstance->GetOutputStream(type), " (%s:%.0d)", file, line);
549 }
550 fprintf(fgInstance->GetOutputStream(type), "\n");
551 }
552
553 // abort in case of a fatal message
554 if (type == kFatal) {
555 delete fgInstance;
556 if (gSystem) {
557 gSystem->StackTrace();
558 gSystem->Abort();
559 } else {
560 ::abort();
561 }
562 }
563}
564
565//_____________________________________________________________________________
566void AliLog::Debug(UInt_t level, const char* message,
567 const char* module, const char* className,
568 const char* function, const char* file, Int_t line)
569{
570// print a debug message
571
572 if (level == 0) level = 1;
573 level += kDebugOffset;
574 Message(level, message, module, className, function, file, line);
575}