source: trunk/MagicSoft/Mars/mbase/MLog.cc@ 1886

Last change on this file since 1886 was 1863, checked in by tbretz, 22 years ago
*** empty log message ***
File size: 11.3 KB
Line 
1/* ======================================================================== *\
2!
3! *
4! * This file is part of MARS, the MAGIC Analysis and Reconstruction
5! * Software. It is distributed to you in the hope that it can be a useful
6! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
7! * It is distributed WITHOUT ANY WARRANTY.
8! *
9! * Permission to use, copy, modify and distribute this software and its
10! * documentation for any purpose is hereby granted without fee,
11! * provided that the above copyright notice appear in all copies and
12! * that both that copyright notice and this permission notice appear
13! * in supporting documentation. It is provided "as is" without express
14! * or implied warranty.
15! *
16!
17!
18! Author(s): Thomas Bretz 12/2000 <mailto:tbretz@uni-sw.gwdg.de>
19!
20! Copyright: MAGIC Software Development, 2000-2001
21!
22!
23\* ======================================================================== */
24
25
26//////////////////////////////////////////////////////////////////////////////
27// //
28// MLog //
29// //
30// This is what we call the logging-system. //
31// //
32// It is derived from the C++ streaming classes and can handle our //
33// logging. The log output can be redirected to stdout, stderr, any other //
34// stream or a root window. //
35// //
36// There is a global log-instance which you can use like cout, id is gLog. //
37// A log-instance of your choice (gLog by default) is destributed to all //
38// Task which are used in an eventloop, so that you can redirect the output //
39// of one eventloop to where you want.. //
40// //
41// The MLog stream has the advantage, that it can be used like the common //
42// C++ streams (for example cout). It can redirect the stream to different //
43// outputs (console, file, GUI) if necessary at the same time. //
44// //
45// It supports different debug levels. The debug level of the current //
46// stream contents is set by SetDebugLevel, the output level of the //
47// current stream can be set by SetOutputLevel. //
48// //
49// The header file MLogManip.h contains so called manipulators (like flush //
50// or setw from iomanip.h) which can manipulate these levels from within //
51// stream, for example: //
52// gLog << debug(3) << "Hallo World " << endl; //
53// sets the debug level of the following stream to 3 //
54// //
55// edev(), ddev() can be used to enable/disable an output device from //
56// within the stream. The enumerations are defined in MLog::_flags //
57// //
58// Commonly used abbreviations are also defined: //
59// dbginf Prints source file name and line number. Used for output //
60// which people may like to look up in the code //
61// all Is streamed to the output in any case. Used for outputs //
62// which are requested by the user (eg TObject::Print) //
63// err Should be used for fatal errors which stops the current //
64// processing, eg: //
65// gLog << err << "ERROR: TObject::Copy - Stopped" << endl; //
66// warn Warning means an error occured, but it is not clear whether //
67// this results further procesing or not. //
68// inf Informs the user about what's going on. Mostly usefull for //
69// debugging, but in general not necessary at all. //
70// //
71// gLog is a global stream defined like cout or cerr //
72// //
73//////////////////////////////////////////////////////////////////////////////
74
75#include "MLog.h"
76
77#include <stdlib.h> // mkstempe
78#include <fstream.h>
79#include <pthread.h>
80#include <TGListBox.h>
81
82#include "MLogManip.h"
83
84ClassImp(MLog);
85
86// root 3.02:
87// check for TObjectWarning, TObject::Info, gErrorIgnoreLevel
88
89//
90// This is the definition of the global log facility
91//
92MLog gLog;
93
94// --------------------------------------------------------------------------
95//
96// this strange usage of an unbufferd buffer is a workaround
97// to make it work on Alpha and Linux!
98//
99void MLog::Init()
100{
101 setp(&fBuffer, &fBuffer+1);
102 *this << '\0';
103
104 //
105 // Creat drawing semaphore
106 //
107 fMuxGui = new pthread_mutex_t;
108 pthread_mutex_init((pthread_mutex_t*)fMuxGui, NULL);
109}
110
111// --------------------------------------------------------------------------
112//
113// default constructor which initializes the streamer and sets the device
114// which is used for the output (i)
115//
116MLog::MLog(int i) : ostream(this), fPPtr(fBase), fEPtr(fBase+bsz), fOutputLevel(0), fDebugLevel((unsigned)-1), fDevice(i), fIsNull(kFALSE), fGuiLineId(0), fout(NULL), fOutAllocated(kFALSE), fgui(NULL), fNumLines(0)
117{
118 Init();
119}
120
121// --------------------------------------------------------------------------
122//
123// default constructor which initializes the streamer and sets the given
124// ofstream as the default output device
125//
126MLog::MLog(ofstream &out) : ostream(this), fPPtr(fBase), fEPtr(fBase+bsz), fOutputLevel(0), fDebugLevel((unsigned)-1), fDevice(eFile), fIsNull(kFALSE), fGuiLineId(0), fout(&out), fOutAllocated(kFALSE), fgui(NULL), fNumLines(0)
127{
128 Init();
129}
130
131// --------------------------------------------------------------------------
132//
133// default constructor which initializes the streamer and sets the given
134// TGListBox as the default output device
135//
136MLog::MLog(TGListBox &out) : ostream(this), fPPtr(fBase), fEPtr(fBase+bsz), fOutputLevel(0), fDebugLevel((unsigned)-1), fDevice(eGui), fGuiLineId(0), fout(NULL), fOutAllocated(kFALSE), fgui(&out), fNumLines(0)
137{
138 Init();
139}
140
141// --------------------------------------------------------------------------
142//
143// default constructor which initializes the streamer and opens a file with
144// the given name. Dependend on the flag the file is set as output device
145// or not.
146//
147MLog::MLog(const char *fname, int flag) : ostream(this), fPPtr(fBase), fEPtr(fBase+bsz), fOutputLevel(0), fDebugLevel((unsigned)-1), fDevice(eFile), fIsNull(kFALSE), fGuiLineId(0), fgui(NULL), fNumLines(0)
148{
149 Init();
150
151 AllocateFile(fname);
152 CheckFlag(eFile, flag);
153}
154
155// --------------------------------------------------------------------------
156//
157// Destructor, destroying the gui mutex.
158//
159MLog::~MLog()
160{
161 DeallocateFile();
162 pthread_mutex_destroy((pthread_mutex_t*)fMuxGui);
163}
164
165// --------------------------------------------------------------------------
166//
167// copyt constructor
168//
169MLog::MLog(MLog &log)
170{
171 fOutputLevel = log.fOutputLevel;
172 fDebugLevel = log.fDebugLevel;
173 fDevice = log.fDevice;
174}
175
176// --------------------------------------------------------------------------
177//
178// This is the function which writes the stream physically to a device.
179// If you want to add a new device this must be done here.
180//
181void MLog::WriteBuffer()
182{
183 //
184 // restart writing to the buffer at its first char
185 //
186 const int len = fPPtr - fBase;
187
188 fPPtr = fBase;
189
190 if (fIsNull)
191 return;
192
193 if (fDevice&eStdout)
194 cout.write(fBase, len);
195
196 if (fDevice&eStderr)
197 cerr.write(fBase, len);
198
199 if (fDevice&eFile && fout)
200 fout->write(fBase, len);
201
202 if (fDevice&eGui && fgui)
203 {
204 char **newstr = new char*[fNumLines+1];
205
206 for (int i=0; i<fNumLines; i++)
207 newstr[i] = fGuiLines[i];
208
209 if (fNumLines>0)
210 delete fGuiLines;
211
212 char *dummy = new char[len];
213 memcpy(dummy, fBase, len-1);
214 dummy[len-1]='\0';
215
216 newstr[fNumLines++] = dummy;
217
218 fGuiLines = newstr;
219 }
220}
221
222void MLog::UpdateGui()
223{
224 if (fNumLines==0)
225 return;
226
227 Lock();
228
229// cout << "/---------------------------------------" << endl;
230
231 for (int i=0; i<fNumLines; i++)
232 {
233 fgui->AddEntry(fGuiLines[i], fGuiLineId++);
234// cout << fGuiLines[i] << endl;
235 delete fGuiLines[i];
236 }
237
238 delete fGuiLines;
239
240// cout << "\\---------------------------------------" << endl;
241
242 fNumLines=0;
243
244 fgui->RemoveEntries(0, fGuiLineId-1000);
245 fgui->SetTopEntry(fGuiLineId-1);
246 fgui->SetBit(kHasChanged);
247
248 UnLock();
249}
250
251void MLog::Lock()
252{
253 pthread_mutex_lock((pthread_mutex_t*)fMuxGui);
254}
255
256void MLog::UnLock()
257{
258 pthread_mutex_unlock((pthread_mutex_t*)fMuxGui);
259}
260
261// --------------------------------------------------------------------------
262//
263// This is called to flush the buffer of the streaming devices
264//
265int MLog::sync()
266{
267 Lock();
268 WriteBuffer();
269 UnLock();
270
271 if (fDevice&eStdout)
272 cout.flush();
273
274 if (fDevice&eStderr)
275 cerr.flush();
276
277 if (fDevice&eFile && fout)
278 fout->flush();
279
280 return 0;
281}
282
283// --------------------------------------------------------------------------
284//
285// This function comes from streambuf and should
286// output the buffer to the device (flush, endl)
287// or handle a buffer overflow (too many chars)
288// If a real overflow happens i contains the next
289// chars which doesn't fit into the buffer anymore.
290// If the buffer is not really filled i is EOF(-1).
291//
292int MLog::overflow(int i) // i=EOF means not a real overflow
293{
294 //
295 // no output if
296 //
297 if (fOutputLevel <= fDebugLevel)
298 {
299 Lock();
300
301 *fPPtr++ = (char)i;
302
303 if (fPPtr == fEPtr)
304 WriteBuffer();
305
306 UnLock();
307 }
308
309 return 0;
310}
311
312// --------------------------------------------------------------------------
313//
314// Create a new instance of an file output stream
315// an set the corresponding flag
316//
317void MLog::AllocateFile(const char *fname)
318{
319 char *txt = (char*)"logXXXXXX";
320 fout = fname ? new ofstream(fname) : new ofstream(mkstemp(txt));
321 fOutAllocated = kTRUE;
322}
323
324// --------------------------------------------------------------------------
325//
326// if fout was allocated by this instance of MLooging
327// delete it.
328//
329void MLog::DeallocateFile()
330{
331 if (fOutAllocated)
332 delete fout;
333}
334
335// --------------------------------------------------------------------------
336//
337// if necessary delete the old in stance of the file
338// output stream and create a new one
339//
340void MLog::ReallocateFile(const char *fname)
341{
342 DeallocateFile();
343 AllocateFile(fname);
344}
345
346// --------------------------------------------------------------------------
347//
348// This function checks if a device should get enabled or disabled.
349//
350void MLog::CheckFlag(Flags_t chk, int flag)
351{
352 if (flag==-1)
353 return;
354
355 flag ? EnableOutputDevice(chk) : DisableOutputDevice(chk);
356}
Note: See TracBrowser for help on using the repository browser.