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