blob: 2bd03e5e1e325fdde08c4ba6862aee43c92d41b9 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sal.hxx"
#include <cstdarg>
#include <cstdio>
#include <stdio.h>
#include <stdarg.h>
#include <rtl/logfile.h>
#include <osl/process.h>
#ifndef _OSL_FILE_H_
#include <osl/time.h>
#endif
#include <osl/time.h>
#include <osl/mutex.hxx>
#include <rtl/bootstrap.h>
#include <rtl/ustring.hxx>
#ifndef _RTL_STRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif
#include <rtl/alloc.h>
#include "osl/thread.h"
#include <algorithm>
#ifdef _MSC_VER
#define vsnprintf _vsnprintf
#endif
using namespace rtl;
using namespace osl;
using namespace std;
namespace {
static oslFileHandle g_aFile = 0;
static sal_Bool g_bHasBeenCalled = sal_False;
static const sal_Int32 g_BUFFERSIZE = 4096;
static sal_Char *g_buffer = 0;
class LoggerGuard
{
public:
~LoggerGuard();
};
LoggerGuard::~LoggerGuard()
{
if( g_buffer )
{
sal_Int64 nWritten, nConverted =
sprintf( g_buffer, "closing log file at %06" SAL_PRIuUINT32, osl_getGlobalTimer() );
if( nConverted > 0 )
osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten );
osl_closeFile( g_aFile );
g_aFile = 0;
rtl_freeMemory( g_buffer );
g_buffer = 0;
g_bHasBeenCalled = sal_False;
}
}
// The destructor of this static LoggerGuard is "activated" by the assignment to
// g_buffer in init():
LoggerGuard loggerGuard;
Mutex & getLogMutex()
{
static Mutex *pMutex = 0;
if( !pMutex )
{
MutexGuard guard( Mutex::getGlobalMutex() );
if( ! pMutex )
{
static Mutex mutex;
pMutex = &mutex;
}
}
return *pMutex;
}
OUString getFileUrl( const OUString &name )
{
OUString aRet;
if ( osl_getFileURLFromSystemPath( name.pData, &aRet.pData )
!= osl_File_E_None )
{
OSL_ASSERT( false );
}
OUString aWorkingDirectory;
osl_getProcessWorkingDir( &(aWorkingDirectory.pData) );
osl_getAbsoluteFileURL( aWorkingDirectory.pData, aRet.pData, &(aRet.pData) );
return aRet;
}
void init() {
if( !g_bHasBeenCalled )
{
MutexGuard guard( getLogMutex() );
if( ! g_bHasBeenCalled )
{
OUString name( RTL_CONSTASCII_USTRINGPARAM( "RTL_LOGFILE" ) );
OUString value;
if( rtl_bootstrap_get( name.pData, &value.pData, 0 ) )
{
// Obtain process id.
oslProcessIdentifier aProcessId = 0;
oslProcessInfo info;
info.Size = sizeof (oslProcessInfo);
if (osl_getProcessInfo (0, osl_Process_IDENTIFIER, &info) == osl_Process_E_None)
aProcessId = info.Ident;
// Construct name of log file and open the file.
OUStringBuffer buf( 128 );
buf.append( value );
// if the filename ends with .nopid, the incoming filename is not modified
if( value.getLength() < 6 /* ".nopid" */ ||
rtl_ustr_ascii_compare_WithLength(
value.getStr() + (value.getLength()-6) , 6 , ".nopid" ) )
{
buf.appendAscii( "_" );
buf.append( (sal_Int32) aProcessId );
buf.appendAscii( ".log" );
}
OUString o = getFileUrl( buf.makeStringAndClear() );
oslFileError e = osl_openFile(
o.pData, &g_aFile, osl_File_OpenFlag_Write|osl_File_OpenFlag_Create);
if( osl_File_E_None == e )
{
TimeValue aCurrentTime;
g_buffer = ( sal_Char * ) rtl_allocateMemory( g_BUFFERSIZE );
sal_Int64 nConverted = 0;
if (osl_getSystemTime (&aCurrentTime))
{
nConverted = (sal_Int64 ) sprintf (
g_buffer,
"opening log file %f seconds past January 1st 1970\n"
"corresponding to %" SAL_PRIuUINT32 " ms after timer start\n",
aCurrentTime.Seconds + 1e-9 * aCurrentTime.Nanosec,
osl_getGlobalTimer());
if( nConverted > 0 )
{
sal_Int64 nWritten;
osl_writeFile( g_aFile, g_buffer, nConverted , (sal_uInt64 *)&nWritten );
}
}
nConverted = sprintf (g_buffer, "Process id is %" SAL_PRIuUINT32 "\n", aProcessId);
if( nConverted )
{
sal_Int64 nWritten;
osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64 *)&nWritten );
}
}
else
{
OSL_TRACE( "Couldn't open logfile %s(%d)" , o.getStr(), e );
}
}
g_bHasBeenCalled = sal_True;
}
}
}
}
extern "C" void SAL_CALL rtl_logfile_trace ( const char *pszFormat, ... )
{
init();
if( g_buffer )
{
va_list args;
va_start(args, pszFormat);
{
sal_Int64 nConverted, nWritten;
MutexGuard guard( getLogMutex() );
nConverted = vsnprintf( g_buffer , g_BUFFERSIZE, pszFormat, args );
nConverted = (nConverted > g_BUFFERSIZE ? g_BUFFERSIZE : nConverted );
if( nConverted > 0 )
osl_writeFile( g_aFile, g_buffer, nConverted, (sal_uInt64*)&nWritten );
}
va_end(args);
}
}
extern "C" void SAL_CALL rtl_logfile_longTrace(char const * format, ...) {
init();
if (g_buffer != 0) {
sal_uInt32 time = osl_getGlobalTimer();
oslThreadIdentifier threadId = osl_getThreadIdentifier(0);
va_list args;
va_start(args, format);
{
MutexGuard g(getLogMutex());
int n1 = snprintf(
g_buffer, g_BUFFERSIZE, "%06" SAL_PRIuUINT32 " %" SAL_PRIuUINT32 " ", time, threadId);
if (n1 >= 0) {
sal_uInt64 n2;
osl_writeFile(
g_aFile, g_buffer,
static_cast< sal_uInt64 >(
std::min(n1, static_cast< int >(g_BUFFERSIZE))),
&n2);
n1 = vsnprintf(g_buffer, g_BUFFERSIZE, format, args);
if (n1 > 0) {
osl_writeFile(
g_aFile, g_buffer,
static_cast< sal_uInt64 >(
std::min(n1, static_cast< int >(g_BUFFERSIZE))),
&n2);
}
}
}
va_end(args);
}
}
extern "C" sal_Bool SAL_CALL rtl_logfile_hasLogFile( void ) {
init();
return g_buffer != 0;
}