]> git.uio.no Git - u/mrichter/AliRoot.git/blob - STEER/STEERBase/AliLog.cxx
Adding static methods to get the azimuthal angle and eta range for a given vzero...
[u/mrichter/AliRoot.git] / STEER / STEERBase / 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 <cstdlib>
35 #include <strings.h>
36 #include <Riostream.h>
37 #include <TError.h>
38 #include <TNamed.h>
39 #include <TSystem.h>
40 #include <TEnv.h>
41 #include <TArrayC.h>
42 #include <Varargs.h> // platform independent definition of va_copy
43
44 #include "AliLog.h"
45
46 using std::endl;
47 using std::cout;
48 using std::ostream;
49 using std::cerr;
50 using std::ofstream;
51 using std::ios;
52 ClassImp(AliLog)
53
54 // implementation of a singleton here
55 AliLog* AliLog::fgInstance = NULL;
56
57 Bool_t AliLog::fgDebugEnabled = kTRUE;
58
59 /**
60  * get root logger singleton instance
61  */
62 AliLog *AliLog::GetRootLogger()
63 {
64         if (fgInstance == NULL)
65         {
66                 // creating singleton
67                 fgInstance =  new AliLog;
68         }
69
70         return fgInstance;
71 }
72
73 /**
74  * delete the root logger singleton instance
75  */
76 void AliLog::DeleteRootLogger()
77 {
78         if (fgInstance != NULL)
79         {
80                 delete fgInstance;
81                 fgInstance = NULL;
82         }
83 }
84
85 /**
86  * default private constructor
87  */
88 AliLog::AliLog() :
89   TObject(),
90   fGlobalLogLevel(kInfo),
91   fModuleDebugLevels(),
92   fClassDebugLevels(),
93   fPrintRepetitions(kTRUE),
94   fRepetitions(0),
95   fLastType(0),
96   fLastMessage(),
97   fLastModule(),
98   fLastClassName(),
99   fLastFunction(),
100   fLastFile(),
101   fLastLine(0)
102 {
103 // default constructor: set default values
104
105   for (Int_t iType = kFatal; iType < kMaxType; iType++)
106   {
107     fOutputTypes[iType] = 0;
108     fFileNames[iType] = "";
109     fOutputFiles[iType] = NULL;
110     fOutputStreams[iType] = NULL;
111     fCallBacks[iType]=NULL;
112
113     fPrintType[iType] = kTRUE;
114     fPrintModule[iType] = kFALSE;
115     fPrintScope[iType] = kTRUE;
116     fPrintLocation[iType] = (iType == kDebug);  
117   }
118
119   // TO BE REVIEWED
120   // replace the previous instance by this one
121   if (fgInstance) delete fgInstance;
122   fgInstance = this;
123
124   SetHandleRootMessages(kTRUE);
125
126   // read the .rootrc settings
127   ReadEnvSettings();
128 }
129
130 /**
131  * private destructor
132  */
133 AliLog::~AliLog()
134 {
135 // destructor: clean up and reset instance pointer
136
137   if (fRepetitions > 0) PrintRepetitions();
138
139   for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++)
140   {
141     if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
142   }
143
144   fClassDebugLevels.Delete();
145
146   for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++)
147   {
148     if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
149   }
150
151   fClassDebugLevels.Delete();
152
153   for (Int_t iType = kFatal; iType < kMaxType; iType++)
154   {
155     CloseFile(iType);
156   }
157
158   fflush(stderr);
159   fflush(stdout);
160
161   fgInstance = NULL;
162 }
163
164 // NOT IMPLEMENTED!?
165 //_____________________________________________________________________________
166 AliLog::AliLog(const AliLog& log) :
167   TObject(log),
168   fGlobalLogLevel(log.fGlobalLogLevel),
169   fModuleDebugLevels(log.fModuleDebugLevels),
170   fClassDebugLevels(log.fClassDebugLevels),
171   fPrintRepetitions(log.fPrintRepetitions),
172   fRepetitions(log.fRepetitions),
173   fLastType(log.fLastType),
174   fLastMessage(log.fLastMessage),
175   fLastModule(log.fLastModule),
176   fLastClassName(log.fLastClassName),
177   fLastFunction(log.fLastFunction),
178   fLastFile(log.fLastFile),
179   fLastLine(log.fLastLine)
180 {
181 // copy constructor
182
183   Fatal("AliLog", "copy constructor not implemented");
184 }
185
186 // NOT IMPLEMENTED!?
187 //_____________________________________________________________________________
188 AliLog& AliLog::operator = (const AliLog& /*log*/)
189 {
190 // assignment operator
191
192   Fatal("operator =", "assignment operator not implemented");
193   return *this;
194 }
195
196
197 /**
198  * gSystem see TSystem.h
199  * gEnv see TEnv.h
200  *
201  * LOG_NO_DEBUG: fgDebugEnabled <- false
202  * AliRoot.AliLog.EnableDebug
203  * AliRoot.AliLog.GlobalLogLevel
204  */
205 //_____________________________________________________________________________
206 void AliLog::ReadEnvSettings()
207 {
208 // load settings from the root configuration file (.rootrc)
209 // and from environment variables
210
211   static const char* typeNames[kMaxType] = {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
212
213   // debug en- or disabling
214   if (gSystem->Getenv("LOG_NO_DEBUG"))
215   {
216     fgDebugEnabled = kFALSE;
217   }
218   else if (gEnv->Defined("AliRoot.AliLog.EnableDebug"))
219   {
220     fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", fgDebugEnabled);
221     AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
222   }
223
224   // global log level
225   if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel"))
226   {
227     const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
228
229     for (Int_t iType = kFatal; iType < kMaxType; iType++)
230     {
231       if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
232     }
233
234     AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
235   }
236
237   // global debug level
238   if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel"))
239   {
240     Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel", Int_t(fGlobalLogLevel - kDebugOffset));
241     if (level < -kDebugOffset) level = kDebugOffset;
242     fGlobalLogLevel = kDebugOffset + level;
243     AliDebug(3, Form("global debug level set to %d", fGlobalLogLevel - kDebugOffset));
244   }
245
246   // module debug level
247   if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel"))
248   {
249     TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
250     char* p = const_cast<char*>(levels.Data());
251
252     while (const char* module = strtok(p, " "))
253     {
254       p = NULL;
255       char* pos = const_cast<char*>(index(module, ':'));
256       if (!pos) continue;
257       *(pos++) = '\0';
258       Int_t level = atoi(pos);
259       SetModuleDebugLevel(module, level);
260       AliDebug(3, Form("debug level for module %s set to %d", module, level));
261     }
262   }
263
264   // class debug level
265   if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel"))
266   {
267     TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
268     char* p = const_cast<char*>(levels.Data());
269
270     while (const char* className = strtok(p, " "))
271     {
272       p = NULL;
273       char* pos = const_cast<char*>(index(className, ':'));
274       if (!pos) continue;
275       *(pos++) = '\0';
276       Int_t level = atoi(pos);
277       SetClassDebugLevel(className, level);
278       AliDebug(3, Form("debug level for class %s set to %d", className, level));
279     }
280   }
281
282   // general output stream
283   if (gEnv->Defined("AliRoot.AliLog.Output"))
284   {
285     TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
286
287     if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
288     {
289       SetStandardOutput();
290       AliDebug(3, "output stream set to standard output for all types");
291     }
292     else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
293     {
294       SetErrorOutput();
295       AliDebug(3, "output stream set to error output for all types");
296     }
297     else if (!stream.IsNull())
298     {
299       SetFileOutput(stream);
300       AliDebug(3, Form("output stream set to file %s for all types", stream.Data()));
301     }
302   }
303
304   // individual output streams
305   for (Int_t iType = kFatal; iType < kMaxType; iType++)
306   {
307     TString name("AliRoot.AliLog.Output.");
308     name += &typeNames[iType][1];
309
310     if (gEnv->Defined(name))
311     {
312       TString stream = gEnv->GetValue(name, "Standard");
313
314       if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
315       {
316         SetStandardOutput(EType_t(iType));
317         AliDebug(3, Form("output stream set to standard output for type %s", typeNames[iType]));
318       }
319       else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
320       {
321         SetErrorOutput(EType_t(iType));
322         AliDebug(3, Form("output stream set to error output for type %s", typeNames[iType]));
323       }
324       else if (!stream.IsNull())
325       {
326         SetFileOutput(EType_t(iType), stream);
327         AliDebug(3, Form("output stream set to file %s for type %s", stream.Data(), typeNames[iType]));
328       }
329     }
330   }
331
332   // handling of root error messages
333   if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages"))
334   {
335     Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
336     SetHandleRootMessages(on);
337     AliDebug(3, Form("handling of root messages %sabled", ((on) ? "en" : "dis")));
338   }
339
340   // printout settings
341   static const char* settingNames[4] = {"Type", "Module", "Scope", "Location"};
342   Bool_t* settings[] = {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
343
344   for (Int_t iSetting = 0; iSetting < 4; iSetting++)
345   {
346     TString name("AliRoot.AliLog.Print");
347     name += settingNames[iSetting];
348
349     if (gEnv->Defined(name))
350     {
351       Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
352
353       for (Int_t iType = kFatal; iType < kMaxType; iType++)
354       {
355         settings[iSetting][iType] = on;
356       }
357       AliDebug(3, Form("printing of %s %sabled for all types", settingNames[iSetting], ((on) ? "en" : "dis")));
358     }
359
360     for (Int_t iType = kFatal; iType < kMaxType; iType++)
361     {
362       TString nameType = name + "." + &typeNames[iType][1];
363
364       if (gEnv->Defined(nameType))
365       {
366         Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
367         settings[iSetting][iType] = on;
368         AliDebug(3, Form("printing of %s %sabled for type %s", settingNames[iSetting], ((on) ? "en" : "dis"), typeNames[iType]));
369       }
370     }
371   }
372
373   // repetition of messages
374   if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions"))
375   {
376     Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
377     fPrintRepetitions = on;
378     AliDebug(3, Form("printing of message repetitions %sabled", ((on) ? "en" : "dis")));
379   }
380 }
381
382
383 //_____________________________________________________________________________
384 void AliLog::RootErrorHandler(Int_t level, Bool_t abort, 
385                               const char* location, const char* message)
386 {
387 // new error handler for messages from root
388
389   switch (level)
390   {
391   case ::kFatal    : level = kFatal; break;
392   case ::kSysError :
393     DefaultErrorHandler(level, abort, location, message);
394     return;
395   case ::kBreak    :
396     DefaultErrorHandler(level, abort, location, message);
397     return;
398   case ::kError    : level = kError; break;
399   case ::kWarning  : level = kWarning; break;
400   case ::kInfo     : level = kInfo; break;
401   default          : level = kDebug; break;
402   }
403   AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
404 }
405
406
407 // DEPRECATED: USE A CONFIGURATION FILE INSTEAD
408 //_____________________________________________________________________________
409 void AliLog::EnableDebug(Bool_t enabled)
410 {
411 // enable or disable debug output
412
413   fgDebugEnabled = enabled;
414 }
415
416 //_____________________________________________________________________________
417 void AliLog::SetGlobalLogLevel(EType_t type)
418 {
419 // set the global debug level
420
421   // TO BE DELETED
422   if (!fgInstance) new AliLog; 
423   fgInstance->fGlobalLogLevel = type;
424 }
425
426 //_____________________________________________________________________________
427 Int_t AliLog::GetGlobalLogLevel()
428 {
429 // get the global debug level
430
431   if (!fgInstance) new AliLog;
432   return fgInstance->fGlobalLogLevel;
433 }
434
435 //_____________________________________________________________________________
436 void AliLog::SetGlobalDebugLevel(Int_t level)
437 {
438 // set the global debug level
439
440   if (!fgInstance) new AliLog;
441   if (level < -kDebugOffset) level = -kDebugOffset;
442   fgInstance->fGlobalLogLevel = kDebugOffset + level;
443 }
444
445 //_____________________________________________________________________________
446 Int_t AliLog::GetGlobalDebugLevel()
447 {
448 // get the global debug level
449
450   if (!fgInstance) new AliLog;
451   return fgInstance->fGlobalLogLevel - kDebugOffset;
452 }
453
454 //_____________________________________________________________________________
455 void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
456 {
457 // set the debug level for the given module
458
459   if (!module) return;
460   if (!fgInstance) new AliLog;
461   TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
462   if (!obj) {
463     obj = new TNamed(module, module);
464     fgInstance->fModuleDebugLevels.Add(obj);
465   }
466   level += kDebugOffset;
467   if (level < kFatal) level = kFatal;
468   obj->SetUniqueID(level);
469 }
470
471 //_____________________________________________________________________________
472 void AliLog::ClearModuleDebugLevel(const char* module)
473 {
474 // remove the setting of the debug level for the given module
475
476   if (!module) return;
477   if (!fgInstance) new AliLog;
478   TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
479   if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
480 }
481
482 //_____________________________________________________________________________
483 void AliLog::SetClassDebugLevel(const char* className, Int_t level)
484 {
485 // set the debug level for the given class
486
487   if (!className) return;
488   if (!fgInstance) new AliLog;
489   TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
490   if (!obj) {
491     obj = new TNamed(className, className);
492     fgInstance->fClassDebugLevels.Add(obj);
493   }
494   level += kDebugOffset;
495   if (level < kFatal) level = kFatal;
496   obj->SetUniqueID(level);
497 }
498
499 //_____________________________________________________________________________
500 void AliLog::ClearClassDebugLevel(const char* className)
501 {
502 // remove the setting of the debug level for the given class
503
504   if (!className) return;
505   if (!fgInstance) new AliLog;
506   TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
507   if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
508 }
509
510
511 //_____________________________________________________________________________
512 void AliLog::SetStandardOutput()
513 {
514 // write all log messages to the standard output (stdout)
515
516   if (!fgInstance) new AliLog;
517   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
518     fgInstance->CloseFile(iType);
519     fgInstance->fOutputTypes[iType] = 0;
520   }
521 }
522
523 //_____________________________________________________________________________
524 void AliLog::SetStandardOutput(EType_t type)
525 {
526 // write log messages of the given type to the standard output (stdout)
527
528   if ((type < kFatal) || (type >= kMaxType)) return;
529   if (!fgInstance) new AliLog;
530   fgInstance->CloseFile(type);
531   fgInstance->fOutputTypes[type] = 0;
532 }
533
534 //_____________________________________________________________________________
535 void AliLog::SetErrorOutput()
536 {
537 // write all log messages to the error output (stderr)
538
539   if (!fgInstance) new AliLog;
540   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
541     fgInstance->CloseFile(iType);
542     fgInstance->fOutputTypes[iType] = 1;
543   }
544 }
545
546 //_____________________________________________________________________________
547 void AliLog::SetErrorOutput(EType_t type)
548 {
549 // write log messages of the given type to the error output (stderr)
550
551   if ((type < kFatal) || (type >= kMaxType)) return;
552   if (!fgInstance) new AliLog;
553   fgInstance->CloseFile(type);
554   fgInstance->fOutputTypes[type] = 1;
555 }
556
557 //_____________________________________________________________________________
558 void AliLog::SetFileOutput(const char* fileName)
559 {
560 // write all log messages to the given file
561
562   if (!fgInstance) new AliLog;
563   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
564     if ((fgInstance->fOutputTypes[iType] == 2) && 
565         (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
566       fgInstance->CloseFile(iType);
567     }
568     fgInstance->fOutputTypes[iType] = 2;
569     fgInstance->fFileNames[iType] = fileName;
570     fgInstance->fOutputFiles[iType] = NULL;
571     fgInstance->fOutputStreams[iType] = NULL;
572   }
573 }
574
575 //_____________________________________________________________________________
576 void AliLog::SetFileOutput(EType_t type, const char* fileName)
577 {
578 // write log messages of the given type to the given file
579
580   if ((type < kFatal) || (type >= kMaxType)) return;
581   if (!fgInstance) new AliLog;
582   if ((fgInstance->fOutputTypes[type] == 2) && 
583       (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
584     fgInstance->CloseFile(type);
585   }
586   fgInstance->fOutputTypes[type] = 2;
587   fgInstance->fFileNames[type] = fileName;
588   fgInstance->fOutputFiles[type] = NULL;
589   fgInstance->fOutputStreams[type] = NULL;
590 }
591
592 //_____________________________________________________________________________
593 void AliLog::CloseFile(Int_t type)
594 {
595 // close the file for the given type if needed
596
597   if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
598     Bool_t closeFile = kTRUE;
599     for (Int_t iType = kFatal; iType < kMaxType; iType++) {
600       if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
601         closeFile = kFALSE;
602       }
603     }
604     if (closeFile) {
605       fclose(fOutputFiles[type]);
606       ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
607       stream->close();
608       delete fOutputStreams[type];
609     }
610   }
611   fOutputFiles[type] = NULL;
612   fOutputStreams[type] = NULL;
613   fFileNames[type] = "";
614   fOutputTypes[type] = 0;
615 }
616
617 //_____________________________________________________________________________
618 FILE* AliLog::GetOutputStream(Int_t type)
619 {
620 // get the output stream for the given type of messages
621
622   if (type > kDebug) type = kDebug;
623   if (fOutputTypes[type] == 0) return stdout;
624   else if (fOutputTypes[type] == 1) return stderr;
625   else if (fOutputTypes[type] == 2) {
626     if (!fOutputFiles[type]) {
627       FILE* file = NULL;
628       ostream* stream = NULL;
629       if (!fFileNames[type].IsNull()) {
630         for (Int_t iType = kFatal; iType < kMaxType; iType++) {
631           if ((iType != type) && 
632               (fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
633               fOutputFiles[iType]) {
634             file = fOutputFiles[iType];
635             stream = fOutputStreams[iType];
636             break;
637           }
638         }
639         if (!file) {
640           file = fopen(fFileNames[type], "a");
641           stream = new ofstream(fFileNames[type], ios::app);
642         }
643       }
644       fOutputFiles[type] = file;
645       fOutputStreams[type] = stream;
646       if (!file) CloseFile(type);
647     }
648     if (fOutputFiles[type]) return fOutputFiles[type];
649   }
650
651   return stdout;
652 }
653
654 //_____________________________________________________________________________
655 void AliLog::Flush()
656 {
657 // flush the output streams
658
659   if (!fgInstance) new AliLog;
660   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
661     if (fgInstance->fOutputFiles[iType]) {
662       fflush(fgInstance->fOutputFiles[iType]);
663       fgInstance->fOutputStreams[iType]->flush();
664     }
665   }
666   fflush(stderr);
667   fflush(stdout);
668 }
669
670
671 //_____________________________________________________________________________
672 void AliLog::SetHandleRootMessages(Bool_t on)
673 {
674 // enable or disable the handling of messages form root
675
676   if (!fgInstance) new AliLog;
677   if (on) {
678     SetErrorHandler(RootErrorHandler);
679   } else {
680     SetErrorHandler(DefaultErrorHandler);
681   }
682 }
683
684
685 //_____________________________________________________________________________
686 void AliLog::SetPrintType(Bool_t on)
687 {
688 // switch on or off the printing of the message type for all message types
689
690   if (!fgInstance) new AliLog;
691   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
692     fgInstance->fPrintType[iType] = on;
693   }
694 }
695
696 //_____________________________________________________________________________
697 void AliLog::SetPrintType(EType_t type, Bool_t on)
698 {
699 // switch on or off the printing of the message type for the given message type
700
701   if ((type < kFatal) || (type >= kMaxType)) return;
702   if (!fgInstance) new AliLog;
703   fgInstance->fPrintType[type] = on;
704 }
705
706 //_____________________________________________________________________________
707 void AliLog::SetPrintModule(Bool_t on)
708 {
709 // switch on or off the printing of the module for all message types
710
711   if (!fgInstance) new AliLog;
712   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
713     fgInstance->fPrintModule[iType] = on;
714   }
715 }
716
717 //_____________________________________________________________________________
718 void AliLog::SetPrintModule(EType_t type, Bool_t on)
719 {
720 // switch on or off the printing of the module for the given message type
721
722   if ((type < kFatal) || (type >= kMaxType)) return;
723   if (!fgInstance) new AliLog;
724   fgInstance->fPrintModule[type] = on;
725 }
726
727 //_____________________________________________________________________________
728 void AliLog::SetPrintScope(Bool_t on)
729 {
730 // switch on or off the printing of the scope/class name for all message types
731
732   if (!fgInstance) new AliLog;
733   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
734     fgInstance->fPrintScope[iType] = on;
735   }
736 }
737
738 //_____________________________________________________________________________
739 void AliLog::SetPrintScope(EType_t type, Bool_t on)
740 {
741 // switch on or off the printing of the scope/class name
742 // for the given message type
743
744   if ((type < kFatal) || (type >= kMaxType)) return;
745   if (!fgInstance) new AliLog;
746   fgInstance->fPrintScope[type] = on;
747 }
748
749 //_____________________________________________________________________________
750 void AliLog::SetPrintLocation(Bool_t on)
751 {
752 // switch on or off the printing of the file name and line number
753 // for all message types
754
755   if (!fgInstance) new AliLog;
756   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
757     fgInstance->fPrintLocation[iType] = on;
758   }
759 }
760
761 //_____________________________________________________________________________
762 void AliLog::SetPrintLocation(EType_t type, Bool_t on)
763 {
764 // switch on or off the printing of the file name and line number 
765 // for the given message type
766
767   if ((type < kFatal) || (type >= kMaxType)) return;
768   if (!fgInstance) new AliLog;
769   fgInstance->fPrintLocation[type] = on;
770 }
771
772
773 //_____________________________________________________________________________
774 void AliLog::SetPrintRepetitions(Bool_t on)
775 {
776 // switch on or off the printing of the number of repetitions of a message
777 // instead of repeating the same message
778
779   if (!fgInstance) new AliLog;
780   if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
781   fgInstance->fPrintRepetitions = on;
782 }
783
784
785 //_____________________________________________________________________________
786 void AliLog::WriteToFile(const char* name, Int_t option)
787 {
788 // write the log object with the given name and option to the current file
789
790   if (!fgInstance) new AliLog;
791   fgInstance->TObject::Write(name, option);
792 }
793
794
795 //_____________________________________________________________________________
796 UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
797 {
798 // get the logging level for the given module and class
799
800   if (!fgInstance) new AliLog;
801   if (className) {
802     TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
803     if (obj) return obj->GetUniqueID();
804   }
805   if (module) {
806     TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
807     if (obj) return obj->GetUniqueID();
808   }
809   return fgInstance->fGlobalLogLevel;
810 }
811
812 //_____________________________________________________________________________
813 Int_t AliLog::GetDebugLevel(const char* module, const char* className)
814 {
815 // get the debug level for the given module and class
816
817   if (!fgInstance) new AliLog;
818   return fgInstance->GetLogLevel(module, className) - kDebugOffset;
819 }
820
821 //_____________________________________________________________________________
822 void AliLog::PrintMessage(UInt_t type, const char* message, 
823                           const char* module, const char* className,
824                           const char* function, const char* file, Int_t line)
825 {
826 // print the given message
827
828   // don't print the message if it is repeated
829   if (fPrintRepetitions &&
830       (fLastType == type) && 
831       (message && (fLastMessage.CompareTo(message) == 0)) &&
832       ((module && (fLastModule.CompareTo(module) == 0)) ||
833        (!module && fLastModule.IsNull())) &&
834       ((className && (fLastClassName.CompareTo(className) == 0)) ||
835        (!className && fLastClassName.IsNull())) &&
836       ((function && (fLastFunction.CompareTo(function) == 0)) ||
837        (!function && fLastFunction.IsNull()))&&
838       ((file && (fLastFile.CompareTo(file) == 0)) ||
839        (!file && fLastFile.IsNull())) &&
840       (fLastLine == line)) {
841     fRepetitions++;
842     return;
843   }
844
845   // print number of repetitions
846   if (fRepetitions > 0) PrintRepetitions();
847
848   // remember this message
849   fRepetitions = 0;
850   fLastType = type;
851   fLastMessage = message;
852   fLastModule = module;
853   fLastClassName = className;
854   fLastFunction = function;
855   fLastFile = file;
856   fLastLine = line;
857
858   // print the message
859   FILE* stream = GetOutputStream(type);
860   static const char* typeNames[kMaxType] = 
861     {"Fatal", "Error", "Warning", "Info", "Debug"};
862
863   if (fPrintType[type]) {
864     PrintString(type, stream, "%c-", typeNames[type][0]);
865   }
866   if (fPrintModule[type] && module) {
867     PrintString(type, stream, "%s/", module);
868   }
869   if (fPrintScope[type] && className) {
870     PrintString(type, stream, "%s::", className);
871   }
872   if (message) {
873     PrintString(type, stream, "%s: %s", function, message);
874   } else {
875     PrintString(type, stream, "%s", function);
876   }
877   if (fPrintLocation[type] && file) {
878     PrintString(type, stream, " (%s:%.0d)", file, line);
879   }
880   if (message) {
881     PrintString(type, stream, "\n");
882   } else {
883     PrintString(type, stream, ": ");
884   }
885   if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
886 }
887
888 //_____________________________________________________________________________
889 void AliLog::PrintRepetitions()
890 {
891 // print number of repetitions
892
893   PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n", 
894           fRepetitions, (fRepetitions > 1) ? "s" : "");
895   if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
896 }
897
898 //_____________________________________________________________________________
899 void AliLog::Message(UInt_t level, const char* message, 
900                      const char* module, const char* className,
901                      const char* function, const char* file, Int_t line)
902 {
903 // print a log message
904
905   if (!fgInstance) new AliLog;
906
907   // get the message type
908   UInt_t type = level;
909   if (type >= kMaxType) type = kMaxType - 1;
910
911   // print the message if the debug level allows
912   if (level <= fgInstance->GetLogLevel(module, className)) {
913     fgInstance->PrintMessage(type, message, 
914                              module, className, function, file, line);
915   }
916
917   // abort in case of a fatal message
918   if (type == kFatal) {
919     delete fgInstance;
920     if (gSystem) {
921       gSystem->StackTrace();
922       gSystem->Abort();
923     } else {
924       ::abort();
925     }
926   }
927 }
928
929 //_____________________________________________________________________________
930 void AliLog::Debug(UInt_t level, const char* message, 
931                    const char* module, const char* className,
932                    const char* function, const char* file, Int_t line)
933 {
934 // print a debug message
935
936   if (level == 0) level = 1;
937   level += kDebugOffset;
938   Message(level, message, module, className, function, file, line);
939 }
940
941
942 //_____________________________________________________________________________
943 Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module, 
944                                const char* className, const char* function,
945                                const char* file, Int_t line, Bool_t print)
946 {
947 // redirect the standard output to the stream of the given type
948
949   if (!fgInstance) new AliLog;
950   return fgInstance->RedirectTo(stdout, type, level, module, className, 
951                                 function, file, line, print);
952 }
953
954 //_____________________________________________________________________________
955 Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module, 
956                                const char* className, const char* function,
957                                const char* file, Int_t line, Bool_t print)
958 {
959 // redirect the standard error output to the stream of the given type
960
961   if (!fgInstance) new AliLog;
962   return fgInstance->RedirectTo(stderr, type, level, module, className, 
963                                 function, file, line, print);
964 }
965
966 //_____________________________________________________________________________
967 Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level, 
968                          const char* module, const char* className,
969                          const char* function, const char* file, Int_t line,
970                          Bool_t print)
971 {
972 // redirect the standard (error) output stream to the stream of the given type
973
974   // get the original file descriptor to be able to restore it later
975   Int_t original = dup(fileno(stream));
976   fflush(stream);
977
978   // flush the stream of the selected type
979   FILE* newStream = GetOutputStream(type);
980   fflush(newStream);
981
982   // redirect stream
983   if ((type == kDebug) && (level > 0)) level--;
984   if (type + level > GetLogLevel(module, className)) { // /dev/null
985     if(!freopen("/dev/null", "a", stream)) AliWarning("Cannot reopen /dev/null");
986   } else if (fOutputTypes[type] == 0) {         // stdout
987     if (stream != stdout) dup2(fileno(stdout), fileno(stream));
988   } else if (fOutputTypes[type] == 1) {         // stderr
989     if (stream != stderr) dup2(fileno(stderr), fileno(stream));
990   } else if (fOutputTypes[type] == 2) {         // file
991     if(!freopen(fFileNames[type], "a", stream)) AliWarning(Form("Cannot reopen %s",fFileNames[type].Data()));
992   } else if (fOutputTypes[type] == 3) {         // external C++ stream
993     // redirection is not possible for external C++ streams
994   }
995
996   // print information
997   if (print) {
998     PrintMessage(type, NULL, module, className, function, file, line);
999     fflush(newStream);
1000   }
1001
1002   return original;
1003 }
1004
1005 //_____________________________________________________________________________
1006 void AliLog::RestoreStdout(Int_t original)
1007 {
1008 // restore the standard output
1009
1010   fflush(stdout);
1011   dup2(original, fileno(stdout));  
1012   close(original);
1013 }
1014
1015 //_____________________________________________________________________________
1016 void AliLog::RestoreStderr(Int_t original)
1017 {
1018 // restore the standard error output
1019
1020   fflush(stderr);
1021   dup2(original, fileno(stderr));  
1022   close(original);
1023 }
1024
1025
1026 //_____________________________________________________________________________
1027 ostream& AliLog::Stream(EType_t type, UInt_t level,
1028                         const char* module, const char* className,
1029                         const char* function, const char* file, Int_t line)
1030 {
1031 // get the stream object for the given output type
1032
1033   if (!fgInstance) new AliLog;
1034   return fgInstance->GetStream(type, level, module, className, 
1035                                function, file, line);
1036 }
1037
1038 //_____________________________________________________________________________
1039 ostream& AliLog::GetStream(EType_t type, UInt_t level,
1040                            const char* module, const char* className,
1041                            const char* function, const char* file, Int_t line)
1042 {
1043 // get the stream object for the given output type
1044
1045   if ((type == kDebug) && (level > 0)) level--;
1046   Bool_t noOutput = (type + level > GetLogLevel(module, className));
1047
1048   if (!noOutput) {
1049     PrintMessage(type, NULL, module, className, function, file, line);
1050   }
1051   fflush(GetOutputStream(type));
1052
1053   static ofstream nullStream("/dev/null");
1054   if (noOutput) {
1055     return nullStream;
1056   } else if (fOutputTypes[type] == 0) {
1057     return cout;
1058   } else if (fOutputTypes[type] == 1) {
1059     return cerr;
1060   } else if (fOutputTypes[type] == 2) {
1061     return *fOutputStreams[type];
1062   } else if (fOutputTypes[type] == 3) {
1063     return *fOutputStreams[type];
1064   }
1065
1066   return nullStream;
1067 }
1068
1069 void  AliLog::SetStreamOutput(ostream* stream)
1070 {
1071   // set an external stream as target for log messages of all types
1072   // the external stream is completely handled by the caller, the
1073   // AliLog class just writes to it
1074
1075   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1076     SetStreamOutput((AliLog::EType_t)iType, stream);
1077   }
1078 }
1079
1080 void  AliLog::SetStreamOutput(EType_t type, ostream* stream)
1081 {
1082   // set an external stream as target for log messages of the given type
1083   // the external stream is completely handled by the caller, the
1084   // AliLog class just writes to it
1085
1086   if ((type < kFatal) || (type >= kMaxType)) return;
1087   if (!fgInstance) new AliLog;
1088   if (fgInstance->fOutputTypes[type] == 2) {
1089     fgInstance->CloseFile(type);
1090   }
1091   fgInstance->fOutputTypes[type] = 3;
1092   fgInstance->fFileNames[type] = "";
1093   fgInstance->fOutputFiles[type] = NULL;
1094   fgInstance->fOutputStreams[type] = stream;
1095 }
1096
1097 void  AliLog::SetLogNotification(AliLogNotification pCallBack)
1098 {
1099   // set a notification callback function for log messages of all types
1100
1101   for (Int_t iType = kFatal; iType < kMaxType; iType++) {
1102     SetLogNotification((AliLog::EType_t)iType, pCallBack);
1103   }
1104 }
1105
1106 void  AliLog::SetLogNotification(EType_t type, AliLogNotification pCallBack)
1107 {
1108   // set a notifications call back function for log messages of all types
1109   // the callback fuction is invoced whenever an output was written
1110   // Note: does not work for c++ streamer classes, the external stream
1111   // has to handle this diectly (e.g. custom implementation of endl)
1112
1113   if ((type < kFatal) || (type >= kMaxType)) return;
1114   if (!fgInstance) new AliLog;
1115   fgInstance->fCallBacks[type]=pCallBack;
1116 }
1117
1118 void  AliLog::PrintString(Int_t type, FILE* stream, const char* format, ...)
1119 {
1120   // this is the general method to print a log message using variadac args
1121   // to the FILE* like (C - like) streams, e.g. stdout, stderr, or files
1122   // opened by fopen.
1123   // Only in case of an external c++ ostream type output, the message is
1124   // written to that stream and the notifictaion callback is called.
1125   // The message is printed by a normal vfprintf function otherwise
1126
1127   if (format==NULL) return;
1128   
1129   va_list ap;
1130   va_start(ap, format);
1131   if (fOutputTypes[type] != 3) {
1132     if (stream!=NULL) {
1133       vfprintf(stream, format, ap);
1134     }
1135   } else {
1136     // build the string and write everthing to the corresponding ostream
1137     TString fmt(format);
1138     TArrayC tgt(fmt.Length()*10); // just take a number
1139 #ifdef R__VA_COPY
1140     va_list bap;
1141     R__VA_COPY(bap, ap);
1142 #else
1143 #warning definition of R__VA_COPY has disappeared
1144 #endif //R__VA_COPY
1145
1146     Int_t iResult=0;
1147     while (1) {
1148       iResult=vsnprintf(tgt.GetArray(), tgt.GetSize(), format, ap);
1149       if (iResult==-1) {
1150         iResult=tgt.GetSize()*2;
1151       } else if (iResult<tgt.GetSize()) {
1152         break;
1153       }
1154 #ifdef R__VA_COPY
1155       if (iResult<10000) {
1156         tgt.Set(iResult+1);
1157         va_end(ap);
1158         R__VA_COPY(ap, bap);
1159       } else
1160 #endif //R__VA_COPY 
1161       {
1162         tgt[tgt.GetSize()-1]=0;
1163         break;
1164       }
1165     }
1166 #ifdef R__VA_COPY
1167     va_end(bap);
1168 #endif //R__VA_COPY
1169
1170     if (fOutputStreams[type]) {
1171       *(fOutputStreams[type]) << tgt.GetArray();
1172     }
1173   }
1174   va_end(ap);
1175 }