]> git.uio.no Git - u/mrichter/AliRoot.git/blame - STEER/AliLog.cxx
New event tag classes (P.Christakoglou)
[u/mrichter/AliRoot.git] / STEER / AliLog.cxx
CommitLineData
6ab674bd 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15
16/* $Id$ */
17
18///////////////////////////////////////////////////////////////////////////////
19// //
20// class for logging debug, info and error messages //
21// //
22// The AliLog class is a singleton class. It allows to steer the output //
23// level and output streams for different types of messages via static //
24// methods. //
25// //
26// It also handles the messages produces by the preprocessor macros defined //
27// in the header file: AliDebug, AliInfo, AliWarning, AliError, AliFatal. //
28// //
29// More details about the message logging can be found on the ALICE Offline //
30// web page. //
31// //
32///////////////////////////////////////////////////////////////////////////////
33
30ae1e2b 34#include <strings.h>
eeb769e2 35#include <Riostream.h>
6ab674bd 36#include <TError.h>
37#include <TNamed.h>
38#include <TSystem.h>
eeb769e2 39#include <TEnv.h>
6ab674bd 40
41#include "AliLog.h"
42
43ClassImp(AliLog)
44
45
46AliLog* AliLog::fgInstance = NULL;
47
48Bool_t AliLog::fgDebugEnabled = kTRUE;
49
50
51//_____________________________________________________________________________
52AliLog::AliLog() :
53 TObject(),
54 fGlobalLogLevel(kInfo),
55 fModuleDebugLevels(),
45fa0297 56 fClassDebugLevels(),
57 fPrintRepetitions(kTRUE),
58 fRepetitions(0),
59 fLastType(0),
60 fLastMessage(),
61 fLastModule(),
62 fLastClassName(),
63 fLastFunction(),
64 fLastFile(),
65 fLastLine(0)
6ab674bd 66{
67// default constructor: set default values
68
69 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
70 fOutputTypes[iType] = 0;
71 fFileNames[iType] = "";
72 fOutputFiles[iType] = NULL;
eeb769e2 73 fOutputStreams[iType] = NULL;
6ab674bd 74
75 fPrintType[iType] = kTRUE;
76 fPrintModule[iType] = kFALSE;
77 fPrintScope[iType] = kTRUE;
78 fPrintLocation[iType] = (iType == kDebug);
79 }
80
6ab674bd 81 // replace the previous instance by this one
82 if (fgInstance) delete fgInstance;
83 fgInstance = this;
eeb769e2 84
45fa0297 85 SetHandleRootMessages(kTRUE);
86
eeb769e2 87 // read the .rootrc settings
88 ReadEnvSettings();
6ab674bd 89}
90
91//_____________________________________________________________________________
92AliLog::~AliLog()
93{
94// destructor: clean up and reset instance pointer
95
45fa0297 96 if (fRepetitions > 0) PrintRepetitions();
97
6ab674bd 98 for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++) {
99 if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
100 }
101 fClassDebugLevels.Delete();
102 for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++) {
103 if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
104 }
105 fClassDebugLevels.Delete();
106
107 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
108 CloseFile(iType);
109 }
110 fflush(stderr);
111 fflush(stdout);
112
113 fgInstance = NULL;
114}
115
116//_____________________________________________________________________________
117AliLog::AliLog(const AliLog& log) :
90e48c0c 118 TObject(log),
119 fGlobalLogLevel(log.fGlobalLogLevel),
120 fModuleDebugLevels(log.fModuleDebugLevels),
121 fClassDebugLevels(log.fClassDebugLevels),
122 fPrintRepetitions(log.fPrintRepetitions),
123 fRepetitions(log.fRepetitions),
124 fLastType(log.fLastType),
125 fLastMessage(log.fLastMessage),
126 fLastModule(log.fLastModule),
127 fLastClassName(log.fLastClassName),
128 fLastFunction(log.fLastFunction),
129 fLastFile(log.fLastFile),
130 fLastLine(log.fLastLine)
6ab674bd 131{
132// copy constructor
133
134 Fatal("AliLog", "copy constructor not implemented");
135}
136
137//_____________________________________________________________________________
138AliLog& AliLog::operator = (const AliLog& /*log*/)
139{
140// assignment operator
141
142 Fatal("operator =", "assignment operator not implemented");
143 return *this;
144}
145
146
eeb769e2 147//_____________________________________________________________________________
148void AliLog::ReadEnvSettings()
149{
150// load settings from the root configuration file (.rootrc)
151// and from environment variables
152
153 static const char* typeNames[kMaxType] =
154 {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
155
156 // debug en- or disabling
157 if (gSystem->Getenv("LOG_NO_DEBUG")) {
158 fgDebugEnabled = kFALSE;
159 } else if (gEnv->Defined("AliRoot.AliLog.EnableDebug")) {
160 fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug",
161 fgDebugEnabled);
162 AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
163 }
164
165 // global log level
166 if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel")) {
167 const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
168 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
169 if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
170 }
171 AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
172 }
173
174 // global debug level
175 if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel")) {
176 Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel",
177 Int_t(fGlobalLogLevel - kDebugOffset));
178 if (level < -kDebugOffset) level = kDebugOffset;
179 fGlobalLogLevel = kDebugOffset + level;
180 AliDebug(3, Form("global debug level set to %d",
181 fGlobalLogLevel - kDebugOffset));
182 }
183
184 // module debug level
185 if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel")) {
186 TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
187 char* p = const_cast<char*>(levels.Data());
188 while (const char* module = strtok(p, " ")) {
189 p = NULL;
190 char* pos = index(module, ':');
191 if (!pos) continue;
192 *(pos++) = '\0';
193 Int_t level = atoi(pos);
194 SetModuleDebugLevel(module, level);
195 AliDebug(3, Form("debug level for module %s set to %d", module, level));
196 }
197 }
198
199 // class debug level
200 if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel")) {
201 TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
202 char* p = const_cast<char*>(levels.Data());
203 while (const char* className = strtok(p, " ")) {
204 p = NULL;
205 char* pos = index(className, ':');
206 if (!pos) continue;
207 *(pos++) = '\0';
208 Int_t level = atoi(pos);
209 SetClassDebugLevel(className, level);
210 AliDebug(3, Form("debug level for class %s set to %d",
211 className, level));
212 }
213 }
214
215 // general output stream
216 if (gEnv->Defined("AliRoot.AliLog.Output")) {
217 TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
218 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) {
219 SetStandardOutput();
220 AliDebug(3, "output stream set to standard output for all types");
221 } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) {
222 SetErrorOutput();
223 AliDebug(3, "output stream set to error output for all types");
224 } else if (!stream.IsNull()) {
225 SetFileOutput(stream);
226 AliDebug(3, Form("output stream set to file %s for all types",
227 stream.Data()));
228 }
229 }
230
231 // individual output streams
232 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
233 TString name("AliRoot.AliLog.Output.");
234 name += &typeNames[iType][1];
235 if (gEnv->Defined(name)) {
236 TString stream = gEnv->GetValue(name, "Standard");
237 if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) {
44ce6bbe 238 SetStandardOutput(EType_t(iType));
eeb769e2 239 AliDebug(3, Form("output stream set to standard output for type %s",
240 typeNames[iType]));
241 } else if (stream.CompareTo("error", TString::kIgnoreCase) == 0) {
44ce6bbe 242 SetErrorOutput(EType_t(iType));
eeb769e2 243 AliDebug(3, Form("output stream set to error output for type %s",
244 typeNames[iType]));
245 } else if (!stream.IsNull()) {
44ce6bbe 246 SetFileOutput(EType_t(iType), stream);
eeb769e2 247 AliDebug(3, Form("output stream set to file %s for type %s",
248 stream.Data(), typeNames[iType]));
249 }
250 }
251 }
252
253 // handling of root error messages
254 if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages")) {
255 Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
256 SetHandleRootMessages(on);
257 AliDebug(3, Form("handling of root messages %sabled",
258 ((on) ? "en" : "dis")));
259 }
260
261 // printout settings
262 static const char* settingNames[4] =
263 {"Type", "Module", "Scope", "Location"};
264 Bool_t* settings[] =
265 {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
266 for (Int_t iSetting = 0; iSetting < 4; iSetting++) {
267 TString name("AliRoot.AliLog.Print");
268 name += settingNames[iSetting];
269 if (gEnv->Defined(name)) {
270 Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
271 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
272 settings[iSetting][iType] = on;
273 }
274 AliDebug(3, Form("printing of %s %sabled for all types",
275 settingNames[iSetting], ((on) ? "en" : "dis")));
276 }
277
278 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
279 TString nameType = name + "." + &typeNames[iType][1];
280 if (gEnv->Defined(nameType)) {
281 Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
282 settings[iSetting][iType] = on;
283 AliDebug(3, Form("printing of %s %sabled for type %s",
284 settingNames[iSetting], ((on) ? "en" : "dis"),
285 typeNames[iType]));
286 }
287 }
288 }
45fa0297 289
290 // repetition of messages
291 if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions")) {
292 Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
293 fPrintRepetitions = on;
294 AliDebug(3, Form("printing of message repetitions %sabled",
295 ((on) ? "en" : "dis")));
296 }
eeb769e2 297}
298
299
6ab674bd 300//_____________________________________________________________________________
301void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
302 const char* location, const char* message)
303{
304// new error handler for messages from root
305
306 switch (level) {
307 case ::kFatal : level = kFatal; break;
308 case ::kSysError :
309 DefaultErrorHandler(level, abort, location, message);
310 return;
311 case ::kBreak :
312 DefaultErrorHandler(level, abort, location, message);
313 return;
314 case ::kError : level = kError; break;
315 case ::kWarning : level = kWarning; break;
316 case ::kInfo : level = kInfo; break;
317 default : level = kDebug; break;
318 }
319 AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
320}
321
322
323//_____________________________________________________________________________
324void AliLog::EnableDebug(Bool_t enabled)
325{
326// enable or disable debug output
327
328 fgDebugEnabled = enabled;
329}
330
331//_____________________________________________________________________________
44ce6bbe 332void AliLog::SetGlobalLogLevel(EType_t type)
6ab674bd 333{
334// set the global debug level
335
336 if (!fgInstance) new AliLog;
337 fgInstance->fGlobalLogLevel = type;
338}
339
340//_____________________________________________________________________________
341Int_t AliLog::GetGlobalLogLevel()
342{
343// get the global debug level
344
345 if (!fgInstance) new AliLog;
346 return fgInstance->fGlobalLogLevel;
347}
348
349//_____________________________________________________________________________
350void AliLog::SetGlobalDebugLevel(Int_t level)
351{
352// set the global debug level
353
354 if (!fgInstance) new AliLog;
355 if (level < -kDebugOffset) level = -kDebugOffset;
356 fgInstance->fGlobalLogLevel = kDebugOffset + level;
357}
358
359//_____________________________________________________________________________
360Int_t AliLog::GetGlobalDebugLevel()
361{
362// get the global debug level
363
364 if (!fgInstance) new AliLog;
365 return fgInstance->fGlobalLogLevel - kDebugOffset;
366}
367
368//_____________________________________________________________________________
369void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
370{
371// set the debug level for the given module
372
373 if (!module) return;
374 if (!fgInstance) new AliLog;
375 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
376 if (!obj) {
377 obj = new TNamed(module, module);
378 fgInstance->fModuleDebugLevels.Add(obj);
379 }
380 level += kDebugOffset;
381 if (level < kFatal) level = kFatal;
382 obj->SetUniqueID(level);
383}
384
385//_____________________________________________________________________________
386void AliLog::ClearModuleDebugLevel(const char* module)
387{
388// remove the setting of the debug level for the given module
389
390 if (!module) return;
391 if (!fgInstance) new AliLog;
392 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
393 if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
394}
395
396//_____________________________________________________________________________
397void AliLog::SetClassDebugLevel(const char* className, Int_t level)
398{
399// set the debug level for the given class
400
401 if (!className) return;
402 if (!fgInstance) new AliLog;
403 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
404 if (!obj) {
405 obj = new TNamed(className, className);
406 fgInstance->fClassDebugLevels.Add(obj);
407 }
408 level += kDebugOffset;
409 if (level < kFatal) level = kFatal;
410 obj->SetUniqueID(level);
411}
412
413//_____________________________________________________________________________
414void AliLog::ClearClassDebugLevel(const char* className)
415{
416// remove the setting of the debug level for the given class
417
418 if (!className) return;
419 if (!fgInstance) new AliLog;
420 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
421 if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
422}
423
424
425//_____________________________________________________________________________
426void AliLog::SetStandardOutput()
427{
428// write all log messages to the standard output (stdout)
429
430 if (!fgInstance) new AliLog;
431 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
432 fgInstance->CloseFile(iType);
433 fgInstance->fOutputTypes[iType] = 0;
434 }
435}
436
437//_____________________________________________________________________________
44ce6bbe 438void AliLog::SetStandardOutput(EType_t type)
6ab674bd 439{
440// write log messages of the given type to the standard output (stdout)
441
442 if ((type < kFatal) || (type >= kMaxType)) return;
443 if (!fgInstance) new AliLog;
444 fgInstance->CloseFile(type);
445 fgInstance->fOutputTypes[type] = 0;
446}
447
448//_____________________________________________________________________________
449void AliLog::SetErrorOutput()
450{
451// write all log messages to the error output (stderr)
452
453 if (!fgInstance) new AliLog;
454 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
455 fgInstance->CloseFile(iType);
456 fgInstance->fOutputTypes[iType] = 1;
457 }
458}
459
460//_____________________________________________________________________________
44ce6bbe 461void AliLog::SetErrorOutput(EType_t type)
6ab674bd 462{
463// write log messages of the given type to the error output (stderr)
464
465 if ((type < kFatal) || (type >= kMaxType)) return;
466 if (!fgInstance) new AliLog;
467 fgInstance->CloseFile(type);
468 fgInstance->fOutputTypes[type] = 1;
469}
470
471//_____________________________________________________________________________
472void AliLog::SetFileOutput(const char* fileName)
473{
474// write all log messages to the given file
475
476 if (!fgInstance) new AliLog;
477 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
051599bf 478 if ((fgInstance->fOutputTypes[iType] == 2) &&
6ab674bd 479 (fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
480 fgInstance->CloseFile(iType);
481 }
482 fgInstance->fOutputTypes[iType] = 2;
483 fgInstance->fFileNames[iType] = fileName;
484 fgInstance->fOutputFiles[iType] = NULL;
eeb769e2 485 fgInstance->fOutputStreams[iType] = NULL;
6ab674bd 486 }
487}
488
489//_____________________________________________________________________________
44ce6bbe 490void AliLog::SetFileOutput(EType_t type, const char* fileName)
6ab674bd 491{
492// write log messages of the given type to the given file
493
494 if ((type < kFatal) || (type >= kMaxType)) return;
495 if (!fgInstance) new AliLog;
051599bf 496 if ((fgInstance->fOutputTypes[type] == 2) &&
6ab674bd 497 (fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
498 fgInstance->CloseFile(type);
499 }
500 fgInstance->fOutputTypes[type] = 2;
501 fgInstance->fFileNames[type] = fileName;
502 fgInstance->fOutputFiles[type] = NULL;
eeb769e2 503 fgInstance->fOutputStreams[type] = NULL;
6ab674bd 504}
505
506//_____________________________________________________________________________
507void AliLog::CloseFile(Int_t type)
508{
509// close the file for the given type if needed
510
511 if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
512 Bool_t closeFile = kTRUE;
513 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
514 if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
515 closeFile = kFALSE;
516 }
517 }
eeb769e2 518 if (closeFile) {
519 fclose(fOutputFiles[type]);
520 fOutputStreams[type]->close();
521 delete fOutputStreams[type];
522 }
6ab674bd 523 }
524 fOutputFiles[type] = NULL;
eeb769e2 525 fOutputStreams[type] = NULL;
6ab674bd 526 fFileNames[type] = "";
527 fOutputTypes[type] = 0;
528}
529
530//_____________________________________________________________________________
531FILE* AliLog::GetOutputStream(Int_t type)
532{
533// get the output stream for the given type of messages
534
eeb769e2 535 if (type > kDebug) type = kDebug;
6ab674bd 536 if (fOutputTypes[type] == 0) return stdout;
537 else if (fOutputTypes[type] == 1) return stderr;
538 else if (fOutputTypes[type] == 2) {
539 if (!fOutputFiles[type]) {
540 FILE* file = NULL;
eeb769e2 541 ofstream* stream = NULL;
6ab674bd 542 if (!fFileNames[type].IsNull()) {
543 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
544 if ((iType != type) &&
545 (fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
546 fOutputFiles[iType]) {
547 file = fOutputFiles[iType];
eeb769e2 548 stream = fOutputStreams[iType];
6ab674bd 549 break;
550 }
551 }
eeb769e2 552 if (!file) {
553 file = fopen(fFileNames[type], "a");
554 stream = new ofstream(fFileNames[type], ios::app);
555 }
6ab674bd 556 }
557 fOutputFiles[type] = file;
eeb769e2 558 fOutputStreams[type] = stream;
6ab674bd 559 if (!file) CloseFile(type);
560 }
561 if (fOutputFiles[type]) return fOutputFiles[type];
562 }
563
564 return stdout;
565}
566
567//_____________________________________________________________________________
568void AliLog::Flush()
569{
570// flush the output streams
571
572 if (!fgInstance) new AliLog;
573 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
574 if (fgInstance->fOutputFiles[iType]) {
575 fflush(fgInstance->fOutputFiles[iType]);
eeb769e2 576 fgInstance->fOutputStreams[iType]->flush();
6ab674bd 577 }
578 }
579 fflush(stderr);
580 fflush(stdout);
581}
582
583
584//_____________________________________________________________________________
585void AliLog::SetHandleRootMessages(Bool_t on)
586{
587// enable or disable the handling of messages form root
588
45fa0297 589 if (!fgInstance) new AliLog;
6ab674bd 590 if (on) {
591 SetErrorHandler(RootErrorHandler);
592 } else {
593 SetErrorHandler(DefaultErrorHandler);
594 }
595}
596
597
598//_____________________________________________________________________________
599void AliLog::SetPrintType(Bool_t on)
600{
601// switch on or off the printing of the message type for all message types
602
603 if (!fgInstance) new AliLog;
604 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
605 fgInstance->fPrintType[iType] = on;
606 }
607}
608
609//_____________________________________________________________________________
44ce6bbe 610void AliLog::SetPrintType(EType_t type, Bool_t on)
6ab674bd 611{
612// switch on or off the printing of the message type for the given message type
613
614 if ((type < kFatal) || (type >= kMaxType)) return;
615 if (!fgInstance) new AliLog;
616 fgInstance->fPrintType[type] = on;
617}
618
619//_____________________________________________________________________________
620void AliLog::SetPrintModule(Bool_t on)
621{
622// switch on or off the printing of the module for all message types
623
624 if (!fgInstance) new AliLog;
625 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
626 fgInstance->fPrintModule[iType] = on;
627 }
628}
629
630//_____________________________________________________________________________
44ce6bbe 631void AliLog::SetPrintModule(EType_t type, Bool_t on)
6ab674bd 632{
633// switch on or off the printing of the module for the given message type
634
635 if ((type < kFatal) || (type >= kMaxType)) return;
636 if (!fgInstance) new AliLog;
637 fgInstance->fPrintModule[type] = on;
638}
639
640//_____________________________________________________________________________
641void AliLog::SetPrintScope(Bool_t on)
642{
643// switch on or off the printing of the scope/class name for all message types
644
645 if (!fgInstance) new AliLog;
646 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
647 fgInstance->fPrintScope[iType] = on;
648 }
649}
650
651//_____________________________________________________________________________
44ce6bbe 652void AliLog::SetPrintScope(EType_t type, Bool_t on)
6ab674bd 653{
654// switch on or off the printing of the scope/class name
655// for the given message type
656
657 if ((type < kFatal) || (type >= kMaxType)) return;
658 if (!fgInstance) new AliLog;
659 fgInstance->fPrintScope[type] = on;
660}
661
662//_____________________________________________________________________________
663void AliLog::SetPrintLocation(Bool_t on)
664{
665// switch on or off the printing of the file name and line number
666// for all message types
667
668 if (!fgInstance) new AliLog;
669 for (Int_t iType = kFatal; iType < kMaxType; iType++) {
670 fgInstance->fPrintLocation[iType] = on;
671 }
672}
673
674//_____________________________________________________________________________
44ce6bbe 675void AliLog::SetPrintLocation(EType_t type, Bool_t on)
6ab674bd 676{
677// switch on or off the printing of the file name and line number
678// for the given message type
679
680 if ((type < kFatal) || (type >= kMaxType)) return;
681 if (!fgInstance) new AliLog;
682 fgInstance->fPrintLocation[type] = on;
683}
684
685
45fa0297 686//_____________________________________________________________________________
687void AliLog::SetPrintRepetitions(Bool_t on)
688{
689// switch on or off the printing of the number of repetitions of a message
690// instead of repeating the same message
691
692 if (!fgInstance) new AliLog;
693 if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
694 fgInstance->fPrintRepetitions = on;
695}
696
697
6ab674bd 698//_____________________________________________________________________________
c4cb6153 699void AliLog::WriteToFile(const char* name, Int_t option)
6ab674bd 700{
701// write the log object with the given name and option to the current file
702
703 if (!fgInstance) new AliLog;
704 fgInstance->TObject::Write(name, option);
705}
706
707
708//_____________________________________________________________________________
709UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
710{
711// get the logging level for the given module and class
712
713 if (!fgInstance) new AliLog;
21bf76e1 714 if (className) {
715 TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
716 if (obj) return obj->GetUniqueID();
717 }
718 if (module) {
719 TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
720 if (obj) return obj->GetUniqueID();
721 }
6ab674bd 722 return fgInstance->fGlobalLogLevel;
723}
724
725//_____________________________________________________________________________
726Int_t AliLog::GetDebugLevel(const char* module, const char* className)
727{
728// get the debug level for the given module and class
729
730 if (!fgInstance) new AliLog;
731 return fgInstance->GetLogLevel(module, className) - kDebugOffset;
732}
733
eeb769e2 734//_____________________________________________________________________________
735void AliLog::PrintMessage(UInt_t type, const char* message,
736 const char* module, const char* className,
737 const char* function, const char* file, Int_t line)
738{
739// print the given message
740
45fa0297 741 // don't print the message if it is repeated
742 if (fPrintRepetitions &&
743 (fLastType == type) &&
744 (message && (fLastMessage.CompareTo(message) == 0)) &&
745 ((module && (fLastModule.CompareTo(module) == 0)) ||
746 (!module && fLastModule.IsNull())) &&
747 ((className && (fLastClassName.CompareTo(className) == 0)) ||
748 (!className && fLastClassName.IsNull())) &&
749 ((function && (fLastFunction.CompareTo(function) == 0)) ||
750 (!function && fLastFunction.IsNull()))&&
751 ((file && (fLastFile.CompareTo(file) == 0)) ||
752 (!file && fLastFile.IsNull())) &&
753 (fLastLine == line)) {
754 fRepetitions++;
755 return;
756 }
757
758 // print number of repetitions
759 if (fRepetitions > 0) PrintRepetitions();
760
761 // remember this message
762 fRepetitions = 0;
763 fLastType = type;
764 fLastMessage = message;
765 fLastModule = module;
766 fLastClassName = className;
767 fLastFunction = function;
768 fLastFile = file;
769 fLastLine = line;
770
771 // print the message
eeb769e2 772 FILE* stream = GetOutputStream(type);
773 static const char* typeNames[kMaxType] =
774 {"Fatal", "Error", "Warning", "Info", "Debug"};
775
776 if (fPrintType[type]) {
e709b087 777 fprintf(stream, "%c-", typeNames[type][0]);
eeb769e2 778 }
eeb769e2 779 if (fPrintModule[type] && module) {
780 fprintf(stream, "%s/", module);
781 }
782 if (fPrintScope[type] && className) {
783 fprintf(stream, "%s::", className);
784 }
785 if (message) {
e709b087 786 fprintf(stream, "%s: %s", function, message);
eeb769e2 787 } else {
e709b087 788 fprintf(stream, "%s", function);
eeb769e2 789 }
790 if (fPrintLocation[type] && file) {
791 fprintf(stream, " (%s:%.0d)", file, line);
792 }
793 if (message) {
794 fprintf(stream, "\n");
795 } else {
796 fprintf(stream, ": ");
797 }
798}
799
45fa0297 800//_____________________________________________________________________________
801void AliLog::PrintRepetitions()
802{
803// print number of repetitions
804
805 fprintf(GetOutputStream(fLastType), " <message repeated %d time%s>\n",
806 fRepetitions, (fRepetitions > 1) ? "s" : "");
807}
808
6ab674bd 809//_____________________________________________________________________________
810void AliLog::Message(UInt_t level, const char* message,
811 const char* module, const char* className,
812 const char* function, const char* file, Int_t line)
813{
814// print a log message
815
816 if (!fgInstance) new AliLog;
817
818 // get the message type
6ab674bd 819 UInt_t type = level;
820 if (type >= kMaxType) type = kMaxType - 1;
821
822 // print the message if the debug level allows
823 if (level <= fgInstance->GetLogLevel(module, className)) {
eeb769e2 824 fgInstance->PrintMessage(type, message,
825 module, className, function, file, line);
6ab674bd 826 }
827
828 // abort in case of a fatal message
829 if (type == kFatal) {
830 delete fgInstance;
831 if (gSystem) {
832 gSystem->StackTrace();
833 gSystem->Abort();
834 } else {
835 ::abort();
836 }
837 }
838}
839
840//_____________________________________________________________________________
841void AliLog::Debug(UInt_t level, const char* message,
842 const char* module, const char* className,
843 const char* function, const char* file, Int_t line)
844{
845// print a debug message
846
847 if (level == 0) level = 1;
848 level += kDebugOffset;
849 Message(level, message, module, className, function, file, line);
850}
eeb769e2 851
852
853//_____________________________________________________________________________
44ce6bbe 854Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module,
eeb769e2 855 const char* className, const char* function,
856 const char* file, Int_t line, Bool_t print)
857{
858// redirect the standard output to the stream of the given type
859
860 if (!fgInstance) new AliLog;
861 return fgInstance->RedirectTo(stdout, type, level, module, className,
862 function, file, line, print);
863}
864
865//_____________________________________________________________________________
44ce6bbe 866Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
eeb769e2 867 const char* className, const char* function,
868 const char* file, Int_t line, Bool_t print)
869{
870// redirect the standard error output to the stream of the given type
871
872 if (!fgInstance) new AliLog;
873 return fgInstance->RedirectTo(stderr, type, level, module, className,
874 function, file, line, print);
875}
876
877//_____________________________________________________________________________
44ce6bbe 878Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
eeb769e2 879 const char* module, const char* className,
880 const char* function, const char* file, Int_t line,
881 Bool_t print)
882{
883// redirect the standard (error) output stream to the stream of the given type
884
885 // get the original file descriptor to be able to restore it later
886 Int_t original = dup(fileno(stream));
887 fflush(stream);
888
889 // flush the stream of the selected type
890 FILE* newStream = GetOutputStream(type);
891 fflush(newStream);
892
893 // redirect stream
894 if ((type == kDebug) && (level > 0)) level--;
895 if (type + level > GetLogLevel(module, className)) { // /dev/null
896 freopen("/dev/null", "a", stream);
897 } else if (fOutputTypes[type] == 0) { // stdout
898 if (stream != stdout) dup2(fileno(stdout), fileno(stream));
899 } else if (fOutputTypes[type] == 1) { // stderr
900 if (stream != stderr) dup2(fileno(stderr), fileno(stream));
901 } else if (fOutputTypes[type] == 2) { // file
902 freopen(fFileNames[type], "a", stream);
903 }
904
905 // print information
906 if (print) {
907 PrintMessage(type, NULL, module, className, function, file, line);
908 fflush(newStream);
909 }
910
911 return original;
912}
913
914//_____________________________________________________________________________
915void AliLog::RestoreStdout(Int_t original)
916{
917// restore the standard output
918
919 fflush(stdout);
920 dup2(original, fileno(stdout));
b6f30bf9 921 close(original);
eeb769e2 922}
923
924//_____________________________________________________________________________
925void AliLog::RestoreStderr(Int_t original)
926{
927// restore the standard error output
928
929 fflush(stderr);
930 dup2(original, fileno(stderr));
b6f30bf9 931 close(original);
eeb769e2 932}
933
934
935//_____________________________________________________________________________
44ce6bbe 936ostream& AliLog::Stream(EType_t type, UInt_t level,
eeb769e2 937 const char* module, const char* className,
938 const char* function, const char* file, Int_t line)
939{
940// get the stream object for the given output type
941
942 if (!fgInstance) new AliLog;
943 return fgInstance->GetStream(type, level, module, className,
944 function, file, line);
945}
946
947//_____________________________________________________________________________
44ce6bbe 948ostream& AliLog::GetStream(EType_t type, UInt_t level,
eeb769e2 949 const char* module, const char* className,
950 const char* function, const char* file, Int_t line)
951{
952// get the stream object for the given output type
953
954 if ((type == kDebug) && (level > 0)) level--;
955 Bool_t noOutput = (type + level > GetLogLevel(module, className));
956
957 if (!noOutput) {
958 PrintMessage(type, NULL, module, className, function, file, line);
959 }
960 fflush(GetOutputStream(type));
961
962 static ofstream nullStream("/dev/null");
963 if (noOutput) {
964 return nullStream;
965 } else if (fOutputTypes[type] == 0) {
966 return cout;
967 } else if (fOutputTypes[type] == 1) {
968 return cerr;
969 } else if (fOutputTypes[type] == 2) {
970 return *fOutputStreams[type];
971 }
972
973 return nullStream;
974}
975