#include <cstdlib>
#include <strings.h>
#include <Riostream.h>
#include <TError.h>
#include <TNamed.h>
#include <TSystem.h>
#include <TEnv.h>
#include <TArrayC.h>
#include <Varargs.h> // platform independent definition of va_copy
#include "AliLog.h"
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdexcept>
#include <functional>
using std::endl;
using std::cout;
using std::ostream;
using std::cerr;
using std::ofstream;
using std::ios;
ClassImp(AliLog)
AliLog* AliLog::fgInstance = NULL;
Bool_t AliLog::fgDebugEnabled = kTRUE;
Bool_t AliLog::fgCoreEnabled = kFALSE;
AliLog *AliLog::GetRootLogger()
{
if (fgInstance == NULL)
{
fgInstance = new AliLog;
}
return fgInstance;
}
void AliLog::DeleteRootLogger()
{
if (fgInstance != NULL)
{
delete fgInstance;
fgInstance = NULL;
}
}
AliLog::AliLog() :
TObject(),
fGlobalLogLevel(kInfo),
fModuleDebugLevels(),
fClassDebugLevels(),
fPrintRepetitions(kTRUE),
fRepetitions(0),
fLastType(0),
fLastMessage(),
fLastModule(),
fLastClassName(),
fLastFunction(),
fLastFile(),
fLastLine(0)
{
for (Int_t iType = kFatal; iType < kMaxType; iType++)
{
fOutputTypes[iType] = 0;
fFileNames[iType] = "";
fOutputFiles[iType] = NULL;
fOutputStreams[iType] = NULL;
fCallBacks[iType]=NULL;
fPrintType[iType] = kTRUE;
fPrintModule[iType] = kFALSE;
fPrintScope[iType] = kTRUE;
fPrintLocation[iType] = (iType == kDebug);
}
if (fgInstance) delete fgInstance;
fgInstance = this;
SetHandleRootMessages(kTRUE);
ReadEnvSettings();
}
AliLog::~AliLog()
{
if (fRepetitions > 0) PrintRepetitions();
for (Int_t i = 0; i < fModuleDebugLevels.GetEntriesFast(); i++)
{
if (fModuleDebugLevels[i]) fModuleDebugLevels[i]->Delete();
}
fClassDebugLevels.Delete();
for (Int_t i = 0; i < fClassDebugLevels.GetEntriesFast(); i++)
{
if (fClassDebugLevels[i]) fClassDebugLevels[i]->Delete();
}
fClassDebugLevels.Delete();
for (Int_t iType = kFatal; iType < kMaxType; iType++)
{
CloseFile(iType);
}
fflush(stderr);
fflush(stdout);
fgInstance = NULL;
}
AliLog::AliLog(const AliLog& log) :
TObject(log),
fGlobalLogLevel(log.fGlobalLogLevel),
fModuleDebugLevels(log.fModuleDebugLevels),
fClassDebugLevels(log.fClassDebugLevels),
fPrintRepetitions(log.fPrintRepetitions),
fRepetitions(log.fRepetitions),
fLastType(log.fLastType),
fLastMessage(log.fLastMessage),
fLastModule(log.fLastModule),
fLastClassName(log.fLastClassName),
fLastFunction(log.fLastFunction),
fLastFile(log.fLastFile),
fLastLine(log.fLastLine)
{
Fatal("AliLog", "copy constructor not implemented");
}
AliLog& AliLog::operator = (const AliLog& )
{
Fatal("operator =", "assignment operator not implemented");
return *this;
}
void AliLog::ReadEnvSettings()
{
static const char* typeNames[kMaxType] = {"kFatal", "kError", "kWarning", "kInfo", "kDebug"};
if (gSystem->Getenv("LOG_NO_DEBUG"))
{
fgDebugEnabled = kFALSE;
}
else if (gEnv->Defined("AliRoot.AliLog.EnableDebug"))
{
fgDebugEnabled = gEnv->GetValue("AliRoot.AliLog.EnableDebug", fgDebugEnabled);
AliInfo(Form("debug %sabled", ((fgDebugEnabled) ? "en" : "dis")));
}
if (gEnv->Defined("AliRoot.AliLog.GlobalLogLevel"))
{
const char* type = gEnv->GetValue("AliRoot.AliLog.GlobalLogLevel", "");
for (Int_t iType = kFatal; iType < kMaxType; iType++)
{
if (strcmp(type, typeNames[iType]) == 0) fGlobalLogLevel = iType;
}
AliDebug(3, Form("global log level set to %d", fGlobalLogLevel));
}
if (gEnv->Defined("AliRoot.AliLog.GlobalDebugLevel"))
{
Int_t level = gEnv->GetValue("AliRoot.AliLog.GlobalDebugLevel", Int_t(fGlobalLogLevel - kDebugOffset));
if (level < -kDebugOffset) level = kDebugOffset;
fGlobalLogLevel = kDebugOffset + level;
AliDebug(3, Form("global debug level set to %d", fGlobalLogLevel - kDebugOffset));
}
if (gEnv->Defined("AliRoot.AliLog.ModuleDebugLevel"))
{
TString levels = gEnv->GetValue("AliRoot.AliLog.ModuleDebugLevel", "");
char* p = const_cast<char*>(levels.Data());
while (const char* module = strtok(p, " "))
{
p = NULL;
char* pos = const_cast<char*>(index(module, ':'));
if (!pos) continue;
*(pos++) = '\0';
Int_t level = atoi(pos);
SetModuleDebugLevel(module, level);
AliDebug(3, Form("debug level for module %s set to %d", module, level));
}
}
if (gEnv->Defined("AliRoot.AliLog.ClassDebugLevel"))
{
TString levels = gEnv->GetValue("AliRoot.AliLog.ClassDebugLevel", "");
char* p = const_cast<char*>(levels.Data());
while (const char* className = strtok(p, " "))
{
p = NULL;
char* pos = const_cast<char*>(index(className, ':'));
if (!pos) continue;
*(pos++) = '\0';
Int_t level = atoi(pos);
SetClassDebugLevel(className, level);
AliDebug(3, Form("debug level for class %s set to %d", className, level));
}
}
if (gEnv->Defined("AliRoot.AliLog.Output"))
{
TString stream = gEnv->GetValue("AliRoot.AliLog.Output", "Standard");
if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
{
SetStandardOutput();
AliDebug(3, "output stream set to standard output for all types");
}
else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
{
SetErrorOutput();
AliDebug(3, "output stream set to error output for all types");
}
else if (!stream.IsNull())
{
SetFileOutput(stream);
AliDebug(3, Form("output stream set to file %s for all types", stream.Data()));
}
}
for (Int_t iType = kFatal; iType < kMaxType; iType++)
{
TString name("AliRoot.AliLog.Output.");
name += &typeNames[iType][1];
if (gEnv->Defined(name))
{
TString stream = gEnv->GetValue(name, "Standard");
if (stream.CompareTo("standard", TString::kIgnoreCase) == 0)
{
SetStandardOutput(EType_t(iType));
AliDebug(3, Form("output stream set to standard output for type %s", typeNames[iType]));
}
else if (stream.CompareTo("error", TString::kIgnoreCase) == 0)
{
SetErrorOutput(EType_t(iType));
AliDebug(3, Form("output stream set to error output for type %s", typeNames[iType]));
}
else if (!stream.IsNull())
{
SetFileOutput(EType_t(iType), stream);
AliDebug(3, Form("output stream set to file %s for type %s", stream.Data(), typeNames[iType]));
}
}
}
if (gEnv->Defined("AliRoot.AliLog.HandleRootMessages"))
{
Bool_t on = gEnv->GetValue("AliRoot.AliLog.HandleRootMessages", kTRUE);
SetHandleRootMessages(on);
AliDebug(3, Form("handling of root messages %sabled", ((on) ? "en" : "dis")));
}
static const char* settingNames[4] = {"Type", "Module", "Scope", "Location"};
Bool_t* settings[] = {fPrintType, fPrintModule, fPrintScope, fPrintLocation};
for (Int_t iSetting = 0; iSetting < 4; iSetting++)
{
TString name("AliRoot.AliLog.Print");
name += settingNames[iSetting];
if (gEnv->Defined(name))
{
Bool_t on = gEnv->GetValue(name, settings[iSetting][0]);
for (Int_t iType = kFatal; iType < kMaxType; iType++)
{
settings[iSetting][iType] = on;
}
AliDebug(3, Form("printing of %s %sabled for all types", settingNames[iSetting], ((on) ? "en" : "dis")));
}
for (Int_t iType = kFatal; iType < kMaxType; iType++)
{
TString nameType = name + "." + &typeNames[iType][1];
if (gEnv->Defined(nameType))
{
Bool_t on = gEnv->GetValue(nameType, settings[iSetting][iType]);
settings[iSetting][iType] = on;
AliDebug(3, Form("printing of %s %sabled for type %s", settingNames[iSetting], ((on) ? "en" : "dis"), typeNames[iType]));
}
}
}
if (gEnv->Defined("AliRoot.AliLog.PrintRepetitions"))
{
Bool_t on = gEnv->GetValue("AliRoot.AliLog.PrintRepetitions", kTRUE);
fPrintRepetitions = on;
AliDebug(3, Form("printing of message repetitions %sabled", ((on) ? "en" : "dis")));
}
if (gSystem->Getenv("ALIROOT_FORCE_COREDUMP")){
EnableCoreDump(kTRUE);
}
}
void AliLog::RootErrorHandler(Int_t level, Bool_t abort,
const char* location, const char* message)
{
switch (level)
{
case ::kFatal : level = kFatal; break;
case ::kSysError :
DefaultErrorHandler(level, abort, location, message);
return;
case ::kBreak :
DefaultErrorHandler(level, abort, location, message);
return;
case ::kError : level = kError; break;
case ::kWarning : level = kWarning; break;
case ::kInfo : level = kInfo; break;
default : level = kDebug; break;
}
AliLog::Message(level, message, "ROOT", NULL, location, NULL, 0);
}
void AliLog::EnableDebug(Bool_t enabled)
{
fgDebugEnabled = enabled;
}
void AliLog::EnableCoreDump(Bool_t enabled)
{
gSystem->Exec("ulimit -c unlimited");
fgCoreEnabled = enabled;
gSystem->ResetSignal(kSigFloatingException,enabled);
gSystem->ResetSignal(kSigSegmentationViolation,enabled);
if (enabled) {
printf("Core dump enabled\n");
}
else {
printf("Core dump disabled\n");
}
}
void AliLog::SetGlobalLogLevel(EType_t type)
{
if (!fgInstance) new AliLog;
fgInstance->fGlobalLogLevel = type;
}
Int_t AliLog::GetGlobalLogLevel()
{
if (!fgInstance) new AliLog;
return fgInstance->fGlobalLogLevel;
}
void AliLog::SetGlobalDebugLevel(Int_t level)
{
if (!fgInstance) new AliLog;
if (level < -kDebugOffset) level = -kDebugOffset;
fgInstance->fGlobalLogLevel = kDebugOffset + level;
}
Int_t AliLog::GetGlobalDebugLevel()
{
if (!fgInstance) new AliLog;
return fgInstance->fGlobalLogLevel - kDebugOffset;
}
void AliLog::SetModuleDebugLevel(const char* module, Int_t level)
{
if (!module) return;
if (!fgInstance) new AliLog;
TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
if (!obj) {
obj = new TNamed(module, module);
fgInstance->fModuleDebugLevels.Add(obj);
}
level += kDebugOffset;
if (level < kFatal) level = kFatal;
obj->SetUniqueID(level);
}
void AliLog::ClearModuleDebugLevel(const char* module)
{
if (!module) return;
if (!fgInstance) new AliLog;
TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
if (obj) delete fgInstance->fModuleDebugLevels.Remove(obj);
}
void AliLog::SetClassDebugLevel(const char* className, Int_t level)
{
if (!className) return;
if (!fgInstance) new AliLog;
TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
if (!obj) {
obj = new TNamed(className, className);
fgInstance->fClassDebugLevels.Add(obj);
}
level += kDebugOffset;
if (level < kFatal) level = kFatal;
obj->SetUniqueID(level);
}
void AliLog::ClearClassDebugLevel(const char* className)
{
if (!className) return;
if (!fgInstance) new AliLog;
TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
if (obj) delete fgInstance->fClassDebugLevels.Remove(obj);
}
void AliLog::SetStandardOutput()
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
fgInstance->CloseFile(iType);
fgInstance->fOutputTypes[iType] = 0;
}
}
void AliLog::SetStandardOutput(EType_t type)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
fgInstance->CloseFile(type);
fgInstance->fOutputTypes[type] = 0;
}
void AliLog::SetErrorOutput()
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
fgInstance->CloseFile(iType);
fgInstance->fOutputTypes[iType] = 1;
}
}
void AliLog::SetErrorOutput(EType_t type)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
fgInstance->CloseFile(type);
fgInstance->fOutputTypes[type] = 1;
}
void AliLog::SetFileOutput(const char* fileName)
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
if ((fgInstance->fOutputTypes[iType] == 2) &&
(fgInstance->fFileNames[iType].CompareTo(fileName) != 0)) {
fgInstance->CloseFile(iType);
}
fgInstance->fOutputTypes[iType] = 2;
fgInstance->fFileNames[iType] = fileName;
fgInstance->fOutputFiles[iType] = NULL;
fgInstance->fOutputStreams[iType] = NULL;
}
}
void AliLog::SetFileOutput(EType_t type, const char* fileName)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
if ((fgInstance->fOutputTypes[type] == 2) &&
(fgInstance->fFileNames[type].CompareTo(fileName) != 0)) {
fgInstance->CloseFile(type);
}
fgInstance->fOutputTypes[type] = 2;
fgInstance->fFileNames[type] = fileName;
fgInstance->fOutputFiles[type] = NULL;
fgInstance->fOutputStreams[type] = NULL;
}
void AliLog::CloseFile(Int_t type)
{
if ((fOutputTypes[type] == 2) && fOutputFiles[type]) {
Bool_t closeFile = kTRUE;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
if ((iType != type) && (fOutputFiles[iType] == fOutputFiles[type])) {
closeFile = kFALSE;
}
}
if (closeFile) {
fclose(fOutputFiles[type]);
ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
stream->close();
delete fOutputStreams[type];
}
}
fOutputFiles[type] = NULL;
fOutputStreams[type] = NULL;
fFileNames[type] = "";
fOutputTypes[type] = 0;
}
FILE* AliLog::GetOutputStream(Int_t type)
{
if (type > kDebug) type = kDebug;
if (fOutputTypes[type] == 0) return stdout;
else if (fOutputTypes[type] == 1) return stderr;
else if (fOutputTypes[type] == 2) {
if (!fOutputFiles[type]) {
FILE* file = NULL;
ostream* stream = NULL;
if (!fFileNames[type].IsNull()) {
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
if ((iType != type) &&
(fFileNames[iType].CompareTo(fFileNames[type]) == 0) &&
fOutputFiles[iType]) {
file = fOutputFiles[iType];
stream = fOutputStreams[iType];
break;
}
}
if (!file) {
file = fopen(fFileNames[type], "a");
stream = new ofstream(fFileNames[type], ios::app);
}
}
fOutputFiles[type] = file;
fOutputStreams[type] = stream;
if (!file) CloseFile(type);
}
if (fOutputFiles[type]) return fOutputFiles[type];
}
return stdout;
}
void AliLog::Flush()
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
if (fgInstance->fOutputFiles[iType]) {
fflush(fgInstance->fOutputFiles[iType]);
fgInstance->fOutputStreams[iType]->flush();
}
}
fflush(stderr);
fflush(stdout);
}
void AliLog::SetHandleRootMessages(Bool_t on)
{
if (!fgInstance) new AliLog;
if (on) {
SetErrorHandler(RootErrorHandler);
} else {
SetErrorHandler(DefaultErrorHandler);
}
}
void AliLog::SetPrintType(Bool_t on)
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
fgInstance->fPrintType[iType] = on;
}
}
void AliLog::SetPrintType(EType_t type, Bool_t on)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
fgInstance->fPrintType[type] = on;
}
void AliLog::SetPrintModule(Bool_t on)
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
fgInstance->fPrintModule[iType] = on;
}
}
void AliLog::SetPrintModule(EType_t type, Bool_t on)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
fgInstance->fPrintModule[type] = on;
}
void AliLog::SetPrintScope(Bool_t on)
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
fgInstance->fPrintScope[iType] = on;
}
}
void AliLog::SetPrintScope(EType_t type, Bool_t on)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
fgInstance->fPrintScope[type] = on;
}
void AliLog::SetPrintLocation(Bool_t on)
{
if (!fgInstance) new AliLog;
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
fgInstance->fPrintLocation[iType] = on;
}
}
void AliLog::SetPrintLocation(EType_t type, Bool_t on)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
fgInstance->fPrintLocation[type] = on;
}
void AliLog::SetPrintRepetitions(Bool_t on)
{
if (!fgInstance) new AliLog;
if (!on && (fgInstance->fRepetitions > 0)) fgInstance->PrintRepetitions();
fgInstance->fPrintRepetitions = on;
}
void AliLog::WriteToFile(const char* name, Int_t option)
{
if (!fgInstance) new AliLog;
fgInstance->TObject::Write(name, option);
}
UInt_t AliLog::GetLogLevel(const char* module, const char* className) const
{
if (!fgInstance) new AliLog;
if (className) {
TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
if (obj) return obj->GetUniqueID();
}
if (module) {
TObject* obj = fgInstance->fModuleDebugLevels.FindObject(module);
if (obj) return obj->GetUniqueID();
}
return fgInstance->fGlobalLogLevel;
}
Int_t AliLog::GetDebugLevel(const char* module, const char* className)
{
if (!fgInstance) new AliLog;
return fgInstance->GetLogLevel(module, className) - kDebugOffset;
}
void AliLog::PrintMessage(UInt_t type, const char* message,
const char* module, const char* className,
const char* function, const char* file, Int_t line)
{
if (fPrintRepetitions &&
(fLastType == type) &&
(message && (fLastMessage.CompareTo(message) == 0)) &&
((module && (fLastModule.CompareTo(module) == 0)) ||
(!module && fLastModule.IsNull())) &&
((className && (fLastClassName.CompareTo(className) == 0)) ||
(!className && fLastClassName.IsNull())) &&
((function && (fLastFunction.CompareTo(function) == 0)) ||
(!function && fLastFunction.IsNull()))&&
((file && (fLastFile.CompareTo(file) == 0)) ||
(!file && fLastFile.IsNull())) &&
(fLastLine == line)) {
fRepetitions++;
return;
}
if (fRepetitions > 0) PrintRepetitions();
fRepetitions = 0;
fLastType = type;
fLastMessage = message;
fLastModule = module;
fLastClassName = className;
fLastFunction = function;
fLastFile = file;
fLastLine = line;
FILE* stream = GetOutputStream(type);
static const char* typeNames[kMaxType] =
{"Fatal", "Error", "Warning", "Info", "Debug"};
if (fPrintType[type]) {
PrintString(type, stream, "%c-", typeNames[type][0]);
}
if (fPrintModule[type] && module) {
PrintString(type, stream, "%s/", module);
}
if (fPrintScope[type] && className) {
PrintString(type, stream, "%s::", className);
}
if (message) {
PrintString(type, stream, "%s: %s", function, message);
} else {
PrintString(type, stream, "%s", function);
}
if (fPrintLocation[type] && file) {
PrintString(type, stream, " (%s:%.0d)", file, line);
}
if (message) {
PrintString(type, stream, "\n");
} else {
PrintString(type, stream, ": ");
}
if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
}
void AliLog::PrintRepetitions()
{
PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n",
fRepetitions, (fRepetitions > 1) ? "s" : "");
if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
}
void AliLog::Message(UInt_t level, const char* message,
const char* module, const char* className,
const char* function, const char* file, Int_t line)
{
if (!fgInstance) new AliLog;
UInt_t type = level;
if (type >= kMaxType) type = kMaxType - 1;
if (level <= fgInstance->GetLogLevel(module, className)) {
fgInstance->PrintMessage(type, message,
module, className, function, file, line);
}
if (type == kFatal) {
delete fgInstance;
if (gSystem) {
gSystem->StackTrace();
if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
gSystem->Abort();
} else {
if (fgCoreEnabled) MakeCoreDump("core.AliRoot");
::abort();
}
}
}
void AliLog::Debug(UInt_t level, const char* message,
const char* module, const char* className,
const char* function, const char* file, Int_t line)
{
if (level == 0) level = 1;
level += kDebugOffset;
Message(level, message, module, className, function, file, line);
}
Int_t AliLog::RedirectStdoutTo(EType_t type, UInt_t level, const char* module,
const char* className, const char* function,
const char* file, Int_t line, Bool_t print)
{
if (!fgInstance) new AliLog;
return fgInstance->RedirectTo(stdout, type, level, module, className,
function, file, line, print);
}
Int_t AliLog::RedirectStderrTo(EType_t type, UInt_t level, const char* module,
const char* className, const char* function,
const char* file, Int_t line, Bool_t print)
{
if (!fgInstance) new AliLog;
return fgInstance->RedirectTo(stderr, type, level, module, className,
function, file, line, print);
}
Int_t AliLog::RedirectTo(FILE* stream, EType_t type, UInt_t level,
const char* module, const char* className,
const char* function, const char* file, Int_t line,
Bool_t print)
{
Int_t original = dup(fileno(stream));
fflush(stream);
FILE* newStream = GetOutputStream(type);
fflush(newStream);
if ((type == kDebug) && (level > 0)) level--;
if (type + level > GetLogLevel(module, className)) {
if(!freopen("/dev/null", "a", stream)) AliWarning("Cannot reopen /dev/null");
} else if (fOutputTypes[type] == 0) {
if (stream != stdout) dup2(fileno(stdout), fileno(stream));
} else if (fOutputTypes[type] == 1) {
if (stream != stderr) dup2(fileno(stderr), fileno(stream));
} else if (fOutputTypes[type] == 2) {
if(!freopen(fFileNames[type], "a", stream)) AliWarning(Form("Cannot reopen %s",fFileNames[type].Data()));
} else if (fOutputTypes[type] == 3) {
}
if (print) {
PrintMessage(type, NULL, module, className, function, file, line);
fflush(newStream);
}
return original;
}
void AliLog::RestoreStdout(Int_t original)
{
fflush(stdout);
dup2(original, fileno(stdout));
close(original);
}
void AliLog::RestoreStderr(Int_t original)
{
fflush(stderr);
dup2(original, fileno(stderr));
close(original);
}
ostream& AliLog::Stream(EType_t type, UInt_t level,
const char* module, const char* className,
const char* function, const char* file, Int_t line)
{
if (!fgInstance) new AliLog;
return fgInstance->GetStream(type, level, module, className,
function, file, line);
}
ostream& AliLog::GetStream(EType_t type, UInt_t level,
const char* module, const char* className,
const char* function, const char* file, Int_t line)
{
if ((type == kDebug) && (level > 0)) level--;
Bool_t noOutput = (type + level > GetLogLevel(module, className));
if (!noOutput) {
PrintMessage(type, NULL, module, className, function, file, line);
}
fflush(GetOutputStream(type));
static ofstream nullStream("/dev/null");
if (noOutput) {
return nullStream;
} else if (fOutputTypes[type] == 0) {
return cout;
} else if (fOutputTypes[type] == 1) {
return cerr;
} else if (fOutputTypes[type] == 2) {
return *fOutputStreams[type];
} else if (fOutputTypes[type] == 3) {
return *fOutputStreams[type];
}
return nullStream;
}
void AliLog::SetStreamOutput(ostream* stream)
{
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
SetStreamOutput((AliLog::EType_t)iType, stream);
}
}
void AliLog::SetStreamOutput(EType_t type, ostream* stream)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
if (fgInstance->fOutputTypes[type] == 2) {
fgInstance->CloseFile(type);
}
fgInstance->fOutputTypes[type] = 3;
fgInstance->fFileNames[type] = "";
fgInstance->fOutputFiles[type] = NULL;
fgInstance->fOutputStreams[type] = stream;
}
void AliLog::SetLogNotification(AliLogNotification pCallBack)
{
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
SetLogNotification((AliLog::EType_t)iType, pCallBack);
}
}
void AliLog::SetLogNotification(EType_t type, AliLogNotification pCallBack)
{
if ((type < kFatal) || (type >= kMaxType)) return;
if (!fgInstance) new AliLog;
fgInstance->fCallBacks[type]=pCallBack;
}
void AliLog::PrintString(Int_t type, FILE* stream, const char* format, ...)
{
if (format==NULL) return;
va_list ap;
va_start(ap, format);
if (fOutputTypes[type] != 3) {
if (stream!=NULL) {
vfprintf(stream, format, ap);
}
} else {
TString fmt(format);
TArrayC tgt(fmt.Length()*10);
#ifdef R__VA_COPY
va_list bap;
R__VA_COPY(bap, ap);
#else
#warning definition of R__VA_COPY has disappeared
#endif //R__VA_COPY
Int_t iResult=0;
while (1) {
iResult=vsnprintf(tgt.GetArray(), tgt.GetSize(), format, ap);
if (iResult==-1) {
iResult=tgt.GetSize()*2;
} else if (iResult<tgt.GetSize()) {
break;
}
#ifdef R__VA_COPY
if (iResult<10000) {
tgt.Set(iResult+1);
va_end(ap);
R__VA_COPY(ap, bap);
} else
#endif //R__VA_COPY
{
tgt[tgt.GetSize()-1]=0;
break;
}
}
#ifdef R__VA_COPY
va_end(bap);
#endif //R__VA_COPY
if (fOutputStreams[type]) {
*(fOutputStreams[type]) << tgt.GetArray();
}
}
va_end(ap);
}
void AliLog::MakeCoreDump(const char *fout){
if (!gSystem) return;
printf("AliLog::MakeCoreDump\n");
if (fout){
gSystem->Exec(Form("gcore -o %s %d",fout, gSystem->GetPid()));
}else{
gSystem->Exec(Form("gcore %d", gSystem->GetPid()));
}
}
void AliLog::TestException(Int_t level){
printf("AliLog::TestException(%d)\n",level);
if (level>0){
level--;
TestException(level);
}else{
throw std::runtime_error("Test exception");
}
}