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