xref: /trunk/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