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