// $Id$ //----------------------------------------------------------------------- // The GSI Online Offline Object Oriented (Go4) Project // Experiment Data Processing at EE department, GSI //----------------------------------------------------------------------- // Copyright (C) 2000- GSI Helmholtzzentrum fuer Schwerionenforschung GmbH // Planckstr. 1, 64291 Darmstadt, Germany // Contact: http://go4.gsi.de //----------------------------------------------------------------------- // This software can be used under the license agreements as stated // in Go4License.txt file which is part of the distribution. //----------------------------------------------------------------------- #include "TGo4Log.h" #ifndef WIN32 #include #include #endif #include #include #include #include "TDatime.h" #include "TDataType.h" #include "TMutex.h" #include "TSystem.h" const char* TGo4Log::fgcLEFT = "GO4-"; //const char* TGo4Log::fgcRIGHT = " 0) return; #ifndef WIN32 fflush(stdout); fgStdSave = dup(STDOUT_FILENO); /* save stdout for display later */ if(pipe(fgStdPipe) != 0) return; /* make a pipe */ dup2(fgStdPipe[1], STDOUT_FILENO); /* redirect stdout to the pipe */ long flags = fcntl(fgStdPipe[0], F_GETFL); flags |= O_NONBLOCK; fcntl(fgStdPipe[0], F_SETFL, flags); if (fgTimer==0) { fgTimer = new TLogTimer(200); fgTimer->Start(200); } #endif } void TGo4Log::ProcessRedirection(int kind) { if (fgStdSave<0) return; #ifndef WIN32 if (kind>=0) { std::cout.flush(); fflush(stdout); char buffer[20000]; memset(buffer, 0, sizeof(buffer)); int len = read(fgStdPipe[0], buffer, sizeof(buffer)-1); /* read from pipe into buffer */ // when nothing to read, than nothing to redirect if (len==0) return; dup2(fgStdSave, STDOUT_FILENO); /* reconnect stdout for realoutput */ printf("%s", buffer); fflush(stdout); if (fgSniffer!=0) fgSniffer->SetTitle(buffer); } if (kind<=0) { dup2(fgStdPipe[1], STDOUT_FILENO); // redirect again } #endif } void TGo4Log::SetSniffer(TNamed* sniff) { fgSniffer = sniff; } const char* TGo4Log::GO4SYS() { if (fgsGO4SYS.Length()>0) return fgsGO4SYS.Data(); const char* go4sys = gSystem->Getenv("GO4SYS"); #ifdef COMP_GO4SYS if ((go4sys==0) || (strlen(go4sys)==0)) go4sys = COMP_GO4SYS; #endif if ((go4sys==0) || (strlen(go4sys)==0)) return ""; fgsGO4SYS = go4sys; if (fgsGO4SYS.Length() > 0) { #ifdef WIN32 char lastsymbol = '\\'; fgsGO4SYS.ReplaceAll("/","\\"); // while in cygpath we cannot deliver windows-like slashes #else char lastsymbol = '/'; #endif if (fgsGO4SYS[fgsGO4SYS.Length() - 1] != lastsymbol) fgsGO4SYS += lastsymbol; } return fgsGO4SYS.Length()>0 ? fgsGO4SYS.Data() : ""; } const char* TGo4Log::GO4INCPATH() { #ifdef COMP_GO4INC return COMP_GO4INC; #endif return ""; } TString TGo4Log::subGO4SYS(const char* subdir) { const char* go4sys = GO4SYS(); if ((subdir==0) || (strlen(subdir)==0)) return TString(go4sys); TString res = go4sys; #ifdef WIN32 res += TString(subdir).ReplaceAll("/","\\"); #else res += subdir; #endif return res; } const char* TGo4Log::Message(Int_t prio, const char* text,...) { Instance(); //TGo4LockGuard(fxMutex); if(prio>-1 && prio %s %s", fgcLEFT, prefix, txtbuf, fgcRIGHT); // this is just because of gcc8 warnings if (res < 0) (void)res; if(fgbOutputEnabled) { ProcessRedirection(1); // disable redirection std::cout << fgcMessagetext << std::endl; std::cout.flush(); if (fgSniffer) fgSniffer->SetTitle(fgcMessagetext); ProcessRedirection(-1); // enable again } return fgcMessagetext; } void TGo4Log::Printf(Bool_t _stdout, const char* text) { ProcessRedirection(1); // disable redirection if (_stdout) { fprintf(stdout, "%s", text); fflush(stdout); } else { fprintf(stderr, "%s", text); fflush(stderr); } ProcessRedirection(-1); // enable again } void TGo4Log::Debug(const char* text,...) { if(fgiIgnoreLevel>0) return; Instance(); //TGo4LockGuard(fxMutex); char txtbuf[fguMESLEN]; va_list args; va_start(args, text); vsnprintf(txtbuf, fguMESLEN, text, args); va_end(args); Message(0,txtbuf); } void TGo4Log::Info(const char* text,...) { if(fgiIgnoreLevel>1) return; Instance(); //TGo4LockGuard(fxMutex); char txtbuf[fguMESLEN]; va_list args; va_start(args, text); vsnprintf(txtbuf, fguMESLEN, text, args); va_end(args); Message(1,txtbuf); } void TGo4Log::Warn(const char* text,...) { if(fgiIgnoreLevel>2) return; Instance(); //TGo4LockGuard(fxMutex); char txtbuf[fguMESLEN]; va_list args; va_start(args, text); vsnprintf(txtbuf, fguMESLEN, text, args); va_end(args); Message(2,txtbuf); } void TGo4Log::Error(const char* text,...) { Instance(); //TGo4LockGuard(fxMutex); char txtbuf[fguMESLEN]; va_list args; va_start(args, text); vsnprintf(txtbuf, fguMESLEN, text, args); va_end(args); Message(3,txtbuf); } void TGo4Log::SetIgnoreLevel(Int_t level) { //TGo4LockGuard(fxMutex); fgiIgnoreLevel=level; } Int_t TGo4Log::GetIgnoreLevel() { return fgiIgnoreLevel; } const char* TGo4Log::GetLogname() { return fgxLogName.Data(); } const char* TGo4Log::GetDefaultLogname() { return fgcDEFAULTLOG; } const char* TGo4Log::GetPrintfArg(Int_t type_id) { switch (type_id) { case kInt_t: return "%d"; case kUInt_t: return "%u"; case kLong_t: return "%ld"; case kULong_t: return "%lu"; case kLong64_t: return sizeof(long long int)==8 ? "%lld" : "%ld"; case kULong64_t: return sizeof(long long unsigned)==8 ? "%llu" : "%lu"; } return "%d"; } void TGo4Log::OutputEnable(Bool_t on) { //TGo4LockGuard(fxMutex); fgbOutputEnabled=on; } Bool_t TGo4Log::IsOutputEnabled() { return fgbOutputEnabled; } void TGo4Log::LogfileEnable(Bool_t on) { //TGo4LockGuard(fxMutex); fgbLogfileEnabled=on; } Bool_t TGo4Log::IsLogfileEnabled() { return fgbLogfileEnabled; } void TGo4Log::AutoEnable(Bool_t on) { //TGo4LockGuard(fxMutex); fgbAutoMode=on; } Bool_t TGo4Log::IsAutoEnabled() { return fgbAutoMode; } void TGo4Log::OpenLogfile(const char* name, const char* headercomment, Bool_t appendmode) { //TGo4LockGuard(fxMutex); try { CloseLogfile(); char txtbuf[fguMESLEN]; if(name==0) // default: encode pid into filename snprintf(txtbuf,fguMESLEN,"go4log-%d.txt", gSystem->GetPid()); else snprintf(txtbuf,fguMESLEN,"%s",name); std::ofstream* lf = new std::ofstream(txtbuf, appendmode ? std::ios::app : std::ios::out); if(lf->fail()) { LogfileEnable(kFALSE); delete lf; std::cerr <<"TGo4Log::OpenLogfile() - Error opening logfile "<< name << std::endl; } else { fgxLogfile = lf; fgxLogName = txtbuf; // remember our last filename } // write headercomment into the first lines: if(headercomment) WriteLogfile(headercomment, kFALSE); } // try catch(std::exception& ex) // treat standard library exceptions { std::cerr <<"standard exception "<(fgxLogfile); if (lf->is_open()) { if(withtime) { TDatime now; *lf << now.AsSQLString() << ": "; } *lf << text << std::endl; } }// try catch(std::exception& ex) // treat standard library exceptions { std::cerr <<"standard exception "<