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