]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/STEERBase/AliLog.cxx
- fast TRD PID implementation with muon constraints (Daniel Lohner)
[u/mrichter/AliRoot.git] / STEER / STEERBase / 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
66b0310c 46using std::endl;
47using std::cout;
48using std::ostream;
49using std::cerr;
50using std::ofstream;
51using std::ios;
6ab674bd 52ClassImp(AliLog)
53
6d7793cf 54// implementation of a singleton here
6ab674bd 55AliLog* AliLog::fgInstance = NULL;
56
57Bool_t AliLog::fgDebugEnabled = kTRUE;
58
6d7793cf 59/**
60 * get root logger singleton instance
61 */
62AliLog *AliLog::GetRootLogger()
63{
64 if (fgInstance == NULL)
65 {
66 // creating singleton
67 fgInstance = new AliLog;
68 }
6ab674bd 69
6d7793cf 70 return fgInstance;
71}
72
73/**
74 * delete the root logger singleton instance
75 */
76void AliLog::DeleteRootLogger()
77{
78 if (fgInstance != NULL)
79 {
80 delete fgInstance;
81 fgInstance = NULL;
82 }
83}
84
85/**
86 * default private constructor
87 */
6ab674bd 88AliLog::AliLog() :
89 TObject(),
90 fGlobalLogLevel(kInfo),
91 fModuleDebugLevels(),
45fa0297 92 fClassDebugLevels(),
93 fPrintRepetitions(kTRUE),
94 fRepetitions(0),
95 fLastType(0),
96 fLastMessage(),
97 fLastModule(),
98 fLastClassName(),
99 fLastFunction(),
100 fLastFile(),
101 fLastLine(0)
6ab674bd 102{
103// default constructor: set default values
104
6d7793cf 105 for (Int_t iType = kFatal; iType < kMaxType; iType++)
106 {
6ab674bd 107 fOutputTypes[iType] = 0;
108 fFileNames[iType] = "";
109 fOutputFiles[iType] = NULL;
eeb769e2 110 fOutputStreams[iType] = NULL;
1948744e 111 fCallBacks[iType]=NULL;
6ab674bd 112
113 fPrintType[iType] = kTRUE;
114 fPrintModule[iType] = kFALSE;
115 fPrintScope[iType] = kTRUE;
116 fPrintLocation[iType] = (iType == kDebug);
117 }
118
6d7793cf 119 // TO BE REVIEWED
6ab674bd 120 // replace the previous instance by this one
121 if (fgInstance) delete fgInstance;
122 fgInstance = this;
eeb769e2 123
45fa0297 124 SetHandleRootMessages(kTRUE);
125
eeb769e2 126 // read the .rootrc settings
127 ReadEnvSettings();
6ab674bd 128}
129
6d7793cf 130/**
131 * private destructor
132 */
6ab674bd 133AliLog::~AliLog()
134{
135// destructor: clean up and reset instance pointer
136
45fa0297 137 if (fRepetitions > 0) PrintRepetitions();
138
6d7793cf 139 for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++)
140 {
6ab674bd 141 if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
142 }
6d7793cf 143
6ab674bd 144 fClassDebugLevels.Delete();
6d7793cf 145
146 for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++)
147 {
6ab674bd 148 if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
149 }
6d7793cf 150
6ab674bd 151 fClassDebugLevels.Delete();
152
6d7793cf 153 for (Int_t iType = kFatal; iType < kMaxType; iType++)
154 {
6ab674bd 155 CloseFile(iType);
156 }
6d7793cf 157
6ab674bd 158 fflush(stderr);
159 fflush(stdout);
160
161 fgInstance = NULL;
162}
163
6d7793cf 164// NOT IMPLEMENTED!?
6ab674bd 165//_____________________________________________________________________________
166AliLog::AliLog(const AliLog& log) :
90e48c0c 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)
6ab674bd 180{
181// copy constructor
182
183 Fatal("AliLog", "copy constructor not implemented");
184}
185
6d7793cf 186// NOT IMPLEMENTED!?
6ab674bd 187//_____________________________________________________________________________
188AliLog& AliLog::operator = (const AliLog& /*log*/)
189{
190// assignment operator
191
192 Fatal("operator =", "assignment operator not implemented");
193 return *this;
194}
195
196
6d7793cf 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 */
eeb769e2 205//_____________________________________________________________________________
206void AliLog::ReadEnvSettings()
207{
208// load settings from the root configuration file (.rootrc)
209// and from environment variables
210
6d7793cf 211 static const char* typeNames[kMaxType] = {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
eeb769e2 212
213 // debug en- or disabling
6d7793cf 214 if (gSystem->Getenv("LOG_NO_DEBUG"))
215 {
eeb769e2 216 fgDebugEnabled = kFALSE;
6d7793cf 217 }
218 else if (gEnv->Defined("AliRoot.AliLog.EnableDebug"))
219 {
220 fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", fgDebugEnabled);
eeb769e2 221 AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
222 }
223
224 // global log level
6d7793cf 225 if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel"))
226 {
eeb769e2 227 const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
6d7793cf 228
229 for (Int_t iType = kFatal; iType < kMaxType; iType++)
230 {
eeb769e2 231 if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
232 }
6d7793cf 233
eeb769e2 234 AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
235 }
236
237 // global debug level
6d7793cf 238 if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel"))
239 {
240 Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel", Int_t(fGlobalLogLevel - kDebugOffset));
eeb769e2 241 if (level < -kDebugOffset) level = kDebugOffset;
242 fGlobalLogLevel = kDebugOffset + level;
6d7793cf 243 AliDebug(3, Form("global debug level set to %d", fGlobalLogLevel - kDebugOffset));
eeb769e2 244 }
245
246 // module debug level
6d7793cf 247 if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel"))
248 {
eeb769e2 249 TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
250 char* p = const_cast<char*>(levels.Data());
6d7793cf 251
252 while (const char* module = strtok(p, " "))
253 {
eeb769e2 254 p = NULL;
12f04812 255 char* pos = const_cast<char*>(index(module, ':'));
eeb769e2 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
6d7793cf 265 if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel"))
266 {
eeb769e2 267 TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
268 char* p = const_cast<char*>(levels.Data());
6d7793cf 269
270 while (const char* className = strtok(p, " "))
271 {
eeb769e2 272 p = NULL;
12f04812 273 char* pos = const_cast<char*>(index(className, ':'));
eeb769e2 274 if (!pos) continue;
275 *(pos++) = '\0';
276 Int_t level = atoi(pos);
277 SetClassDebugLevel(className, level);
6d7793cf 278 AliDebug(3, Form("debug level for class %s set to %d", className, level));
eeb769e2 279 }
280 }
281
282 // general output stream
6d7793cf 283 if (gEnv->Defined("AliRoot.AliLog.Output"))
284 {
eeb769e2 285 TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
6d7793cf 286
287 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
288 {
eeb769e2 289 SetStandardOutput();
290 AliDebug(3, "output stream set to standard output for all types");
6d7793cf 291 }
292 else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
293 {
eeb769e2 294 SetErrorOutput();
295 AliDebug(3, "output stream set to error output for all types");
6d7793cf 296 }
297 else if (!stream.IsNull())
298 {
eeb769e2 299 SetFileOutput(stream);
6d7793cf 300 AliDebug(3, Form("output stream set to file %s for all types", stream.Data()));
eeb769e2 301 }
302 }
303
304 // individual output streams
6d7793cf 305 for (Int_t iType = kFatal; iType < kMaxType; iType++)
306 {
eeb769e2 307 TString name("AliRoot.AliLog.Output.");
308 name += &typeNames[iType][1];
6d7793cf 309
310 if (gEnv->Defined(name))
311 {
eeb769e2 312 TString stream = gEnv->GetValue(name, "Standard");
6d7793cf 313
314 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
315 {
44ce6bbe 316 SetStandardOutput(EType_t(iType));
6d7793cf 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 {
44ce6bbe 321 SetErrorOutput(EType_t(iType));
6d7793cf 322 AliDebug(3, Form("output stream set to error output for type %s", typeNames[iType]));
323 }
324 else if (!stream.IsNull())
325 {
44ce6bbe 326 SetFileOutput(EType_t(iType), stream);
6d7793cf 327 AliDebug(3, Form("output stream set to file %s for type %s", stream.Data(), typeNames[iType]));
eeb769e2 328 }
329 }
330 }
331
332 // handling of root error messages
6d7793cf 333 if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages"))
334 {
eeb769e2 335 Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
336 SetHandleRootMessages(on);
6d7793cf 337 AliDebug(3, Form("handling of root messages %sabled", ((on) ? "en" : "dis")));
eeb769e2 338 }
339
340 // printout settings
6d7793cf 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 {
eeb769e2 346 TString name("AliRoot.AliLog.Print");
347 name += settingNames[iSetting];
6d7793cf 348
349 if (gEnv->Defined(name))
350 {
eeb769e2 351 Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
6d7793cf 352
353 for (Int_t iType = kFatal; iType < kMaxType; iType++)
354 {
eeb769e2 355 settings[iSetting][iType] = on;
356 }
6d7793cf 357 AliDebug(3, Form("printing of %s %sabled for all types", settingNames[iSetting], ((on) ? "en" : "dis")));
eeb769e2 358 }
359
6d7793cf 360 for (Int_t iType = kFatal; iType < kMaxType; iType++)
361 {
eeb769e2 362 TString nameType = name + "." + &typeNames[iType][1];
6d7793cf 363
364 if (gEnv->Defined(nameType))
365 {
eeb769e2 366 Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
367 settings[iSetting][iType] = on;
6d7793cf 368 AliDebug(3, Form("printing of %s %sabled for type %s", settingNames[iSetting], ((on) ? "en" : "dis"), typeNames[iType]));
eeb769e2 369 }
370 }
371 }
45fa0297 372
373 // repetition of messages
6d7793cf 374 if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions"))
375 {
45fa0297 376 Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
377 fPrintRepetitions = on;
6d7793cf 378 AliDebug(3, Form("printing of message repetitions %sabled", ((on) ? "en" : "dis")));
45fa0297 379 }
eeb769e2 380}
381
382
6ab674bd 383//_____________________________________________________________________________
384void 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
6d7793cf 389 switch (level)
390 {
6ab674bd 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
6d7793cf 407// DEPRECATED: USE A CONFIGURATION FILE INSTEAD
6ab674bd 408//_____________________________________________________________________________
409void AliLog::EnableDebug(Bool_t enabled)
410{
411// enable or disable debug output
412
413 fgDebugEnabled = enabled;
414}
415
416//_____________________________________________________________________________
44ce6bbe 417void AliLog::SetGlobalLogLevel(EType_t type)
6ab674bd 418{
419// set the global debug level
420
6d7793cf 421 // TO BE DELETED
6ab674bd 422 if (!fgInstance) new AliLog;
423 fgInstance->fGlobalLogLevel = type;
424}
425
426//_____________________________________________________________________________
427Int_t AliLog::GetGlobalLogLevel()
428{
429// get the global debug level
430
431 if (!fgInstance) new AliLog;
432 return fgInstance->fGlobalLogLevel;
433}
434
435//_____________________________________________________________________________
436void 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//_____________________________________________________________________________
446Int_t AliLog::GetGlobalDebugLevel()
447{
448// get the global debug level
449
450 if (!fgInstance) new AliLog;
451 return fgInstance->fGlobalLogLevel - kDebugOffset;
452}
453
454//_____________________________________________________________________________
455void 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//_____________________________________________________________________________
472void 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//_____________________________________________________________________________
483void 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//_____________________________________________________________________________
500void 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//_____________________________________________________________________________
512void 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//_____________________________________________________________________________
44ce6bbe 524void AliLog::SetStandardOutput(EType_t type)
6ab674bd 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//_____________________________________________________________________________
535void 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//_____________________________________________________________________________
44ce6bbe 547void AliLog::SetErrorOutput(EType_t type)
6ab674bd 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//_____________________________________________________________________________
558void 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++) {
051599bf 564 if ((fgInstance->fOutputTypes[iType] == 2) &&
6ab674bd 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;
eeb769e2 571 fgInstance->fOutputStreams[iType] = NULL;
6ab674bd 572 }
573}
574
575//_____________________________________________________________________________
44ce6bbe 576void AliLog::SetFileOutput(EType_t type, const char* fileName)
6ab674bd 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;
051599bf 582 if ((fgInstance->fOutputTypes[type] == 2) &&
6ab674bd 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;
eeb769e2 589 fgInstance->fOutputStreams[type] = NULL;
6ab674bd 590}
591
592//_____________________________________________________________________________
593void 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 }
eeb769e2 604 if (closeFile) {
605 fclose(fOutputFiles[type]);
1948744e 606 ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
607 stream->close();
eeb769e2 608 delete fOutputStreams[type];
609 }
6ab674bd 610 }
611 fOutputFiles[type] = NULL;
eeb769e2 612 fOutputStreams[type] = NULL;
6ab674bd 613 fFileNames[type] = "";
614 fOutputTypes[type] = 0;
615}
616
617//_____________________________________________________________________________
618FILE* AliLog::GetOutputStream(Int_t type)
619{
620// get the output stream for the given type of messages
621
eeb769e2 622 if (type > kDebug) type = kDebug;
6ab674bd 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;
1948744e 628 ostream* stream = NULL;
6ab674bd 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];
eeb769e2 635 stream = fOutputStreams[iType];
6ab674bd 636 break;
637 }
638 }
eeb769e2 639 if (!file) {
640 file = fopen(fFileNames[type], "a");
641 stream = new ofstream(fFileNames[type], ios::app);
642 }
6ab674bd 643 }
644 fOutputFiles[type] = file;
eeb769e2 645 fOutputStreams[type] = stream;
6ab674bd 646 if (!file) CloseFile(type);
647 }
648 if (fOutputFiles[type]) return fOutputFiles[type];
649 }
650
651 return stdout;
652}
653
654//_____________________________________________________________________________
655void 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]);
eeb769e2 663 fgInstance->fOutputStreams[iType]->flush();
6ab674bd 664 }
665 }
666 fflush(stderr);
667 fflush(stdout);
668}
669
670
671//_____________________________________________________________________________
672void AliLog::SetHandleRootMessages(Bool_t on)
673{
674// enable or disable the handling of messages form root
675
45fa0297 676 if (!fgInstance) new AliLog;
6ab674bd 677 if (on) {
678 SetErrorHandler(RootErrorHandler);
679 } else {
680 SetErrorHandler(DefaultErrorHandler);
681 }
682}
683
684
685//_____________________________________________________________________________
686void 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//_____________________________________________________________________________
44ce6bbe 697void AliLog::SetPrintType(EType_t type, Bool_t on)
6ab674bd 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//_____________________________________________________________________________
707void 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//_____________________________________________________________________________
44ce6bbe 718void AliLog::SetPrintModule(EType_t type, Bool_t on)
6ab674bd 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//_____________________________________________________________________________
728void 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//_____________________________________________________________________________
44ce6bbe 739void AliLog::SetPrintScope(EType_t type, Bool_t on)
6ab674bd 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//_____________________________________________________________________________
750void 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//_____________________________________________________________________________
44ce6bbe 762void AliLog::SetPrintLocation(EType_t type, Bool_t on)
6ab674bd 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
45fa0297 773//_____________________________________________________________________________
774void 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
6ab674bd 785//_____________________________________________________________________________
c4cb6153 786void AliLog::WriteToFile(const char* name, Int_t option)
6ab674bd 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//_____________________________________________________________________________
796UInt_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;
21bf76e1 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 }
6ab674bd 809 return fgInstance->fGlobalLogLevel;
810}
811
812//_____________________________________________________________________________
813Int_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
eeb769e2 821//_____________________________________________________________________________
822void 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
45fa0297 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
eeb769e2 859 FILE* stream = GetOutputStream(type);
860 static const char* typeNames[kMaxType] =
861 {"Fatal", "Error", "Warning", "Info", "Debug"};
862
863 if (fPrintType[type]) {
1948744e 864 PrintString(type, stream, "%c-", typeNames[type][0]);
eeb769e2 865 }
eeb769e2 866 if (fPrintModule[type] && module) {
1948744e 867 PrintString(type, stream, "%s/", module);
eeb769e2 868 }
869 if (fPrintScope[type] && className) {
1948744e 870 PrintString(type, stream, "%s::", className);
eeb769e2 871 }
872 if (message) {
1948744e 873 PrintString(type, stream, "%s: %s", function, message);
eeb769e2 874 } else {
1948744e 875 PrintString(type, stream, "%s", function);
eeb769e2 876 }
877 if (fPrintLocation[type] && file) {
1948744e 878 PrintString(type, stream, " (%s:%.0d)", file, line);
eeb769e2 879 }
880 if (message) {
1948744e 881 PrintString(type, stream, "\n");
eeb769e2 882 } else {
1948744e 883 PrintString(type, stream, ": ");
eeb769e2 884 }
1948744e 885 if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
eeb769e2 886}
887
45fa0297 888//_____________________________________________________________________________
889void AliLog::PrintRepetitions()
890{
891// print number of repetitions
892
1948744e 893 PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n",
45fa0297 894 fRepetitions, (fRepetitions > 1) ? "s" : "");
1948744e 895 if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
45fa0297 896}
897
6ab674bd 898//_____________________________________________________________________________
899void 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
6ab674bd 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)) {
eeb769e2 913 fgInstance->PrintMessage(type, message,
914 module, className, function, file, line);
6ab674bd 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//_____________________________________________________________________________
930void 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}
eeb769e2 940
941
942//_____________________________________________________________________________
44ce6bbe 943Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module,
eeb769e2 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//_____________________________________________________________________________
44ce6bbe 955Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
eeb769e2 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//_____________________________________________________________________________
44ce6bbe 967Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
eeb769e2 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
17ef8526 985 if(!freopen("/dev/null", "a", stream)) AliWarning("Cannot reopen /dev/null");
eeb769e2 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
17ef8526 991 if(!freopen(fFileNames[type], "a", stream)) AliWarning(Form("Cannot reopen %s",fFileNames[type].Data()));
1948744e 992 } else if (fOutputTypes[type] == 3) { // external C++ stream
993 // redirection is not possible for external C++ streams
eeb769e2 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//_____________________________________________________________________________
1006void AliLog::RestoreStdout(Int_t original)
1007{
1008// restore the standard output
1009
1010 fflush(stdout);
1011 dup2(original, fileno(stdout));
b6f30bf9 1012 close(original);
eeb769e2 1013}
1014
1015//_____________________________________________________________________________
1016void AliLog::RestoreStderr(Int_t original)
1017{
1018// restore the standard error output
1019
1020 fflush(stderr);
1021 dup2(original, fileno(stderr));
b6f30bf9 1022 close(original);
eeb769e2 1023}
1024
1025
1026//_____________________________________________________________________________
44ce6bbe 1027ostream& AliLog::Stream(EType_t type, UInt_t level,
eeb769e2 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//_____________________________________________________________________________
44ce6bbe 1039ostream& AliLog::GetStream(EType_t type, UInt_t level,
eeb769e2 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];
1948744e 1062 } else if (fOutputTypes[type] == 3) {
1063 return *fOutputStreams[type];
eeb769e2 1064 }
1065
1066 return nullStream;
1067}
1068
1948744e 1069void 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
1080void 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
1097void 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
1106void 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
1118void 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);
a7a801dc 1142#else
1143#warning definition of R__VA_COPY has disappeared
1948744e 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}