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