Linux GCC 開發入門(2) -- 日誌輸出功能 從windows移植 NCTRACE


windows log



linux


Header file  ( logutils.h )

#ifndef __LINUX_LOGUTILS_H__
#define __LINUX_LOGUTILS_H__

#define NCTRACE NcTrace
#define MYTRACE NcTrace
#define NCTRACE2 NcTrace2
#define MYTRACE2 NcTrace2
#define HDTRACE	HdTrace

//2016-07-03
//Linux Version. -- UNICODE is yet to be done.

//2014-8 Option to Send text to window display and Control( Stop ).
//See GenericWin.
//          Init with window display. add InitDefaultLogFile

//2013-5 Add file name for NCTRACE.
bool NcSetLogFile     ( const char * sFile );
void NcSetLogFileSize ( int iSize );


int get_executable_path( char* process_path, size_t len);
bool NcTrace( const char * lpszFormat , ... );
bool NcTrace2(const char * lpszLogFileName, const char * lpszFormat, ... );
//bool HdTrace( const char * lpszFormat , ... );



#endif


implementation:  (logutils.cpp)

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "logutils.h"

//2016-07-03 
//Linux VERSION. -- UNICODE is yet to be done.

//2013-6-9  Updated --  Add Log File name.  In Unicode Build use ANSI form compatible.
//2014-8-20 Updated --  
//          Init with window display. add InitDefaultLogFile
static int  LOG_FILE_SIZE =  (4*1024*1024);


#define CHAR_TYPE   char

#define MAX_PATH  256

static 	CHAR_TYPE  g_szAppPath[MAX_PATH] = { 0 } ;
static 	CHAR_TYPE  g_szBakFile[MAX_PATH] = { 0 } ;
static  bool       g_bInitNcTrace = false;


static pthread_mutex_t  s_mtx_log;

void NcSetLogFileSize( int iSize )
{
	if ( iSize >= ( 64<<10 ) )
		LOG_FILE_SIZE = iSize;
}


bool NcSetLogFile( const CHAR_TYPE * sFile )
{
	if ( !g_bInitNcTrace )
	{
		pthread_mutex_init( &s_mtx_log, NULL );	
	}


	pthread_mutex_lock( &s_mtx_log );

	if ( !sFile || strlen( sFile ) < 2 )
		return false;

	if ( sFile != g_szAppPath )
		strcpy( g_szAppPath, sFile );

	strcpy( g_szBakFile, sFile );

	CHAR_TYPE * pDot = (CHAR_TYPE *)strrchr( g_szBakFile, ('.') );
	if ( pDot  )
	{
		pDot[0] = 0;
	}
	strcat( g_szBakFile,  "_0.txt"  );



	g_bInitNcTrace = true;

	pthread_mutex_unlock( &s_mtx_log );

	return true;
}



static int get_executable_dir( char* processdir,  size_t len)
{
	char* path_end;
	int ifunc;

	ifunc = readlink("/proc/self/exe", processdir, len );
	if( ifunc  <= 0 )
		return -1;

	path_end = strrchr(processdir,  '/');

	if(path_end == NULL)
		return -1;

	path_end ++;
	*path_end = '\0';

	return 0;
}



int get_executable_path( char* process_path,size_t len)
{
	int ifunc;

	//返回值: 進程路徑的長度 (char).  但是沒有null 結束。
	ifunc = readlink("/proc/self/exe", process_path, len );
	if( ifunc <=  0 )
		return -1;

	process_path[ifunc] = 0;
	return 0;
}


static bool InitDefaultLogFile()
{
	//獲得程序運行目錄
	//if( GetModuleFileName( NULL, g_szAppPath, MAX_PATH )  == 0 )
	//	return FALSE;
	if ( g_bInitNcTrace )
		return true;

	if ( get_executable_path( g_szAppPath,  256 ) != 0 )
		return false;

	strcpy( g_szBakFile, g_szAppPath    );
	strcat( g_szAppPath, (".txt" )  );

	NcSetLogFile( g_szAppPath );

	return true;
}


static FILE * OpenAutoLogFile()
{
	int ifunc;

	//當日志文件大於100K時,存儲到*0.txt中
	struct stat st_file;
	ifunc = stat( g_szAppPath, &st_file );

	if ( ifunc == 0 && st_file.st_size	> LOG_FILE_SIZE )
	{
		remove( g_szBakFile );
		rename( g_szAppPath, g_szBakFile );
	}

	FILE* fOut = fopen( g_szAppPath , "a"	);

	return fOut;
}


bool locked_NcTrace( FILE *fOut , const CHAR_TYPE * lpszFormat ,va_list args )
{
	int ifunc;
	try
	{
		// 進程ID
		int iCurrentProcessID = getpid();

		// 記錄時間
		char  szTime[128]		= { 0 };


		//SYSTEMTIME localTime	= { 0 };
		//GetLocalTime( &localTime );

		struct timeval tv;
		ifunc = gettimeofday( &tv, NULL );

		struct tm *  ptime = localtime( &tv.tv_sec );
		int iYear = ptime->tm_year + 1900;
		int iMonth = ptime->tm_mon + 1;

		sprintf( szTime , ("[%x] %4d-%02d-%02d %02d:%02d:%02d:%03d : "), iCurrentProcessID 
			, iYear, iMonth,  ptime->tm_mday , ptime->tm_hour, ptime->tm_min, ptime->tm_sec, (int)tv.tv_usec/1000 );


		// 格式化字符串
		char szInfo[2*1024] = { 0 };
		vsnprintf(szInfo, 2*1024, lpszFormat, args);



		fwrite( szTime , sizeof(char) ,   strlen( szTime ) , fOut )	;
		fwrite( szInfo ,   sizeof(char) , strlen( szInfo ) , fOut )	;
		fwrite( "\n" , 1 , 1 , fOut )	;	

	}
	catch (...)
	{
		return false;
	}

	return true;
}


bool NcTrace( const CHAR_TYPE * lpszFormat , ... )
{
	InitDefaultLogFile();


	pthread_mutex_lock ( &s_mtx_log );

	va_list  va;
	va_start(va, lpszFormat);

	FILE *fp = OpenAutoLogFile();
	if ( fp )
	{
		locked_NcTrace( fp,lpszFormat, va );
		fclose( fp );
	}

	va_end( va );

	pthread_mutex_unlock ( &s_mtx_log );

	return true;
}




static FILE * OpenLogFile(const CHAR_TYPE * sLogFile )
{
	int ifunc;
	//當日志文件大於100K時,存儲到*0.txt中
	struct stat st_file;
	
	memset( &st_file, 0, sizeof(struct stat ) );

	ifunc = stat( sLogFile, &st_file );

	if ( ifunc == 0 && st_file.st_size	> LOG_FILE_SIZE )
	{
		remove( sLogFile );
	}

	FILE* fOut = fopen( sLogFile , "a"	);
	return fOut;
}


bool NcTrace2(const char * lpszLogFileName, const char * lpszFormat, ... )
{
	InitDefaultLogFile();


	pthread_mutex_lock ( &s_mtx_log );

	va_list  va;
	va_start(va, lpszFormat);

	FILE *fp = OpenLogFile( lpszLogFileName );
	if ( fp )
	{
		locked_NcTrace( fp, lpszFormat, va );
		fclose( fp );
	}

	va_end( va );

	pthread_mutex_unlock ( &s_mtx_log );

	return true;
}








發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章