#include <TNamed.h>
#include <TSystem.h>
#include <TEnv.h>
+#include <TArrayC.h>
#include "AliLog.h"
fFileNames[iType] = "";
fOutputFiles[iType] = NULL;
fOutputStreams[iType] = NULL;
+ fCallBacks[iType]=NULL;
fPrintType[iType] = kTRUE;
fPrintModule[iType] = kFALSE;
//_____________________________________________________________________________
AliLog::AliLog(const AliLog& log) :
- TObject(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)
{
// copy constructor
if (gEnv->Defined(name)) {
TString stream = gEnv->GetValue(name, "Standard");
if (stream.CompareTo("standard", TString::kIgnoreCase) == 0) {
- SetStandardOutput(EType(iType));
+ 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(iType));
+ SetErrorOutput(EType_t(iType));
AliDebug(3, Form("output stream set to error output for type %s",
typeNames[iType]));
} else if (!stream.IsNull()) {
- SetFileOutput(EType(iType), stream);
+ SetFileOutput(EType_t(iType), stream);
AliDebug(3, Form("output stream set to file %s for type %s",
stream.Data(), typeNames[iType]));
}
}
//_____________________________________________________________________________
-void AliLog::SetGlobalLogLevel(EType type)
+void AliLog::SetGlobalLogLevel(EType_t type)
{
// set the global debug level
}
//_____________________________________________________________________________
-void AliLog::SetStandardOutput(EType type)
+void AliLog::SetStandardOutput(EType_t type)
{
// write log messages of the given type to the standard output (stdout)
}
//_____________________________________________________________________________
-void AliLog::SetErrorOutput(EType type)
+void AliLog::SetErrorOutput(EType_t type)
{
// write log messages of the given type to the error output (stderr)
}
//_____________________________________________________________________________
-void AliLog::SetFileOutput(EType type, const char* fileName)
+void AliLog::SetFileOutput(EType_t type, const char* fileName)
{
// write log messages of the given type to the given file
}
if (closeFile) {
fclose(fOutputFiles[type]);
- fOutputStreams[type]->close();
+ ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
+ stream->close();
delete fOutputStreams[type];
}
}
else if (fOutputTypes[type] == 2) {
if (!fOutputFiles[type]) {
FILE* file = NULL;
- ofstream* stream = NULL;
+ ostream* stream = NULL;
if (!fFileNames[type].IsNull()) {
for (Int_t iType = kFatal; iType < kMaxType; iType++) {
if ((iType != type) &&
}
//_____________________________________________________________________________
-void AliLog::SetPrintType(EType type, Bool_t on)
+void AliLog::SetPrintType(EType_t type, Bool_t on)
{
// switch on or off the printing of the message type for the given message type
}
//_____________________________________________________________________________
-void AliLog::SetPrintModule(EType type, Bool_t on)
+void AliLog::SetPrintModule(EType_t type, Bool_t on)
{
// switch on or off the printing of the module for the given message type
}
//_____________________________________________________________________________
-void AliLog::SetPrintScope(EType type, Bool_t on)
+void AliLog::SetPrintScope(EType_t type, Bool_t on)
{
// switch on or off the printing of the scope/class name
// for the given message type
}
//_____________________________________________________________________________
-void AliLog::SetPrintLocation(EType type, Bool_t on)
+void AliLog::SetPrintLocation(EType_t type, Bool_t on)
{
// switch on or off the printing of the file name and line number
// for the given message type
//_____________________________________________________________________________
-void AliLog::Write(const char* name, Int_t option)
+void AliLog::WriteToFile(const char* name, Int_t option)
{
// write the log object with the given name and option to the current file
// get the logging level for the given module and class
if (!fgInstance) new AliLog;
- TObject* obj = fgInstance->fClassDebugLevels.FindObject(className);
- if (obj) return obj->GetUniqueID();
- obj = fgInstance->fModuleDebugLevels.FindObject(module);
- if (obj) return obj->GetUniqueID();
+ 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;
}
{"Fatal", "Error", "Warning", "Info", "Debug"};
if (fPrintType[type]) {
- fprintf(stream, "%s in ", typeNames[type]);
+ PrintString(type, stream, "%c-", typeNames[type][0]);
}
- fprintf(stream, "<");
if (fPrintModule[type] && module) {
- fprintf(stream, "%s/", module);
+ PrintString(type, stream, "%s/", module);
}
if (fPrintScope[type] && className) {
- fprintf(stream, "%s::", className);
+ PrintString(type, stream, "%s::", className);
}
if (message) {
- fprintf(stream, "%s>: %s", function, message);
+ PrintString(type, stream, "%s: %s", function, message);
} else {
- fprintf(stream, "%s>", function);
+ PrintString(type, stream, "%s", function);
}
if (fPrintLocation[type] && file) {
- fprintf(stream, " (%s:%.0d)", file, line);
+ PrintString(type, stream, " (%s:%.0d)", file, line);
}
if (message) {
- fprintf(stream, "\n");
+ PrintString(type, stream, "\n");
} else {
- fprintf(stream, ": ");
+ PrintString(type, stream, ": ");
}
+ if (fCallBacks[type]) (*(fCallBacks[type]))((EType_t)type, NULL);
}
//_____________________________________________________________________________
{
// print number of repetitions
- fprintf(GetOutputStream(fLastType), " <message repeated %d time%s>\n",
+ PrintString(fLastType, GetOutputStream(fLastType), " <message repeated %d time%s>\n",
fRepetitions, (fRepetitions > 1) ? "s" : "");
+ if (fCallBacks[fLastType]) (*(fCallBacks[fLastType]))((EType_t)fLastType, NULL);
}
//_____________________________________________________________________________
//_____________________________________________________________________________
-Int_t AliLog::RedirectStdoutTo(EType type, UInt_t level, const char* module,
+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)
{
}
//_____________________________________________________________________________
-Int_t AliLog::RedirectStderrTo(EType type, UInt_t level, const char* module,
+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)
{
}
//_____________________________________________________________________________
-Int_t AliLog::RedirectTo(FILE* stream, EType type, UInt_t level,
+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)
if (stream != stderr) dup2(fileno(stderr), fileno(stream));
} else if (fOutputTypes[type] == 2) { // file
freopen(fFileNames[type], "a", stream);
+ } else if (fOutputTypes[type] == 3) { // external C++ stream
+ // redirection is not possible for external C++ streams
}
// print information
//_____________________________________________________________________________
-ostream& AliLog::Stream(EType type, UInt_t level,
+ostream& AliLog::Stream(EType_t type, UInt_t level,
const char* module, const char* className,
const char* function, const char* file, Int_t line)
{
}
//_____________________________________________________________________________
-ostream& AliLog::GetStream(EType type, UInt_t level,
+ostream& AliLog::GetStream(EType_t type, UInt_t level,
const char* module, const char* className,
const char* function, const char* file, Int_t line)
{
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)
+{
+ // set an external stream as target for log messages of all types
+ // the external stream is completely handled by the caller, the
+ // AliLog class just writes to it
+
+ for (Int_t iType = kFatal; iType < kMaxType; iType++) {
+ SetStreamOutput((AliLog::EType_t)iType, stream);
+ }
+}
+
+void AliLog::SetStreamOutput(EType_t type, ostream* stream)
+{
+ // set an external stream as target for log messages of the given type
+ // the external stream is completely handled by the caller, the
+ // AliLog class just writes to it
+
+ 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)
+{
+ // set a notification callback function for log messages of all types
+
+ for (Int_t iType = kFatal; iType < kMaxType; iType++) {
+ SetLogNotification((AliLog::EType_t)iType, pCallBack);
+ }
+}
+
+void AliLog::SetLogNotification(EType_t type, AliLogNotification pCallBack)
+{
+ // set a notifications call back function for log messages of all types
+ // the callback fuction is invoced whenever an output was written
+ // Note: does not work for c++ streamer classes, the external stream
+ // has to handle this diectly (e.g. custom implementation of endl)
+
+ 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, ...)
+{
+ // this is the general method to print a log message using variadac args
+ // to the FILE* like (C - like) streams, e.g. stdout, stderr, or files
+ // opened by fopen.
+ // Only in case of an external c++ ostream type output, the message is
+ // written to that stream and the notifictaion callback is called.
+ // The message is printed by a normal vfprintf function otherwise
+
+ if (format==NULL) return;
+
+ va_list ap;
+ va_start(ap, format);
+ if (fOutputTypes[type] != 3) {
+ if (stream!=NULL) {
+ vfprintf(stream, format, ap);
+ }
+ } else {
+ // build the string and write everthing to the corresponding ostream
+ TString fmt(format);
+ TArrayC tgt(fmt.Length()*10); // just take a number
+#ifdef R__VA_COPY
+ va_list bap;
+ R__VA_COPY(bap, ap);
+#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);
+}