xref: /AOO41X/main/sal/rtl/source/logfile.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sal.hxx"
30 #include <cstdarg>
31 #include <cstdio>
32 #include <stdio.h>
33 #include <stdarg.h>
34 
35 #include <rtl/logfile.h>
36 #include <osl/process.h>
37 #ifndef _OSL_FILE_H_
38 #include <osl/time.h>
39 #endif
40 #include <osl/time.h>
41 #include <osl/mutex.hxx>
42 #include <rtl/bootstrap.h>
43 #include <rtl/ustring.hxx>
44 #ifndef _RTL_STRBUF_HXX_
45 #include <rtl/ustrbuf.hxx>
46 #endif
47 #include <rtl/alloc.h>
48 #include "osl/thread.h"
49 
50 #include <algorithm>
51 
52 #ifdef _MSC_VER
53 #define vsnprintf _vsnprintf
54 #endif
55 
56 using namespace rtl;
57 using namespace osl;
58 using namespace std;
59 
60 namespace {
61 
62 static oslFileHandle g_aFile = 0;
63 static sal_Bool g_bHasBeenCalled = sal_False;
64 static const sal_Int32 g_BUFFERSIZE = 4096;
65 static sal_Char *g_buffer = 0;
66 
67 class	LoggerGuard
68 {
69 public:
70 	~LoggerGuard();
71 };
72 
73 LoggerGuard::~LoggerGuard()
74 {
75 	if( g_buffer )
76 	{
77 		sal_Int64 nWritten, nConverted =
78 			sprintf( g_buffer, "closing log file at %06" SAL_PRIuUINT32, osl_getGlobalTimer() );
79 		if( nConverted > 0 )
80 			osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten );
81 		osl_closeFile( g_aFile );
82 		g_aFile = 0;
83 
84 		rtl_freeMemory( g_buffer );
85 		g_buffer = 0;
86 		g_bHasBeenCalled = sal_False;
87 	}
88 }
89 
90 // The destructor of this static LoggerGuard is "activated" by the assignment to
91 // g_buffer in init():
92 LoggerGuard loggerGuard;
93 
94 Mutex & getLogMutex()
95 {
96 	static Mutex *pMutex = 0;
97 	if( !pMutex )
98 	{
99 		MutexGuard guard( Mutex::getGlobalMutex() );
100 		if( ! pMutex )
101 		{
102 			static Mutex mutex;
103 			pMutex = &mutex;
104 		}
105 	}
106 	return *pMutex;
107 }
108 
109 OUString getFileUrl( const OUString &name )
110 {
111 	OUString aRet;
112 	if ( osl_getFileURLFromSystemPath( name.pData, &aRet.pData )
113          != osl_File_E_None )
114     {
115         OSL_ASSERT( false );
116     }
117 
118 	OUString aWorkingDirectory;
119 	osl_getProcessWorkingDir( &(aWorkingDirectory.pData) );
120 	osl_getAbsoluteFileURL( aWorkingDirectory.pData, aRet.pData, &(aRet.pData) );
121 
122 	return aRet;
123 }
124 
125 void init() {
126 	if( !g_bHasBeenCalled )
127 	{
128 		MutexGuard guard( getLogMutex() );
129 		if( ! g_bHasBeenCalled )
130 		{
131 			OUString name( RTL_CONSTASCII_USTRINGPARAM( "RTL_LOGFILE" ) );
132 			OUString value;
133 			if( rtl_bootstrap_get( name.pData, &value.pData, 0 ) )
134 			{
135 				//	Obtain process id.
136 				oslProcessIdentifier aProcessId = 0;
137 				oslProcessInfo info;
138 				info.Size = sizeof (oslProcessInfo);
139 				if (osl_getProcessInfo (0, osl_Process_IDENTIFIER, &info) == osl_Process_E_None)
140 					aProcessId = info.Ident;
141 
142 				//	Construct name of log file and open the file.
143 				OUStringBuffer buf( 128 );
144 				buf.append( value );
145 
146 				// if the filename ends with .nopid, the incoming filename is not modified
147 				if( value.getLength() < 6 /* ".nopid" */ ||
148 					rtl_ustr_ascii_compare_WithLength(
149 						value.getStr() + (value.getLength()-6) , 6 , ".nopid" ) )
150 				{
151 					buf.appendAscii( "_" );
152 					buf.append( (sal_Int32) aProcessId );
153 					buf.appendAscii( ".log" );
154 				}
155 
156 				OUString o = getFileUrl( buf.makeStringAndClear() );
157 				oslFileError e = osl_openFile(
158 					o.pData, &g_aFile, osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
159 
160 				if( osl_File_E_None == e )
161 				{
162 					TimeValue aCurrentTime;
163 					g_buffer = ( sal_Char * ) rtl_allocateMemory( g_BUFFERSIZE );
164 					sal_Int64 nConverted = 0;
165 					if (osl_getSystemTime (&aCurrentTime))
166 					{
167 						nConverted = (sal_Int64 ) sprintf (
168 								g_buffer,
169 								"opening log file %f seconds past January 1st 1970\n"
170 								"corresponding to %" SAL_PRIuUINT32 " ms after timer start\n",
171 								aCurrentTime.Seconds + 1e-9 * aCurrentTime.Nanosec,
172 								osl_getGlobalTimer());
173 
174 						if( nConverted > 0 )
175                         {
176                             sal_Int64 nWritten;
177 							osl_writeFile( g_aFile, g_buffer, nConverted , (sal_uInt64 *)&nWritten );
178                         }
179 					}
180 
181 					nConverted = sprintf (g_buffer, "Process id is %" SAL_PRIuUINT32 "\n", aProcessId);
182 					if( nConverted )
183                     {
184                         sal_Int64 nWritten;
185 						osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten );
186                     }
187 				}
188 				else
189 				{
190 					OSL_TRACE( "Couldn't open logfile %s(%d)" , o.getStr(), e );
191 				}
192 			}
193 			g_bHasBeenCalled = sal_True;
194 		}
195 	}
196 }
197 
198 }
199 
200 extern "C" void	SAL_CALL rtl_logfile_trace	( const char *pszFormat, ... )
201 {
202 	init();
203 	if( g_buffer )
204 	{
205 		va_list args;
206 		va_start(args, pszFormat);
207 		{
208 			sal_Int64 nConverted, nWritten;
209 			MutexGuard guard( getLogMutex() );
210 			nConverted = vsnprintf( g_buffer , g_BUFFERSIZE, pszFormat, args );
211 			nConverted = (nConverted > g_BUFFERSIZE ? g_BUFFERSIZE : nConverted );
212 			if( nConverted > 0 )
213 				osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64*)&nWritten );
214 		}
215 		va_end(args);
216 	}
217 }
218 
219 extern "C" void SAL_CALL rtl_logfile_longTrace(char const * format, ...) {
220     init();
221     if (g_buffer != 0) {
222         sal_uInt32 time = osl_getGlobalTimer();
223         oslThreadIdentifier threadId = osl_getThreadIdentifier(0);
224         va_list args;
225         va_start(args, format);
226         {
227             MutexGuard g(getLogMutex());
228             int n1 = snprintf(
229                 g_buffer, g_BUFFERSIZE, "%06" SAL_PRIuUINT32 " %" SAL_PRIuUINT32 " ", time, threadId);
230             if (n1 >= 0) {
231                 sal_uInt64 n2;
232                 osl_writeFile(
233                     g_aFile, g_buffer,
234                     static_cast< sal_uInt64 >(
235                         std::min(n1, static_cast< int >(g_BUFFERSIZE))),
236                     &n2);
237                 n1 = vsnprintf(g_buffer, g_BUFFERSIZE, format, args);
238                 if (n1 > 0) {
239                     osl_writeFile(
240                         g_aFile, g_buffer,
241                         static_cast< sal_uInt64 >(
242                             std::min(n1, static_cast< int >(g_BUFFERSIZE))),
243                         &n2);
244                 }
245             }
246         }
247         va_end(args);
248     }
249 }
250 
251 extern "C" sal_Bool SAL_CALL rtl_logfile_hasLogFile( void ) {
252 	init();
253     return g_buffer != 0;
254 }
255