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