1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: tracer.cxx,v $
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
38 #include <rtl/string.hxx>
43 #ifdef CFG_ENABLE_TRACING
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>
61 static void call_freeThreadData(void*);
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
;
85 :m_nTraceMask(WARNING
| ERROR
)
86 ,m_pOutputMedium(NULL
)
87 ,m_bInitialized(sal_False
)
89 m_nThreadKey
= ::osl_createThreadKey(call_freeThreadData
);
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();
113 ThreadData() : m_nIndentDepth(0) {}
114 sal_Int32 m_nIndentDepth
;
117 ThreadData
& ensureThreadData();
118 static void freeThreadData(void*p
);
121 //==========================================================================
123 //==========================================================================
124 OTracerSetup
* OConfigTracer::s_pImpl
= NULL
;
126 timeb
OConfigTracer::s_aStartTime
;
128 timeval
OConfigTracer::s_aStartTime
;
131 ::osl::Mutex
& OConfigTracer::getMutex()
133 return rtl::Static
<osl::Mutex
,OConfigTracer
>::get();
135 //--------------------------------------------------------------------------
136 void OConfigTracer::startGlobalTimer()
139 ftime( &s_aStartTime
);
141 gettimeofday( &s_aStartTime
, NULL
);
145 //--------------------------------------------------------------------------
146 sal_uInt32
OConfigTracer::getGlobalTimer()
149 struct timeb currentTime
;
151 ftime( ¤tTime
);
152 nSeconds
= (sal_uInt32
)( currentTime
.time
- s_aStartTime
.time
);
153 return ( nSeconds
* 1000 ) + (long)( currentTime
.millitm
- s_aStartTime
.millitm
);
155 struct timeval currentTime
;
157 gettimeofday( ¤tTime
, 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;
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
);
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
;
190 OSL_ASSERT( pThreadData
== ::osl_getThreadKeyData(m_nThreadKey
) );
192 OSL_ASSERT( pRet
!= NULL
);
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()
214 s_pImpl
= new OTracerSetup
;
217 //--------------------------------------------------------------------------
218 void OConfigTracer::inc()
220 ::osl::MutexGuard
aGuard(getMutex());
222 ++s_pImpl
->indentDepth();
225 //--------------------------------------------------------------------------
226 void OConfigTracer::dec()
228 ::osl::MutexGuard
aGuard(getMutex());
230 --s_pImpl
->indentDepth();
233 //--------------------------------------------------------------------------
234 void OConfigTracer::traceInfo(const sal_Char
* _pFormat
, ...)
236 ::osl::MutexGuard
aGuard(getMutex());
239 if (s_pImpl
->isTracing(OTracerSetup::INFO
) )
244 va_start(args
, _pFormat
);
245 implTrace("info", _pFormat
, args
);
249 #if OSL_DEBUG_LEVEL > 0
250 //--------------------------------------------------------------------------
251 void OConfigTracer::traceWarning(const sal_Char
* _pFormat
, ...)
253 ::osl::MutexGuard
aGuard(getMutex());
256 if (s_pImpl
->isTracing(OTracerSetup::WARNING
))
259 va_start(args
, _pFormat
);
260 implTrace("warning", _pFormat
, args
);
265 //--------------------------------------------------------------------------
266 void OConfigTracer::traceError(const sal_Char
* _pFormat
, ...)
268 ::osl::MutexGuard
aGuard(getMutex());
271 if (s_pImpl
->isTracing(OTracerSetup::ERROR
))
274 va_start(args
, _pFormat
);
275 implTrace("error", _pFormat
, args
);
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
;
293 ::rtl::OString sLoop
;
298 sLoop
+= ::rtl::OString::valueOf(i
);
300 pExistenceCheck
= fopen(sLoop
.getStr(), "r");
301 if (!pExistenceCheck
)
303 return fopen(sLoop
.getStr(), "w+");
305 // already exists, try the next name
306 fclose(pExistenceCheck
);
310 // could not open such a file
314 //--------------------------------------------------------------------------
315 void OConfigTracer::ensureInitalized()
317 if (s_pImpl
->m_bInitialized
)
320 s_pImpl
->m_bInitialized
= sal_True
;
322 char* pSettings
= getenv("ENVCFGFLAGS");
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
;
342 while (!isspace(*pParamLoop
) && *pParamLoop
)
345 sal_Int32 nLen
= pParamLoop
- pSettings
;
346 if ((nLen
> 1) && (*pSettings
== '-'))
359 s_pImpl
->m_pOutputMedium
= stderr
;
362 s_pImpl
->m_pOutputMedium
= stdout
;
367 // copy the filename into an own buffer
368 ::rtl::OString
sFileName(pSettings
, pParamLoop
- pSettings
);
371 s_pImpl
->m_pOutputMedium
= disambiguate(sFileName
);
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(':');
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
);
392 s_pImpl
->m_aDevices
[sVirtualDeviceName
] = pVirtualDevice
;
397 while (pSettings
!= pParamLoop
)
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
);
407 case 'd': s_pImpl
->setTracing( OTracerSetup::THREAD
); break;
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
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
)
444 if (!s_pImpl
->m_pOutputMedium
)
445 // no tracing enabled
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
, ": ");
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