GSI Object Oriented Online Offline (Go4)  GO4-5.3.2
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
TGo4Log.cxx
Go to the documentation of this file.
1 // $Id: TGo4Log.cxx 1879 2016-04-04 17:10:38Z linev $
2 //-----------------------------------------------------------------------
3 // The GSI Online Offline Object Oriented (Go4) Project
4 // Experiment Data Processing at EE department, GSI
5 //-----------------------------------------------------------------------
6 // Copyright (C) 2000- GSI Helmholtzzentrum für Schwerionenforschung GmbH
7 // Planckstr. 1, 64291 Darmstadt, Germany
8 // Contact: http://go4.gsi.de
9 //-----------------------------------------------------------------------
10 // This software can be used under the license agreements as stated
11 // in Go4License.txt file which is part of the distribution.
12 //-----------------------------------------------------------------------
13 
14 #include "TGo4Log.h"
15 
16 #ifndef WIN32
17 #include <unistd.h>
18 #include <fcntl.h>
19 #endif
20 
21 #include "Riostream.h"
22 #include "TDataType.h"
23 #include "TDatime.h"
24 #include "TMutex.h"
25 #include "TSystem.h"
26 #include "snprintf.h"
27 
28 #include "TGo4LockGuard.h"
29 
30 
31 const char* TGo4Log::fgcLEFT = "GO4-";
32 //const char* TGo4Log::fgcRIGHT = " <GO4";
33 const char* TGo4Log::fgcRIGHT = " ";
34 const char* TGo4Log::fgcDEBUG = "d";
35 const char* TGo4Log::fgcINFO = "*";
36 const char* TGo4Log::fgcWARN = "#";
37 const char* TGo4Log::fgcERR = "!";
38 const char* TGo4Log::fgcDEFAULTLOG = "go4logfile.txt";
39 
40 TString TGo4Log::fgsGO4SYS = "";
41 
42 
44 Int_t TGo4Log::fgiIgnoreLevel = 1;
45 Bool_t TGo4Log::fgbOutputEnabled = kTRUE;
46 Bool_t TGo4Log::fgbLogfileEnabled = kFALSE;
47 Bool_t TGo4Log::fgbAutoMode = kFALSE;
48 void* TGo4Log::fgxLogfile = 0;
49 TMutex* TGo4Log::fgxMutex = 0;
51 
53 
54 TNamed* TGo4Log::fgSniffer = 0;
55 
56 int TGo4Log::fgStdPipe[2] = {-1, -1};
57 int TGo4Log::fgStdSave = -1;
58 
59 class TLogTimer : public TTimer {
60  public:
61  TLogTimer(Int_t millisec) : TTimer(millisec) {}
62 
63  virtual Bool_t Notify() { TGo4Log::ProcessRedirection(); return kTRUE; }
64 };
65 
66 
68 
70 {
71  if (fgxMutex == 0) fgxMutex = new TMutex(kTRUE);
72 
73 
74  // initialization at first time we call logger
75  // we use recursive mode for cascading lockguards
76  if (IsLogfileEnabled()) {
77  OpenLogfile(fgcDEFAULTLOG,"--- This is the default Go4 Message logfile ---");
78  LogfileEnable(kFALSE); // after first write disable logfile
79  }
80 }
81 
83 {
84  CloseLogfile();
85 }
86 
88 {
89  if(fgxInstance == 0)
90  fgxInstance = new TGo4Log();
91 
92  return fgxInstance;
93 }
94 
96 {
97  if (fgStdSave > 0) return;
98 
99 #ifndef WIN32
100 
101  fflush(stdout);
102 
103  fgStdSave = dup(STDOUT_FILENO); /* save stdout for display later */
104 
105  if(pipe(fgStdPipe) != 0) return; /* make a pipe */
106 
107  dup2(fgStdPipe[1], STDOUT_FILENO); /* redirect stdout to the pipe */
108  long flags = fcntl(fgStdPipe[0], F_GETFL);
109  flags |= O_NONBLOCK;
110  fcntl(fgStdPipe[0], F_SETFL, flags);
111 
112  if (fgTimer==0) {
113  fgTimer = new TLogTimer(200);
114  fgTimer->Start(200);
115  }
116 #endif
117 }
118 
119 
121 {
122  if (fgStdSave<0) return;
123 
124 #ifndef WIN32
125 
126  if (kind>=0) {
127 
128  std::cout.flush();
129  fflush(stdout);
130 
131  char buffer[20000];
132  memset(buffer, 0, sizeof(buffer));
133  int len = read(fgStdPipe[0], buffer, sizeof(buffer)-1); /* read from pipe into buffer */
134 
135  // when nothing to read, than nothing to redirect
136  if (len==0) return;
137 
138  dup2(fgStdSave, STDOUT_FILENO); /* reconnect stdout for realoutput */
139 
140  printf("%s", buffer);
141  fflush(stdout);
142 
143  if (fgSniffer!=0) fgSniffer->SetTitle(buffer);
144  }
145 
146  if (kind<=0) {
147  dup2(fgStdPipe[1], STDOUT_FILENO); // redirect again
148  }
149 
150 #endif
151 }
152 
153 void TGo4Log::SetSniffer(TNamed* sniff)
154 {
155  fgSniffer = sniff;
156 }
157 
158 const char* TGo4Log::GO4SYS()
159 {
160  if (fgsGO4SYS.Length()>0) return fgsGO4SYS.Data();
161  const char* go4sys = gSystem->Getenv("GO4SYS");
162 #ifdef COMP_GO4SYS
163  if ((go4sys==0) || (strlen(go4sys)==0)) go4sys = COMP_GO4SYS;
164 #endif
165  if ((go4sys==0) || (strlen(go4sys)==0)) return "";
166 
167  fgsGO4SYS = go4sys;
168  if (fgsGO4SYS.Length() > 0) {
169 #ifdef WIN32
170  char lastsymbol = '\\';
171  fgsGO4SYS.ReplaceAll("/","\\"); // while in cygpath we cannot deliver windows-like slashes
172 #else
173  char lastsymbol = '/';
174 #endif
175  if (fgsGO4SYS[fgsGO4SYS.Length() - 1] != lastsymbol) fgsGO4SYS += lastsymbol;
176  }
177 
178  return fgsGO4SYS.Length()>0 ? fgsGO4SYS.Data() : "";
179 }
180 
181 const char* TGo4Log::GO4INCPATH()
182 {
183  #ifdef COMP_GO4INC
184  return COMP_GO4INC;
185  #endif
186 
187  return "";
188 }
189 
190 
191 
192 TString TGo4Log::subGO4SYS(const char* subdir)
193 {
194  const char* go4sys = GO4SYS();
195 
196  if ((subdir==0) || (strlen(subdir)==0)) return TString(go4sys);
197 
198  TString res = go4sys;
199 
200 #ifdef WIN32
201  res += TString(subdir).ReplaceAll("/","\\");
202 #else
203  res += subdir;
204 #endif
205 
206  return res;
207 }
208 
209 const char* TGo4Log::Message(Int_t prio, const char* text,...)
210 {
211  Instance();
212  //TGo4LockGuard(fxMutex);
213  if(prio>-1 && prio<fgiIgnoreLevel) return 0;
214  char txtbuf[fguMESLEN];
215  va_list args;
216  va_start(args, text);
217  vsnprintf(txtbuf, fguMESLEN, text, args);
218  va_end(args);
219  const char* prefix(fgcINFO);
220  switch(prio) {
221  // info output independent of current ignorelevel
222  case -1: prefix=fgcINFO; break;
223  case 0: prefix=fgcDEBUG; break;
224  case 1: prefix=fgcINFO; break;
225  case 2: prefix=fgcWARN; break;
226  case 3: prefix=fgcERR; break;
227  } // switch()
228 
229  if(fgbLogfileEnabled) {
230  // message format for logfile is different:
231  snprintf(fgcMessagetext,fguMESLEN,"%s %s",prefix,txtbuf);
233  }
234 
235  // we compose the full messagetext anyway, for further use outside
236  snprintf(fgcMessagetext,fguMESLEN, "%s%s> %s %s",
237  fgcLEFT, prefix, txtbuf,fgcRIGHT);
238 
239  if(fgbOutputEnabled) {
240 
241  ProcessRedirection(1); // disable redirection
242 
243  std::cout << fgcMessagetext << std::endl;
244 
245  std::cout.flush();
246 
247  if (fgSniffer) fgSniffer->SetTitle(fgcMessagetext);
248 
249  ProcessRedirection(-1); // enable again
250  }
251 
252  return fgcMessagetext;
253 }
254 
255 void TGo4Log::Printf(Bool_t _stdout, const char* text)
256 {
257  ProcessRedirection(1); // disable redirection
258 
259  if (_stdout) {
260  fprintf(stdout, text);
261  fflush(stdout);
262  } else {
263  fprintf(stderr, text);
264  fflush(stderr);
265  }
266 
267  ProcessRedirection(-1); // enable again
268 }
269 
270 void TGo4Log::Debug(const char* text,...)
271 {
272  if(fgiIgnoreLevel>0) return;
273  Instance();
274  //TGo4LockGuard(fxMutex);
275  char txtbuf[fguMESLEN];
276  va_list args;
277  va_start(args, text);
278  vsnprintf(txtbuf, fguMESLEN, text, args);
279  va_end(args);
280  Message(0,txtbuf);
281 }
282 
283 void TGo4Log::Info(const char* text,...)
284 {
285  if(fgiIgnoreLevel>1) return;
286  Instance();
287  //TGo4LockGuard(fxMutex);
288  char txtbuf[fguMESLEN];
289  va_list args;
290  va_start(args, text);
291  vsnprintf(txtbuf, fguMESLEN, text, args);
292  va_end(args);
293  Message(1,txtbuf);
294 }
295 
296 void TGo4Log::Warn(const char* text,...)
297 {
298  if(fgiIgnoreLevel>2) return;
299  Instance();
300  //TGo4LockGuard(fxMutex);
301  char txtbuf[fguMESLEN];
302  va_list args;
303  va_start(args, text);
304  vsnprintf(txtbuf, fguMESLEN, text, args);
305  va_end(args);
306  Message(2,txtbuf);
307 }
308 
309 void TGo4Log::Error(const char* text,...)
310 {
311  Instance();
312  //TGo4LockGuard(fxMutex);
313  char txtbuf[fguMESLEN];
314  va_list args;
315  va_start(args, text);
316  vsnprintf(txtbuf, fguMESLEN, text, args);
317  va_end(args);
318  Message(3,txtbuf);
319 }
320 
321 
322 void TGo4Log::SetIgnoreLevel(Int_t level)
323 {
324  //TGo4LockGuard(fxMutex);
325  fgiIgnoreLevel=level;
326 }
327 
329 {
330  return fgiIgnoreLevel;
331 }
332 
333 const char* TGo4Log::GetLogname()
334 {
335  return fgxLogName.Data();
336 }
337 
339 {
340  return fgcDEFAULTLOG;
341 }
342 
343 const char* TGo4Log::GetPrintfArg(Int_t type_id)
344 {
345  switch (type_id) {
346  case kInt_t: return "%d";
347  case kUInt_t: return "%u";
348  case kLong_t: return "%ld";
349  case kULong_t: return "%lu";
350  case kLong64_t: return sizeof(long long int)==8 ? "%lld" : "%ld";
351  case kULong64_t: return sizeof(long long unsigned)==8 ? "%llu" : "%lu";
352  }
353 
354  return "%d";
355 }
356 
357 
358 void TGo4Log::OutputEnable(Bool_t on)
359 {
360  //TGo4LockGuard(fxMutex);
361  fgbOutputEnabled=on;
362 }
363 
365 {
366  return fgbOutputEnabled;
367 }
368 
369 void TGo4Log::LogfileEnable(Bool_t on)
370 {
371  //TGo4LockGuard(fxMutex);
373 }
374 
376 {
377  return fgbLogfileEnabled;
378 }
379 
380 void TGo4Log::AutoEnable(Bool_t on)
381 {
382  //TGo4LockGuard(fxMutex);
383  fgbAutoMode=on;
384 }
385 
387 {
388  return fgbAutoMode;
389 }
390 
391 void TGo4Log::OpenLogfile(const char* name, const char* headercomment, Bool_t appendmode)
392 {
393  //TGo4LockGuard(fxMutex);
394  try
395  {
396  CloseLogfile();
397  char txtbuf[fguMESLEN];
398  if(name==0)
399  // default: encode pid into filename
400  snprintf(txtbuf,fguMESLEN,"go4log-%d.txt", gSystem->GetPid());
401  else
402  snprintf(txtbuf,fguMESLEN,"%s",name);
403 
404  std::ofstream* lf = new std::ofstream(txtbuf, appendmode ? std::ios::app : std::ios::out);
405 
406  if(lf->fail()) {
407  LogfileEnable(kFALSE);
408  delete lf;
409  std::cerr <<"TGo4Log::OpenLogfile() - Error opening logfile "<< name << std::endl;
410  } else {
411  fgxLogfile = lf;
412  fgxLogName = txtbuf; // remember our last filename
413  }
414  // write headercomment into the first lines:
415  if(headercomment) WriteLogfile(headercomment, kFALSE);
416  } // try
417 
418  catch(std::exception& ex) // treat standard library exceptions
419  {
420  std::cerr <<"standard exception "<<ex.what()<<"in TGo4Log::OpenLogfile" << std::endl;
421  }
422  catch(...)
423  {
424  std::cerr <<"!!! Unexpected exception in TGo4Log::OpenLogfile !!!" << std::endl;
425  } // catch
426 }
427 
428 void TGo4Log::WriteLogfile(const char* text, Bool_t withtime)
429 {
430  //TGo4LockGuard(fxMutex);
431  if((text==0) || !fgbLogfileEnabled || (fgxLogfile==0)) return;
432  try {
433  if(withtime) {
434  TDatime now;
435  *((std::ofstream*)fgxLogfile) << now.AsSQLString() << ": ";
436  }
437  *((std::ofstream*)fgxLogfile) << text << std::endl;
438  }// try
439  catch(std::exception& ex) // treat standard library exceptions
440  {
441  std::cerr <<"standard exception "<<ex.what()<<"in TGo4Log::WriteLogfile" << std::endl;
442  }
443  catch(...)
444  {
445  std::cerr <<"!!! Unexpected exception in TGo4Log::WriteLogfile !!!" << std::endl;
446  } // catch
447 }
448 
450 {
451  //TGo4LockGuard(fxMutex);
452  if(fgxLogfile!=0)
453  {
454  try
455  {
456  delete (std::ofstream*)fgxLogfile;
457  fgxLogfile=0;
458  }
459  catch(std::exception& ex) // treat standard library exceptions
460  {
461  std::cerr <<"standard exception "<<ex.what()<<"in TGo4Log::CloseLogfile" << std::endl;
462  }
463  catch(...)
464  {
465  std::cerr <<"!!! Unexpected exception in TGo4Log::CloseLogfile !!!" << std::endl;
466  } //
467  }
468 }
static const char * GetLogname()
Definition: TGo4Log.cxx:333
static TGo4Log * Instance()
Definition: TGo4Log.cxx:87
static TGo4Log * fgxInstance
Definition: TGo4Log.h:194
virtual Bool_t Notify()
Definition: TGo4Log.cxx:63
static const char * fgcWARN
Definition: TGo4Log.h:169
static void WriteLogfile(const char *text, Bool_t withtime=kTRUE)
Definition: TGo4Log.cxx:428
static void CloseLogfile()
Definition: TGo4Log.cxx:449
static Bool_t IsOutputEnabled()
Definition: TGo4Log.cxx:364
static void Warn(const char *text,...)
Definition: TGo4Log.cxx:296
static const char * GetPrintfArg(Int_t type_id)
Definition: TGo4Log.cxx:343
static Bool_t fgbLogfileEnabled
Definition: TGo4Log.h:206
static const char * GetDefaultLogname()
Definition: TGo4Log.cxx:338
static Bool_t fgbAutoMode
Definition: TGo4Log.h:209
static void SetIgnoreLevel(Int_t level)
Definition: TGo4Log.cxx:322
static void OutputEnable(Bool_t on=kTRUE)
Definition: TGo4Log.cxx:358
static const char * fgcRIGHT
Definition: TGo4Log.h:160
static void OpenLogfile(const char *name=0, const char *headercomment=0, Bool_t appendmode=kFALSE)
Definition: TGo4Log.cxx:391
static const char * fgcDEBUG
Definition: TGo4Log.h:163
static Bool_t fgbOutputEnabled
Definition: TGo4Log.h:203
static TString fgsGO4SYS
Definition: TGo4Log.h:220
static int fgStdSave
redirected pipe for stdout
Definition: TGo4Log.h:225
static void ProcessRedirection(int kind=0)
Definition: TGo4Log.cxx:120
virtual ~TGo4Log()
Definition: TGo4Log.cxx:82
static void SetSniffer(TNamed *sniff)
Definition: TGo4Log.cxx:153
TLogTimer(Int_t millisec)
Definition: TGo4Log.cxx:61
static const char * fgcINFO
Definition: TGo4Log.h:166
TGo4Log()
Definition: TGo4Log.cxx:69
static const char * GO4INCPATH()
Definition: TGo4Log.cxx:181
static void EnableRedirection()
Definition: TGo4Log.cxx:95
static int fgStdPipe[2]
optional object to get all output via SetTitle method
Definition: TGo4Log.h:224
static Bool_t IsLogfileEnabled()
Definition: TGo4Log.cxx:375
static const char * fgcDEFAULTLOG
Definition: TGo4Log.h:175
static const char * Message(Int_t prio, const char *text,...)
Definition: TGo4Log.cxx:209
static Int_t fgiIgnoreLevel
Definition: TGo4Log.h:200
static TString fgxLogName
Definition: TGo4Log.h:218
static void Printf(Bool_t _stdout, const char *text)
Definition: TGo4Log.cxx:255
static TMutex * fgxMutex
Definition: TGo4Log.h:197
static void * fgxLogfile
Definition: TGo4Log.h:215
static Int_t GetIgnoreLevel()
Definition: TGo4Log.cxx:328
static TNamed * fgSniffer
value of GO4SYS during run
Definition: TGo4Log.h:222
static TString subGO4SYS(const char *subdir)
Definition: TGo4Log.cxx:192
static char fgcMessagetext[__MESSAGETEXTLENGTH__]
Definition: TGo4Log.h:212
static const char * fgcLEFT
Definition: TGo4Log.h:157
static const char * GO4SYS()
Definition: TGo4Log.cxx:158
static TLogTimer * fgTimer
saved file for stdout
Definition: TGo4Log.h:227
friend class TLogTimer
Definition: TGo4Log.h:188
static void AutoEnable(Bool_t on=kTRUE)
Definition: TGo4Log.cxx:380
#define __MESSAGETEXTLENGTH__
Definition: TGo4Log.h:23
static const char * fgcERR
Definition: TGo4Log.h:172
static void Error(const char *text,...)
Definition: TGo4Log.cxx:309
static Bool_t IsAutoEnabled()
Definition: TGo4Log.cxx:386
static void Info(const char *text,...)
Definition: TGo4Log.cxx:283
static void Debug(const char *text,...)
Definition: TGo4Log.cxx:270
static void LogfileEnable(Bool_t on=kTRUE)
Definition: TGo4Log.cxx:369