update dev300-m58
[ooovba.git] / configmgr / source / misc / tracer.cxx
blob0632ce08870b1249cb3d76bc2002f0a5369e33d7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tracer.cxx,v $
10 * $Revision: 1.21 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_configmgr.hxx"
34 // SUNPRO5 does not like the following to be done after including stdio.h, that's why it's here at the very
35 // beginning of the file
36 #undef _TIME_T_DEFINED
37 #include <time.h>
38 #include <rtl/string.hxx>
39 #include <map>
41 #include "tracer.hxx"
43 #ifdef CFG_ENABLE_TRACING
45 #include <cstdarg>
46 #include <stdlib.h>
47 #include <ctype.h>
48 #include <string.h>
50 #include <osl/process.h>
51 #include <osl/thread.h>
52 #include <osl/diagnose.h>
53 #include <rtl/ustring.hxx>
54 #include <rtl/instance.hxx>
56 namespace configmgr
59 extern "C"
61 static void call_freeThreadData(void*);
64 struct OTracerSetup
66 enum {
67 INFO = 0x01,
68 WARNING = 0x02,
69 ERROR = 0x04,
70 LEVEL_MASK = 0x0f,
72 TIME = 0x10,
73 THREAD = 0x20,
74 DATA_MASK = 0xf0
77 sal_uInt32 m_nTraceMask;
78 FILE* m_pOutputMedium;
79 sal_Bool m_bInitialized;
80 oslThreadKey m_nThreadKey;
82 ::std::map< ::rtl::OString, void*, ::std::less< ::rtl::OString > > m_aDevices;
84 OTracerSetup()
85 :m_nTraceMask(WARNING | ERROR)
86 ,m_pOutputMedium(NULL)
87 ,m_bInitialized(sal_False)
89 m_nThreadKey = ::osl_createThreadKey(call_freeThreadData);
91 ~OTracerSetup()
93 ::osl_destroyThreadKey(m_nThreadKey);
96 bool isTracing(sal_uInt32 nTraceValue) const
97 { return (nTraceValue & this->m_nTraceMask) == nTraceValue; }
99 void setTracing(sal_uInt32 nTraceValue)
100 { this->m_nTraceMask |= nTraceValue; }
102 void setTracing(sal_uInt32 nTraceValue, sal_uInt32 nMask)
104 OSL_ENSURE( (nTraceValue&nMask) == nTraceValue, "Flags being set must be part of mask");
105 this->m_nTraceMask &= ~nMask;
106 this->m_nTraceMask |= nTraceValue;
109 sal_Int32& indentDepth();
111 struct ThreadData
113 ThreadData() : m_nIndentDepth(0) {}
114 sal_Int32 m_nIndentDepth;
117 ThreadData& ensureThreadData();
118 static void freeThreadData(void*p);
121 //==========================================================================
122 //= OConfigTracer
123 //==========================================================================
124 OTracerSetup* OConfigTracer::s_pImpl = NULL;
125 #ifdef WNT
126 timeb OConfigTracer::s_aStartTime;
127 #else
128 timeval OConfigTracer::s_aStartTime;
129 #endif
131 ::osl::Mutex & OConfigTracer::getMutex()
133 return rtl::Static<osl::Mutex,OConfigTracer>::get();
135 //--------------------------------------------------------------------------
136 void OConfigTracer::startGlobalTimer()
138 #ifdef WNT
139 ftime( &s_aStartTime );
140 #else
141 gettimeofday( &s_aStartTime, NULL );
142 #endif
145 //--------------------------------------------------------------------------
146 sal_uInt32 OConfigTracer::getGlobalTimer()
148 #ifdef WNT
149 struct timeb currentTime;
150 sal_uInt32 nSeconds;
151 ftime( &currentTime );
152 nSeconds = (sal_uInt32)( currentTime.time - s_aStartTime.time );
153 return ( nSeconds * 1000 ) + (long)( currentTime.millitm - s_aStartTime.millitm );
154 #else
155 struct timeval currentTime;
156 sal_uInt32 nSeconds;
157 gettimeofday( &currentTime, NULL );
158 nSeconds = (sal_uInt32)( currentTime.tv_sec - s_aStartTime.tv_sec );
159 return ( nSeconds * 1000 ) + (long)( currentTime.tv_usec - s_aStartTime.tv_usec )/1000;
160 #endif
163 //--------------------------------------------------------------------------
164 sal_Int32& OTracerSetup::indentDepth()
166 return ensureThreadData().m_nIndentDepth;
169 //--------------------------------------------------------------------------
170 OTracerSetup::ThreadData& OTracerSetup::ensureThreadData()
172 void * pThreadData = ::osl_getThreadKeyData(m_nThreadKey);
174 OTracerSetup::ThreadData* pRet
175 = static_cast< OTracerSetup::ThreadData * >(pThreadData);
177 if (pRet == NULL)
179 pThreadData = pRet = new ThreadData();
181 if (!::osl_setThreadKeyData(m_nThreadKey,pThreadData))
183 OSL_ENSURE(false, "Cannot create per-thread data for tracing");
184 freeThreadData(pThreadData);
186 static ThreadData sharedThreadData;
187 pRet = &sharedThreadData;
189 else
190 OSL_ASSERT( pThreadData == ::osl_getThreadKeyData(m_nThreadKey) );
192 OSL_ASSERT( pRet != NULL );
195 return *pRet;
198 static void call_freeThreadData( void* p )
200 OTracerSetup::freeThreadData( p );
203 //--------------------------------------------------------------------------
204 void OTracerSetup::freeThreadData(void* p)
206 delete static_cast< OTracerSetup::ThreadData * > (p);
209 //--------------------------------------------------------------------------
210 void OConfigTracer::ensureData()
212 if (s_pImpl)
213 return;
214 s_pImpl = new OTracerSetup;
217 //--------------------------------------------------------------------------
218 void OConfigTracer::inc()
220 ::osl::MutexGuard aGuard(getMutex());
221 ensureData();
222 ++s_pImpl->indentDepth();
225 //--------------------------------------------------------------------------
226 void OConfigTracer::dec()
228 ::osl::MutexGuard aGuard(getMutex());
229 ensureData();
230 --s_pImpl->indentDepth();
233 //--------------------------------------------------------------------------
234 void OConfigTracer::traceInfo(const sal_Char* _pFormat, ...)
236 ::osl::MutexGuard aGuard(getMutex());
237 ensureData();
238 ensureInitalized();
239 if (s_pImpl->isTracing(OTracerSetup::INFO) )
243 va_list args;
244 va_start(args, _pFormat);
245 implTrace("info", _pFormat, args);
246 va_end(args);
249 #if OSL_DEBUG_LEVEL > 0
250 //--------------------------------------------------------------------------
251 void OConfigTracer::traceWarning(const sal_Char* _pFormat, ...)
253 ::osl::MutexGuard aGuard(getMutex());
254 ensureData();
255 ensureInitalized();
256 if (s_pImpl->isTracing(OTracerSetup::WARNING))
258 va_list args;
259 va_start(args, _pFormat);
260 implTrace("warning", _pFormat, args);
261 va_end(args);
265 //--------------------------------------------------------------------------
266 void OConfigTracer::traceError(const sal_Char* _pFormat, ...)
268 ::osl::MutexGuard aGuard(getMutex());
269 ensureData();
270 ensureInitalized();
271 if (s_pImpl->isTracing(OTracerSetup::ERROR))
273 va_list args;
274 va_start(args, _pFormat);
275 implTrace("error", _pFormat, args);
276 va_end(args);
279 #endif
280 //--------------------------------------------------------------------------
281 void OConfigTracer::indent()
283 sal_Int32 nIndent = s_pImpl->indentDepth();
284 for (sal_Int32 i=0; i<nIndent; ++i)
285 fprintf(s_pImpl->m_pOutputMedium, " ");
288 //--------------------------------------------------------------------------
289 FILE* disambiguate(const ::rtl::OString& _rFileName)
291 FILE* pExistenceCheck = NULL;
292 sal_Int32 i = 1;
293 ::rtl::OString sLoop;
294 while (i <= 256)
296 sLoop = _rFileName;
297 sLoop += ".";
298 sLoop += ::rtl::OString::valueOf(i);
300 pExistenceCheck = fopen(sLoop.getStr(), "r");
301 if (!pExistenceCheck)
302 // does not exist
303 return fopen(sLoop.getStr(), "w+");
305 // already exists, try the next name
306 fclose(pExistenceCheck);
307 ++i;
310 // could not open such a file
311 return NULL;
314 //--------------------------------------------------------------------------
315 void OConfigTracer::ensureInitalized()
317 if (s_pImpl->m_bInitialized)
318 return;
320 s_pImpl->m_bInitialized = sal_True;
322 char* pSettings = getenv("ENVCFGFLAGS");
323 if (!pSettings)
324 return;
326 /* currently recognized structure :
327 + switches have to be separated by whitespaces
328 + valid switches are:
329 -m[e|o|f<file>] - output to stderr (e), stdout (o) or a file (f). In the latter case the whole rest
330 of the param ('til the next one, means 'til the next whitespace) is the filename
331 -t{i,w,e,p,d}* - type of output : i includes infos, w includes warnings, e includes errors
332 content : p includes timestamp, d includes thread-id
335 s_pImpl->m_pOutputMedium = stderr;
336 s_pImpl->setTracing(0, OTracerSetup::LEVEL_MASK);
337 s_pImpl->setTracing(0, OTracerSetup::DATA_MASK);
339 char* pParamLoop = pSettings;
340 while (*pParamLoop)
342 while (!isspace(*pParamLoop) && *pParamLoop)
343 ++pParamLoop;
345 sal_Int32 nLen = pParamLoop - pSettings;
346 if ((nLen > 1) && (*pSettings == '-'))
348 ++pSettings;
349 switch (*pSettings)
351 case 'm':
352 case 'w':
353 if (nLen > 2)
355 ++pSettings;
356 switch (*pSettings)
358 case 'e':
359 s_pImpl->m_pOutputMedium = stderr;
360 break;
361 case 'o':
362 s_pImpl->m_pOutputMedium = stdout;
363 break;
364 case 'f':
366 ++pSettings;
367 // copy the filename into an own buffer
368 ::rtl::OString sFileName(pSettings, pParamLoop - pSettings);
370 // open the file
371 s_pImpl->m_pOutputMedium = disambiguate(sFileName);
373 break;
377 break;
378 case 'd':
379 { // assign a virtual device
380 // copy the device assingment description
381 ::rtl::OString sDescription(pSettings + 1, pParamLoop - pSettings - 1);
382 sal_Int32 nSep = sDescription.indexOf(':');
383 if (-1 == nSep)
384 break; // invalid format
386 ::rtl::OString sVirtualDeviceName, sFileName;
387 sVirtualDeviceName = sDescription.copy(0, nSep);
388 sFileName = sDescription.copy(nSep + 1);
390 FILE* pVirtualDevice = disambiguate(sFileName);
391 if (pVirtualDevice)
392 s_pImpl->m_aDevices[sVirtualDeviceName] = pVirtualDevice;
394 case 't':
396 ++pSettings;
397 while (pSettings != pParamLoop)
399 switch (*pSettings)
401 case 'i': s_pImpl->setTracing( OTracerSetup::INFO ); break;
402 case 'w': s_pImpl->setTracing( OTracerSetup::WARNING ); break;
403 case 'e': s_pImpl->setTracing( OTracerSetup::ERROR ); break;
404 case 'p': s_pImpl->setTracing( OTracerSetup::TIME );
405 startGlobalTimer();
406 break;
407 case 'd': s_pImpl->setTracing( OTracerSetup::THREAD ); break;
409 ++pSettings;
415 if (!*pParamLoop)
416 break;
418 ++pParamLoop;
419 pSettings = pParamLoop;
422 // trace some initial information
423 CFG_TRACE_INFO_NI("initialization: process id: 0x%08X", osl_getProcess(0));
424 ::rtl::OUString sExecutable;
425 osl_getExecutableFile(&sExecutable.pData);
426 CFG_TRACE_INFO_NI("initialization: executable file name: %s", OUSTRING2ASCII(sExecutable));
429 //--------------------------------------------------------------------------
430 //-----------------------------------------------------------
431 // need raw unsigned int to safely printf a value
432 static inline
433 unsigned int getThreadID()
435 oslThreadIdentifier nRealThreadID = ::osl_getThreadIdentifier(NULL);
437 return nRealThreadID; // if this loses data, we can still hope that lsb is changing between thraeds
440 //--------------------------------------------------------------------------
441 void OConfigTracer::implTrace(const sal_Char* _pType, const sal_Char* _pFormat, va_list args)
443 ensureInitalized();
444 if (!s_pImpl->m_pOutputMedium)
445 // no tracing enabled
446 return;
448 if (_pType && strlen(_pType))
450 if (s_pImpl->isTracing(OTracerSetup::THREAD))
452 fprintf(s_pImpl->m_pOutputMedium, "[%04x] ", getThreadID());
455 fprintf(s_pImpl->m_pOutputMedium, "%s ", _pType);
457 if (s_pImpl->isTracing(OTracerSetup::TIME))
459 fprintf(s_pImpl->m_pOutputMedium, "(%06" SAL_PRIuUINT32 ")", getGlobalTimer());
462 fprintf(s_pImpl->m_pOutputMedium, ": ");
464 indent();
466 vfprintf(s_pImpl->m_pOutputMedium, _pFormat, args);
467 fprintf(s_pImpl->m_pOutputMedium,"\n");
468 fflush(s_pImpl->m_pOutputMedium);
471 } // namespace configmgr
473 #endif // CFG_ENABLE_TRACING