redirection and C++ streams added
[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
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
42ClassImp(AliLog)
43
44
45AliLog* AliLog::fgInstance = NULL;
46
47Bool_t AliLog::fgDebugEnabled = kTRUE;
48
49
50//_____________________________________________________________________________
51AliLog::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//_____________________________________________________________________________
82AliLog::~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//_____________________________________________________________________________
105AliLog::AliLog(const AliLog& log) :
106 TObject(log)
107{
108// copy constructor
109
110 Fatal("AliLog", "copy constructor not implemented");
111}
112
113//_____________________________________________________________________________
114AliLog& AliLog::operator = (const AliLog& /*log*/)
115{
116// assignment operator
117
118 Fatal("operator =", "assignment operator not implemented");
119 return *this;
120}
121
122
123//_____________________________________________________________________________
eeb769e2 124void 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
268//_____________________________________________________________________________
6ab674bd 269void 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//_____________________________________________________________________________
292void AliLog::EnableDebug(Bool_t enabled)
293{
294// enable or disable debug output
295
296 fgDebugEnabled = enabled;
297}
298
299//_____________________________________________________________________________
300void AliLog::SetGlobalLogLevel(EType type)
301{
302// set the global debug level
303
304 if (!fgInstance) new AliLog;
305 fgInstance->fGlobalLogLevel = type;
306}
307
308//_____________________________________________________________________________
309Int_t AliLog::GetGlobalLogLevel()
310{
311// get the global debug level
312
313 if (!fgInstance) new AliLog;
314 return fgInstance->fGlobalLogLevel;
315}
316
317//_____________________________________________________________________________
318void 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//_____________________________________________________________________________
328Int_t AliLog::GetGlobalDebugLevel()
329{
330// get the global debug level
331
332 if (!fgInstance) new AliLog;
333 return fgInstance->fGlobalLogLevel - kDebugOffset;
334}
335
336//_____________________________________________________________________________
337void 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//_____________________________________________________________________________
354void 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//_____________________________________________________________________________
365void 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//_____________________________________________________________________________
382void 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//_____________________________________________________________________________
394void 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//_____________________________________________________________________________
406void 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//_____________________________________________________________________________
417void 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//_____________________________________________________________________________
429void 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//_____________________________________________________________________________
440void 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//_____________________________________________________________________________
458void 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//_____________________________________________________________________________
475void 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//_____________________________________________________________________________
499FILE* 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//_____________________________________________________________________________
536void 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//_____________________________________________________________________________
553void 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//_____________________________________________________________________________
566void 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//_____________________________________________________________________________
577void 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//_____________________________________________________________________________
587void 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//_____________________________________________________________________________
598void 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//_____________________________________________________________________________
608void 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//_____________________________________________________________________________
619void 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//_____________________________________________________________________________
630void 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//_____________________________________________________________________________
642void 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//_____________________________________________________________________________
654void 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//_____________________________________________________________________________
664UInt_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//_____________________________________________________________________________
677Int_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
685//_____________________________________________________________________________
eeb769e2 686void 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
721//_____________________________________________________________________________
6ab674bd 722void 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//_____________________________________________________________________________
753void 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//_____________________________________________________________________________
766Int_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//_____________________________________________________________________________
778Int_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//_____________________________________________________________________________
790Int_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//_____________________________________________________________________________
827void AliLog::RestoreStdout(Int_t original)
828{
829// restore the standard output
830
831 fflush(stdout);
832 dup2(original, fileno(stdout));
833}
834
835//_____________________________________________________________________________
836void 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//_____________________________________________________________________________
846ostream& 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//_____________________________________________________________________________
858ostream& 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