]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - STEER/AliLog.cxx
Updated task list
[u/mrichter/AliRoot.git] / STEER / AliLog.cxx
index 13ea390fbbd66e8626998c377cae37862114553e..025852d202a91a4874cb4d36506385c8fdc7fb44 100644 (file)
 //                                                                           //
 ///////////////////////////////////////////////////////////////////////////////
 
+#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"
 
@@ -71,6 +74,7 @@ AliLog::AliLog() :
     fFileNames[iType] = "";
     fOutputFiles[iType] = NULL;
     fOutputStreams[iType] = NULL;
+    fCallBacks[iType]=NULL;
 
     fPrintType[iType] = kTRUE;
     fPrintModule[iType] = kFALSE;
@@ -115,7 +119,19 @@ AliLog::~AliLog()
 
 //_____________________________________________________________________________
 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
 
@@ -175,7 +191,7 @@ void AliLog::ReadEnvSettings()
     char* p = const_cast<char*>(levels.Data());
     while (const char* module = strtok(p, " ")) {
       p = NULL;
-      char* pos = index(module, ':');
+      char* pos = const_cast<char*>(index(module, ':'));
       if (!pos) continue;
       *(pos++) = '\0';
       Int_t level = atoi(pos);
@@ -190,7 +206,7 @@ void AliLog::ReadEnvSettings()
     char* p = const_cast<char*>(levels.Data());
     while (const char* className = strtok(p, " ")) {
       p = NULL;
-      char* pos = index(className, ':');
+      char* pos = const_cast<char*>(index(className, ':'));
       if (!pos) continue;
       *(pos++) = '\0';
       Int_t level = atoi(pos);
@@ -223,15 +239,15 @@ void AliLog::ReadEnvSettings()
     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]));
       }
@@ -317,7 +333,7 @@ void AliLog::EnableDebug(Bool_t enabled)
 }
 
 //_____________________________________________________________________________
-void AliLog::SetGlobalLogLevel(EType type)
+void AliLog::SetGlobalLogLevel(EType_t type)
 {
 // set the global debug level
 
@@ -423,7 +439,7 @@ void AliLog::SetStandardOutput()
 }
 
 //_____________________________________________________________________________
-void AliLog::SetStandardOutput(EType type)
+void AliLog::SetStandardOutput(EType_t type)
 {
 // write log messages of the given type to the standard output (stdout)
 
@@ -446,7 +462,7 @@ void AliLog::SetErrorOutput()
 }
 
 //_____________________________________________________________________________
-void AliLog::SetErrorOutput(EType type)
+void AliLog::SetErrorOutput(EType_t type)
 {
 // write log messages of the given type to the error output (stderr)
 
@@ -475,7 +491,7 @@ void AliLog::SetFileOutput(const char* fileName)
 }
 
 //_____________________________________________________________________________
-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
 
@@ -505,7 +521,8 @@ void AliLog::CloseFile(Int_t type)
     }
     if (closeFile) {
       fclose(fOutputFiles[type]);
-      fOutputStreams[type]->close();
+      ofstream* stream=reinterpret_cast<ofstream*>(fOutputStreams[type]);
+      stream->close();
       delete fOutputStreams[type];
     }
   }
@@ -526,7 +543,7 @@ FILE* AliLog::GetOutputStream(Int_t 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) && 
@@ -595,7 +612,7 @@ void AliLog::SetPrintType(Bool_t on)
 }
 
 //_____________________________________________________________________________
-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
 
@@ -616,7 +633,7 @@ void AliLog::SetPrintModule(Bool_t on)
 }
 
 //_____________________________________________________________________________
-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
 
@@ -637,7 +654,7 @@ void AliLog::SetPrintScope(Bool_t on)
 }
 
 //_____________________________________________________________________________
-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
@@ -660,7 +677,7 @@ void AliLog::SetPrintLocation(Bool_t on)
 }
 
 //_____________________________________________________________________________
-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
@@ -684,7 +701,7 @@ void AliLog::SetPrintRepetitions(Bool_t on)
 
 
 //_____________________________________________________________________________
-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
 
@@ -762,28 +779,28 @@ void AliLog::PrintMessage(UInt_t type, const char* message,
     {"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);
 }
 
 //_____________________________________________________________________________
@@ -791,8 +808,9 @@ void AliLog::PrintRepetitions()
 {
 // 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);
 }
 
 //_____________________________________________________________________________
@@ -840,7 +858,7 @@ void AliLog::Debug(UInt_t level, const char* message,
 
 
 //_____________________________________________________________________________
-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)
 {
@@ -852,7 +870,7 @@ Int_t AliLog::RedirectStdoutTo(EType type, UInt_t level, const char* module,
 }
 
 //_____________________________________________________________________________
-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)
 {
@@ -864,7 +882,7 @@ Int_t AliLog::RedirectStderrTo(EType type, UInt_t level, const char* module,
 }
 
 //_____________________________________________________________________________
-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)
@@ -889,6 +907,8 @@ Int_t AliLog::RedirectTo(FILE* stream, EType type, UInt_t level,
     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
@@ -922,7 +942,7 @@ void AliLog::RestoreStderr(Int_t original)
 
 
 //_____________________________________________________________________________
-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)
 {
@@ -934,7 +954,7 @@ ostream& AliLog::Stream(EType type, UInt_t level,
 }
 
 //_____________________________________________________________________________
-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)
 {
@@ -957,8 +977,117 @@ ostream& AliLog::GetStream(EType type, UInt_t level,
     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);
+#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);
+}