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