⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 writelog.cpp

📁 日志是程序的重要组成部分
💻 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 + -