strings.h declares index on Sun
[u/mrichter/AliRoot.git] / STEER / AliLog.cxx
CommitLineData
6ab674bd 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16/* $Id$ */
17
18///////////////////////////////////////////////////////////////////////////////
19// //
20// class for logging debug, info and error messages //
21// //
22// The AliLog class is a singleton class. It allows to steer the output //
23// level and output streams for different types of messages via static //
24// methods. //
25// //
26// It also handles the messages produces by the preprocessor macros defined //
27// in the header file: AliDebug, AliInfo, AliWarning, AliError, AliFatal. //
28// //
29// More details about the message logging can be found on the ALICE Offline //
30// web page. //
31// //
32///////////////////////////////////////////////////////////////////////////////
33
30ae1e2b 34#include <strings.h>
eeb769e2 35#include <Riostream.h>
6ab674bd 36#include <TError.h>
37#include <TNamed.h>
38#include <TSystem.h>
eeb769e2 39#include <TEnv.h>
6ab674bd 40
41#include "AliLog.h"
42
43ClassImp(AliLog)
44
45
46AliLog* AliLog::fgInstance = NULL;
47
48Bool_t AliLog::fgDebugEnabled = kTRUE;
49
50
51//_____________________________________________________________________________
52AliLog::AliLog() :
53 TObject(),
54 fGlobalLogLevel(kInfo),
55 fModuleDebugLevels(),
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;
eeb769e2 64 fOutputStreams[iType] = NULL;
6ab674bd 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;
eeb769e2 77
78 // read the .rootrc settings
79 ReadEnvSettings();
6ab674bd 80}
81
82//_____________________________________________________________________________
83AliLog::~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//_____________________________________________________________________________
106AliLog::AliLog(const AliLog& log) :
107 TObject(log)
108{
109// copy constructor
110
111 Fatal("AliLog", "copy constructor not implemented");
112}
113
114//_____________________________________________________________________________
115AliLog& AliLog::operator = (const AliLog& /*log*/)
116{
117// assignment operator
118
119 Fatal("operator =", "assignment operator not implemented");
120 return *this;
121}
122
123
eeb769e2 124//_____________________________________________________________________________
125void 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
6ab674bd 269//_____________________________________________________________________________
270void 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//_____________________________________________________________________________
293void AliLog::EnableDebug(Bool_t enabled)
294{
295// enable or disable debug output
296
297 fgDebugEnabled = enabled;
298}
299
300//_____________________________________________________________________________
301void AliLog::SetGlobalLogLevel(EType type)
302{
303// set the global debug level
304
305 if (!fgInstance) new AliLog;
306 fgInstance->fGlobalLogLevel = type;
307}
308
309//_____________________________________________________________________________
310Int_t AliLog::GetGlobalLogLevel()
311{
312// get the global debug level
313
314 if (!fgInstance) new AliLog;
315 return fgInstance->fGlobalLogLevel;
316}
317
318//_____________________________________________________________________________
319void 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//_____________________________________________________________________________
329Int_t AliLog::GetGlobalDebugLevel()
330{
331// get the global debug level
332
333 if (!fgInstance) new AliLog;
334 return fgInstance->fGlobalLogLevel - kDebugOffset;
335}
336
337//_____________________________________________________________________________
338void 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//_____________________________________________________________________________
355void 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//_____________________________________________________________________________
366void 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//_____________________________________________________________________________
383void 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//_____________________________________________________________________________
395void 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//_____________________________________________________________________________
407void 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//_____________________________________________________________________________
418void 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//_____________________________________________________________________________
430void 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//_____________________________________________________________________________
441void 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++) {
051599bf 447 if ((fgInstance->fOutputTypes[iType] == 2) &&
6ab674bd 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;
eeb769e2 454 fgInstance->fOutputStreams[iType] = NULL;
6ab674bd 455 }
456}
457
458//_____________________________________________________________________________
459void 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;
051599bf 465 if ((fgInstance->fOutputTypes[type] == 2) &&
6ab674bd 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;
eeb769e2 472 fgInstance->fOutputStreams[type] = NULL;
6ab674bd 473}
474
475//_____________________________________________________________________________
476void 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 }
eeb769e2 487 if (closeFile) {
488 fclose(fOutputFiles[type]);
489 fOutputStreams[type]->close();
490 delete fOutputStreams[type];
491 }
6ab674bd 492 }
493 fOutputFiles[type] = NULL;
eeb769e2 494 fOutputStreams[type] = NULL;
6ab674bd 495 fFileNames[type] = "";
496 fOutputTypes[type] = 0;
497}
498
499//_____________________________________________________________________________
500FILE* AliLog::GetOutputStream(Int_t type)
501{
502// get the output stream for the given type of messages
503
eeb769e2 504 if (type > kDebug) type = kDebug;
6ab674bd 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;
eeb769e2 510 ofstream* stream = NULL;
6ab674bd 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];
eeb769e2 517 stream = fOutputStreams[iType];
6ab674bd 518 break;
519 }
520 }
eeb769e2 521 if (!file) {
522 file = fopen(fFileNames[type], "a");
523 stream = new ofstream(fFileNames[type], ios::app);
524 }
6ab674bd 525 }
526 fOutputFiles[type] = file;
eeb769e2 527 fOutputStreams[type] = stream;
6ab674bd 528 if (!file) CloseFile(type);
529 }
530 if (fOutputFiles[type]) return fOutputFiles[type];
531 }
532
533 return stdout;
534}
535
536//_____________________________________________________________________________
537void 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]);
eeb769e2 545 fgInstance->fOutputStreams[iType]->flush();
6ab674bd 546 }
547 }
548 fflush(stderr);
549 fflush(stdout);
550}
551
552
553//_____________________________________________________________________________
554void 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//_____________________________________________________________________________
567void 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//_____________________________________________________________________________
578void 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//_____________________________________________________________________________
588void 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//_____________________________________________________________________________
599void 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//_____________________________________________________________________________
609void 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//_____________________________________________________________________________
620void 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//_____________________________________________________________________________
631void 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//_____________________________________________________________________________
643void 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//_____________________________________________________________________________
655void 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//_____________________________________________________________________________
665UInt_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//_____________________________________________________________________________
678Int_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
eeb769e2 686//_____________________________________________________________________________
687void 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
6ab674bd 722//_____________________________________________________________________________
723void 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
6ab674bd 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)) {
eeb769e2 737 fgInstance->PrintMessage(type, message,
738 module, className, function, file, line);
6ab674bd 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//_____________________________________________________________________________
754void 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}
eeb769e2 764
765
766//_____________________________________________________________________________
767Int_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//_____________________________________________________________________________
779Int_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//_____________________________________________________________________________
791Int_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//_____________________________________________________________________________
828void AliLog::RestoreStdout(Int_t original)
829{
830// restore the standard output
831
832 fflush(stdout);
833 dup2(original, fileno(stdout));
834}
835
836//_____________________________________________________________________________
837void 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//_____________________________________________________________________________
847ostream& 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//_____________________________________________________________________________
859ostream& 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