📄 writelog.cpp
字号:
// WriteLog.cpp: implementation of the CWriteLog class.
//
//////////////////////////////////////////////////////////////////////
#include "WriteLog.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
INT16 CWriteLog::m_iPrintLevel= LEVEL_CONTENT;
CWriteLog::CWriteLog()
{
SetLogPath( (INT8*)DFT_LOGPATH );
m_iMaxLogTag= 0;
m_iLogLevel = DFT_LOGLEVEL;
m_iLogBakNum = DFT_BAKLOGNUM;
m_bLogFlag = TRUE;
m_lLogExpiredDay= DFT_EXPIRED_DAY;
m_pSystemTime= NULL;
m_pLocalTime= NULL;
m_asLogFile= NULL;
m_lMaxFileSize= MAX_FILE_LEN;
m_bExitFlag = FALSE;
m_oQueue = new CMyQueue();
}
CWriteLog::~CWriteLog()
{
Shut();
}
INT16 CWriteLog::Start( const UINT32 lMaxMemorySizeK, const UINT32 lMaxFileSize )
{
INT32 iRev;
if ( !m_asLogFile )
{
printf( "FAILED: m_asLogFile is NULL\n" );
return -1;
}
if ( lMaxFileSize <= 0 )
return -2;
m_lMaxFileSize= lMaxFileSize;
if ( lMaxMemorySizeK <= 0 )
return -3;
iRev = m_oQueue->InitQueue( MAX_MEM_SIZE,VAL_DISPLAYBUF_LEN );
if( iRev != 0 )
return -4;
m_alFileTime= (struct tm*)calloc( MAX_FILE_NUM, sizeof(struct tm) );
if ( !m_alFileTime )
{
printf( "FAILED: calloc m_alFileTime !\n" );
return -5;
}
memset( m_alFileTime, 0, MAX_FILE_NUM*sizeof(struct tm) );
pthread_t tid= 0;
if ( pthread_create( &tid, NULL, thWritingThread, this ) != 0 )
return -6;
// PrintLogFile();
return 0;
}
INT16 CWriteLog::Shut()
{
m_bExitFlag= TRUE;
uSleep( 50 );
if ( m_asLogFile )
{
free( m_asLogFile );
m_asLogFile= NULL;
}
if ( m_alFileTime )
{
free( m_alFileTime );
m_alFileTime= NULL;
}
if( m_oQueue != NULL )
{
m_oQueue->RemoveAll();
delete(m_oQueue);
m_oQueue = NULL;
}
return 0;
}
MYTYPE_THREAD_FUNC CWriteLog::thWritingThread(void* pParam)
{
class CWriteLog* pObj= (class CWriteLog*)pParam; //对象指针
INT32 lRetVal; //操作返回值
INT8 sTime[100]; //记录时间字符串
SLogMessage jLogMessage; //待记录信息结构
FILE* afp[MAX_FILE_NUM]; //文件句柄数组中的索引
UINT8 cFile; //文件在文件句柄数组中的索引
INT16 iOpenFileCount= 0; //打开文件计数
UINT32 lWaitCount= 0;
UINT32 lWriteCount= 0;
struct stat fstatbuf;
INT16 i;
pthread_detach( pthread_self() );
printf( "CWriteLog: writing thread [%d:%d] start up\n", (INT32)getpid(), (INT32)pthread_self() );
memset( afp, 0, sizeof(afp) );
while ( !pObj->m_bExitFlag )
{
//取待写信息
lRetVal= pObj->m_oQueue->GetDelNode( &jLogMessage, sizeof(jLogMessage) );
cFile= !lRetVal ? jLogMessage.cFileFlag : -1;
if ( lRetVal != 0 )
{
lWaitCount++;
if ( lWaitCount <= 20 )
uSleep( 20 );
else if ( lWaitCount <= 100 )
{
if ( lWaitCount == 50 )
{
for ( i=0; i<pObj->m_iMaxLogTag && iOpenFileCount>0; i++ )
{
if ( afp[ i ] )
{
//关闭过期
fflush( afp[ i ] );
fclose( afp[ i ] );
afp[ i ]= NULL;
iOpenFileCount--;
}
}
}
uSleep( 100 );
}
else
uSleep( 500 );
continue;
}
else
lWaitCount= 0;
//打开未打开
if ( afp[ cFile ] == NULL )
{
afp[ cFile ] = pObj->OpenLogFile( cFile );
if ( afp[ cFile ] == NULL )
{
printf( "======== FAILED: CWriteLog: open file[%s] ! ========\n", pObj->m_asLogFile[ cFile] );
break;
}
iOpenFileCount++;
}
pObj->GetTimeString( sTime );
jLogMessage.sLogContent[ VAL_DISPLAYBUF_LEN-1 ]= '\0';
//写入文件
//========================================================================
fprintf( afp[ cFile ], "%s%s\r\n", sTime, jLogMessage.sLogContent );
//========================================================================
lWriteCount++;
if ( lWriteCount % 30 == 0 )
{
fflush( afp[ cFile ] );
memset( &fstatbuf, 0, sizeof(struct stat) );
stat( pObj->m_asLogFile[ cFile ], &fstatbuf );
if ( (UINT32)fstatbuf.st_size >= pObj->m_lMaxFileSize )
{
//关闭超过大小限定的文件
fclose( afp[ cFile ] );
afp[ cFile ]= NULL;
iOpenFileCount--;
}
}
else if ( lWriteCount % 100 == 0 )
{
for ( i=0; i<pObj->m_iMaxLogTag && iOpenFileCount>0; i++ )
{
if ( afp[ i ] )
{
fflush( afp[ i ] );
memset( &fstatbuf, 0, sizeof(struct stat) );
stat( pObj->m_asLogFile[ i ], &fstatbuf );
if ( (UINT32)fstatbuf.st_size >= pObj->m_lMaxFileSize )
{
//关闭超过大小限定的文件
fclose( afp[ i ] );
afp[ i ]= NULL;
iOpenFileCount--;
}
}
}
}
if ( lWriteCount % 5 == 0 )
{
fflush( afp[ cFile ] );
uSleep( 10 );
}
}//while (!m_bExitFlag)
//关闭未关闭
for ( i=0; i<=pObj->m_iMaxLogTag && iOpenFileCount>0; i++ )
{
if ( afp[ i ] )
{
fflush( afp[ i ] );
fclose( afp[ i ] );
iOpenFileCount--;
}
}
printf( "CWriteLog: writing thread [%d:%d] exit\n", (INT32)getpid(), (INT32)pthread_self() );
return 0;
}
FILE* CWriteLog::OpenLogFile( UINT8 cFileFlag )
{
FILE* fp;
struct stat fstatbuf;
INT8 sCmd[300];
time_t lRmTime;
struct tm tmRm;
struct tm tmCur;
INT32 iRetVal;
if ( m_pLocalTime )
tmCur= *m_pLocalTime;
else
{
time_t time1;
time( &time1 );
memcpy( &tmCur, localtime(&time1), sizeof(struct tm) );
}
memset( &fstatbuf, 0, sizeof(struct stat) );
iRetVal= stat( m_asLogFile[ cFileFlag ], &fstatbuf );
if ( iRetVal != 0 && errno != ENOENT )
printf( "ERROR: OpenLogFile [%d][%s] stat [ECode:%d]\n", cFileFlag, m_asLogFile[ cFileFlag ], errno );
if ( m_alFileTime[cFileFlag].tm_mday != tmCur.tm_mday )
{
if ( m_pSystemTime )
lRmTime= *m_pSystemTime - m_lLogExpiredDay * 24*60*60;
else
{
time_t time1;
time( &time1 );
lRmTime= time1 - m_lLogExpiredDay * 24*60*60;
}
memcpy( &tmRm, localtime(&lRmTime), sizeof(struct tm) );
#ifndef WIN32
sprintf( sCmd, "rm -f %s.%.2d%.2d.*", m_asLogFile[ cFileFlag ], tmRm.tm_mon+1, tmRm.tm_mday );
system( sCmd );
#else
sprintf( sCmd, "del //F//Q %s.%.2d%.2d.*", m_asLogFile[ cFileFlag ], tmRm.tm_mon+1, tmRm.tm_mday );
system( sCmd );
#endif
m_alFileTime[cFileFlag]= tmCur;
}
if ( iRetVal == 0 && (UINT32)fstatbuf.st_size >= m_lMaxFileSize )
{
INT16 s= GetSerial( cFileFlag );
if ( s < 0 )
return NULL;
#ifndef WIN32
sprintf( sCmd, "mv -f %s %s.%.2d%.2d.%.2d", m_asLogFile[ cFileFlag ], m_asLogFile[ cFileFlag ],
tmCur.tm_mon+1, tmCur.tm_mday, s );
#else
sprintf( sCmd, "move %s %s.%.2d%.2d.%.2d", m_asLogFile[ cFileFlag ], m_asLogFile[ cFileFlag ],
tmCur.tm_mon+1, tmCur.tm_mday, s );
#endif
system( sCmd );
fp= fopen( m_asLogFile[ cFileFlag ], "wb+" );
}
else
fp= mdfopen( m_asLogFile[ cFileFlag ], "ab+" );
return fp;
}
//得到当前可用备份文件的序号(序号从1到m_iLogBakNum)
INT16 CWriteLog::GetSerial( UINT8 cFileFlag )
{
INT8 sFile[MAX_LOGFILENAME_LEN];
struct stat fstatbuf;
INT16 iSerial;
//如果有未使用的序号,使用最小的未使用序号
for ( iSerial= 1; iSerial<= m_iLogBakNum; iSerial++ )
{
sprintf(sFile, BAK_LOG_FORMAT, m_asLogFile[ cFileFlag ], m_pLocalTime->tm_mon+1, m_pLocalTime->tm_mday, iSerial);
#ifdef WIN32
struct stat my_stat;
if ( stat( sFile, &my_stat ) != 0 )
return iSerial;
#else
if ( access( sFile, F_OK ) != 0 )
return iSerial;
#endif
}
//没有未使用序号,使用最早修改的文件的序号(则以此序列号命名的原文件将被覆盖)
iSerial = 1;
UINT32 mtime= 0xFFFFFFFF;
for ( int i= 1; i<= m_iLogBakNum; i++ )
{
sprintf( sFile, BAK_LOG_FORMAT, m_asLogFile[ cFileFlag ], m_pLocalTime->tm_mon+1, m_pLocalTime->tm_mday, i );
memset( &fstatbuf, 0, sizeof(struct stat) );
if ( stat( sFile, &fstatbuf ) == 0 )
{
if ( (UINT32)fstatbuf.st_mtime < mtime )
{
iSerial = i;
mtime = fstatbuf.st_mtime;
}
}
}
return iSerial;
}
INT16 CWriteLog::GetTimeString(INT8* sTime)
{
if ( m_pLocalTime )
sprintf(sTime, "%.2d:%.2d:%.2d %.2d/%.2d : ", m_pLocalTime->tm_hour, m_pLocalTime->tm_min, m_pLocalTime->tm_sec, m_pLocalTime->tm_mon+1, m_pLocalTime->tm_mday);
else
{
time_t time1;
struct tm tm1;
time( &time1 );
memcpy( &tm1, localtime(&time1), sizeof(struct tm) );
sprintf(sTime, "%.2d:%.2d:%.2d %.2d/%.2d : ", tm1.tm_hour, tm1.tm_min, tm1.tm_sec, tm1.tm_mon+1, tm1.tm_mday);
}
return 0;
}
INT16 CWriteLog::SetLogFile( const INT8* sLogFile, const UINT8 cFileTag )
{
if ( strlen(sLogFile) > (MAX_LOGFILENAME_LEN-strlen(m_sFilePath)-1) )
return -1;
if ( cFileTag >= MAX_FILE_NUM )
return -2;
if ( !m_asLogFile )
{
m_asLogFile= (INT8(*)[MAX_LOGFILENAME_LEN])malloc( sizeof(INT8)*MAX_FILE_NUM*MAX_LOGFILENAME_LEN );
if ( m_asLogFile )
{
memset( m_asLogFile, 0, sizeof(INT8)*MAX_FILE_NUM*MAX_LOGFILENAME_LEN );
strcpy( (INT8*)m_asLogFile[ 0 ], DFT_LOGPATH );
strcpy( (INT8*)m_asLogFile[ 0 ] + strlen( DFT_LOGPATH ), DFT_LOGFILE );
}
else
printf( "FAILED: malloc m_asLogFile memory !" );
}
strcpy( m_asLogFile[cFileTag], m_sFilePath );
strcpy( m_asLogFile[cFileTag] + strlen( m_sFilePath ), sLogFile );
if ( cFileTag > m_iMaxLogTag )
m_iMaxLogTag= cFileTag;
return 0;
}
INT16 CWriteLog::SetLogOpen( const INT16 iFlag )
{
m_bLogFlag= (BOOL)iFlag;
return 0;
}
//设置日志文件路径
INT16 CWriteLog::SetLogPath( const INT8* sLogPath )
{
if ( strlen(sLogPath) > MAX_LOGPATH_LEN )
return -1;
strcpy( m_sFilePath, sLogPath );
INT16 iOldPathLen= strlen( m_sFilePath );
if ( m_sFilePath[ iOldPathLen - 1 ] != PATH_TAG )
{
m_sFilePath[ iOldPathLen ]= PATH_TAG;
m_sFilePath[ iOldPathLen + 1 ]= '\0';
}
return 0;
}
INT16 CWriteLog::SetLogLevel(const INT16 iLogLevel)
{
if ( iLogLevel < 0
|| iLogLevel > LEVEL_DEBUG )
return -1;
m_iLogLevel = iLogLevel;
return 0;
}
INT16 CWriteLog::SetLogBakNum(const INT16 iNum)
{
if ( iNum<0 || iNum>MAX_BAKLOGNUM )
return -1;
m_iLogBakNum = iNum;
return 0;
}
//设置日志保存时间
INT16 CWriteLog::SetLogExpiredDay( const INT16 iExpiredDay )
{
if ( iExpiredDay <= 0 )
return -1;
if ( iExpiredDay > 365 )
return -2;
m_lLogExpiredDay= iExpiredDay;
return 0;
}
INT16 CWriteLog::SetTimeReference( const time_t* pSystemTime, const struct tm* pLocalTime )
{
m_pSystemTime= pSystemTime;
m_pLocalTime= pLocalTime;
return 0;
}
//cLogTag 为日志文件标记
INT16 CWriteLog::AddLogMessage(const UINT8 cLogTag, const INT16 iLogLevel, const INT8* sFormat, ...)
{
INT16 iRetVal;
va_list args;
va_start ( args, sFormat );
iRetVal= AddLogMessage( sFormat, args, cLogTag, (UINT8)iLogLevel );
va_end( args );
return iRetVal;
}
//为直接调用与包装调用提供接口
//cLogTag 为日志文件标记
INT16 CWriteLog::AddLogMessage( const INT8* sFormat, const va_list args, const UINT8 cLogTag, const INT16 iLogLevel )
{
SLogMessage jLogMessage;
INT32 lRetVal;
if (!m_bLogFlag)
return 1;
//当前设置记录级别小于信息级别不记录
if ( iLogLevel > m_iLogLevel )
return 2;
jLogMessage.cFileFlag = cLogTag;
// jLogMessage.cLogType = cLogTag;
//高位为信息类型,低位为文件标记
// jLogMessage.cFileFlag <<= 4;
// jLogMessage.cFileFlag >>= 4;
// jLogMessage.cLogType >>= 4;
// jLogMessage.cLogType <<= 4;
jLogMessage.cLogLevel= (UINT8)iLogLevel;
vsnprintf( jLogMessage.sLogContent, VAL_DISPLAYBUF_LEN, sFormat, args );
lRetVal= m_oQueue->InsertNode( &jLogMessage, sizeof(jLogMessage) );
if ( lRetVal != 0 && lRetVal != -1 )
{
printf( "FAILED: CWriteLog::AddLogMessage [ECode:%d][Used:%u, Max:%u]\n", lRetVal, this->GetUsedNodeNum(), this->GetTotalNodeNum() );
return -100+lRetVal;
}
return 0;
}
INT16 CWriteLog::PrintLogFile()
{
for ( INT16 i= 0; i<=m_iMaxLogTag; i++ )
printf( "Tag: %d, File: %s\n", i, m_asLogFile[ i ] );
return 0;
}
FILE* mdfopen(const INT8* pFileName, const INT8* sMode)
{
FILE* fp;
INT8* p;
INT8 sPathName[MAX_MYLIB_FILENAME_LEN];
if (strlen(pFileName) >= MAX_MYLIB_FILENAME_LEN)
return NULL;
fp= fopen(pFileName, sMode);
if (fp != NULL)
return fp;
if (strchr(sMode, 'r')) //读属性, 不会因不存在相应目录而打开失败
return NULL;
strcpy(sPathName, pFileName);
p= sPathName + strlen(sPathName) - 1;
while (1)
{
if (p == pFileName ||
*p == '\\' ||
*p == '/')
break;
p--;
}
*p= '\0';
#ifdef WIN32
mkdir(sPathName); //创建相应目录
#else
mkdir(sPathName, S_IRWXU|S_IRWXG|S_IRWXO); //创建相应目录
#endif
return (fopen(pFileName, sMode));
}
/*
INT32 main()
{
INT32 iRev;
CWriteLog g_oLog;
printf("@@@@@@@@@@@@@@@@@@@@@@@@@ %d\n",iRev);
iRev = g_oLog.SetLogFile( "TESTLOG", 1 );
if(iRev != 0)
{
printf("@@@@@@@@@@@@@@@@@@@@@@@@@ %d\n",iRev);
}
time_t lTime= time(NULL);
struct tm sCurrentTime;
localtime_r( &lTime, &sCurrentTime );
g_oLog.SetTimeReference( &lTime, &sCurrentTime );
//g_oLog.SetTimeReference( &g_oSysParam.m_lSystemTime, &g_oSysParam.m_tmLocalTime );
iRev = g_oLog.Start(10000,5000000);
if( iRev != 0 )
{
printf("@@@@@@@@@@@@@@@@@@@@@@@@@ %d\n",iRev);
}
for(INT32 i = 0 ; i < 1000; i++)
{
g_oLog.AddLogMessage(1,1,"111111111sssssssssssssss %d",i);
}
sleep(10);
}
*/
//////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -