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