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