📄 superlog.cpp
字号:
// *************************************************************
// Copyright (C) 2000-2009,Seuu Technologies Co., Ltd.
//
// File name : SuperLog.cpp
// Description: 日志写入器实现
// Version : 1.0
// Author : Seuu
// Created : 2009-05-08 22:32:31
// *************************************************************
#include "StdAfx.h"
#include "SuperLog.h"
CTime g_tmCurTime;
CString g_strTime;
CString CSuperLog::m_strWriteStrInfo;
int CSuperLog::m_iWriteBinLogLen = 0;
int CSuperLog::m_iCurLogFileSeq = 0;
#ifdef _DEBUG
int CSuperLog::m_iLogLevel = CSuperLog::ENUM_LOG_LEVEL_DEBUG;
#else
int CSuperLog::m_iLogLevel = CSuperLog::ENUM_LOG_LEVEL_RUN;
#endif
TCHAR* g_pszLogLevel[] = {_T("0"), _T("1"), _T("2"), _T("3")};
HANDLE CSuperLog::m_hMapLogFile = NULL;
LPTSTR CSuperLog::m_psMapAddr = NULL;
char g_szWriteBinInfo[MAX_BIN_LOG_INFO_LEN];
TCHAR* g_pszLogFileName[MAX_LOG_FILE_COUNT] = {_T("log1.txt"), _T("log2.txt"), _T("log3.txt")};
HANDLE CSuperLog::m_hThread = NULL;
unsigned CSuperLog::m_uiThreadID = 0;
bool CSuperLog::m_bRun = true;
CSuperLog::enLogStatus CSuperLog::m_enStatus = CSuperLog::ENUM_LOG_INIT;
CStdioFile* CSuperLog::m_pFile = NULL;
int CSuperLog::m_iMaxLogFileLen = MAX_LOG_FILE_LEN;
CRITICAL_SECTION CSuperLog::m_csWriteLog;
CSuperLog g_SuperLog;
unsigned __stdcall CSuperLog::LogProcStart( void* pParam )
{
int nCount = 1;
CString strTemp;
WriteLog(_T("日志线程启动."), ENUM_LOG_LEVEL_DEBUG, true);
// 线程开始
do
{
Sleep(300);
if (++nCount % 10 == 0 )
{
WriteLog(strTemp, ENUM_LOG_LEVEL_ERROR, true); // 每隔三秒写一次日志
CheckLogLevel();
}
if (nCount % 40 == 0 || m_enStatus == ENUM_LOG_INVALID)
{
// 每12秒检查一次文件
if (ENUM_LOG_INVALID == OpenLogFile())
{
Sleep(3000);
OpenLogFile();
}
}
} while (m_bRun);
// 程序开始退出
WriteLog(_T("Super logger has exited."), ENUM_LOG_LEVEL_RUN, true);
if (m_pFile != NULL)
{
m_pFile->Close();
delete m_pFile;
m_pFile = NULL;
}
m_enStatus = ENUM_LOG_EXITED;
_endthreadex( 0 );
return 0;
}
// *************************************************************
// Copyright (C) 2000-2009 Seuu Technologies Co., Ltd.
// Function name : CSuperLog::CSuperLog
// Description : 初始化函数
// Return type :
// Argument : void
// Created by seuu at 2009-05-09 22:05:52
// *************************************************************
CSuperLog::CSuperLog(void)
{
// 初始化临界区变量
InitializeCriticalSection(&m_csWriteLog);
// 打开一个日志文件
OpenLogFile();
// 启动信息
m_strWriteStrInfo = WELCOME_LOG_INFO;
WriteLog(_T("Super logger start up."), ENUM_LOG_LEVEL_RUN, true);
// 从配置文件中读取日志级别
OperaterConfig(FALSE);
// 同步到共离内存中
SetLogLevelShareMem(m_iLogLevel);
// Create the Logger thread.
m_hThread = (HANDLE)_beginthreadex( NULL, 0, &LogProcStart, NULL, 0, &m_uiThreadID );
}
CSuperLog::~CSuperLog(void)
{
m_bRun = false;
m_enStatus = ENUM_LOG_EXITING;
for (int i = 0; i < 50; i++)
{
Sleep(300);
if (m_enStatus == ENUM_LOG_EXITED)
{
break;
}
}
DeleteCriticalSection(&m_csWriteLog);
if (m_psMapAddr != NULL)
{
UnmapViewOfFile(m_psMapAddr);
}
}
int CSuperLog::OperaterConfig(BOOL bSave)
{
TCHAR szPath[MAX_PATH];
if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )
{
WRITE_LOG(_T("GetModuleFileName失败。"), LOG_LEVEL_ERROR);
return -1;
}
CString strDir = szPath;
int nPos = strDir.ReverseFind(_T('\\'));
if (nPos == -1)
{
WRITE_LOG(_T("GetModuleFileName取得信息异常。"), LOG_LEVEL_ERROR);
return -1;
}
strDir = strDir.Left(nPos + 1);
strDir += _T("SuperLog.ini");
if (bSave)
{
WritePrivateProfileString(
_T("SuperLog"),
_T("LogLevel"),
g_pszLogLevel[m_iLogLevel],
strDir);
CString temp;
temp.Format(_T("%d"), m_iMaxLogFileLen);
WritePrivateProfileString(
_T("SuperLog"),
_T("MaxLogFileLen"),
(LPCTSTR)temp,
strDir);
}
else
{
m_iLogLevel = GetPrivateProfileInt(
_T("SuperLog"),
_T("LogLevel"),
ENUM_LOG_LEVEL_RUN,
strDir);
if (m_iLogLevel > ENUM_LOG_LEVEL_ERROR || m_iLogLevel < ENUM_LOG_LEVEL_DEBUG)
{
WriteLog(_T("日志级别配置非法。"),LOG_LEVEL_ERROR);
m_iLogLevel = ENUM_LOG_LEVEL_RUN;
}
m_iMaxLogFileLen = GetPrivateProfileInt(
_T("SuperLog"),
_T("MaxLogFileLen"),
MAX_LOG_FILE_LEN,
strDir);
if (m_iMaxLogFileLen > 1024*1024*1024 || m_iMaxLogFileLen < MAX_BIN_LOG_INFO_LEN)
{
WriteLog(_T("最大文件长度配置非法。"),LOG_LEVEL_ERROR);
m_iMaxLogFileLen = MAX_LOG_FILE_LEN;
}
}
return 0;
}
int CSuperLog::CheckLogLevel()
{
int iLevel = GetLogLevelShareMem();
if (iLevel != m_iLogLevel)
{
SetLogLevelShareMem(iLevel);
m_iLogLevel = iLevel;
OperaterConfig(TRUE);
}
return 0;
}
int CSuperLog::SetLogLevelShareMem(int iLevel)
{
if (m_hMapLogFile == NULL || m_psMapAddr == NULL)
{
GetLogLevelShareMem();
}
if (m_hMapLogFile != NULL && m_psMapAddr != NULL)
{
_tcscpy_s(m_psMapAddr, 1024, g_pszLogLevel[iLevel]);
FlushViewOfFile(m_psMapAddr, _tcslen(g_pszLogLevel[iLevel]));
WriteLog(_T("设置日志级别成功。"), ENUM_LOG_LEVEL_RUN);
}
return 0;
}
int CSuperLog::GetLogLevelShareMem(void)
{
//打开共享的文件对象。
if (m_hMapLogFile == NULL)
{
m_hMapLogFile = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, _T("SuperLogShareMem"));
}
if (m_hMapLogFile != NULL)
{
//显示共享的文件数据。
if (m_psMapAddr == NULL)
{
m_psMapAddr = (LPTSTR)MapViewOfFile(m_hMapLogFile, FILE_MAP_ALL_ACCESS,0,0,0);
WriteLog(m_psMapAddr, ENUM_LOG_LEVEL_DEBUG);
}
}
else
{
//创建共享文件。
m_hMapLogFile = CreateFileMapping(INVALID_HANDLE_VALUE,NULL,PAGE_READWRITE,0,1024, _T("SuperLogShareMem"));
if (m_hMapLogFile != NULL)
{
//拷贝数据到共享文件里。
m_psMapAddr = (LPTSTR)MapViewOfFile(m_hMapLogFile,FILE_MAP_ALL_ACCESS, 0,0,0);
if (m_psMapAddr != NULL)
{
_tcscpy_s(m_psMapAddr, 1024, g_pszLogLevel[m_iLogLevel]);
FlushViewOfFile(m_psMapAddr, _tcslen(g_pszLogLevel[m_iLogLevel]));
WriteLog(_T("设置默认日志级别到共享内存中成功。"), ENUM_LOG_LEVEL_RUN);
}
}
else
{
WriteLog(_T("创建共享内存失败。"), ENUM_LOG_LEVEL_ERROR);
}
}
if (m_psMapAddr != NULL)
{
if (_tcscmp(m_psMapAddr, g_pszLogLevel[ENUM_LOG_LEVEL_RUN]) == 0)
{
return ENUM_LOG_LEVEL_RUN;
}
else if (_tcscmp(m_psMapAddr, g_pszLogLevel[ENUM_LOG_LEVEL_DEBUG]) == 0)
{
return ENUM_LOG_LEVEL_DEBUG;
}
else if (_tcscmp(m_psMapAddr, g_pszLogLevel[ENUM_LOG_LEVEL_ERROR]) == 0)
{
return ENUM_LOG_LEVEL_ERROR;
}
else
{
return ENUM_LOG_LEVEL_RUN;
}
}
return m_iLogLevel;
}
CSuperLog::enLogStatus CSuperLog::OpenLogFile(void)
{
EnterCriticalSection(&m_csWriteLog);
// 写入过程中出错后需要关闭文件
if (m_enStatus == ENUM_LOG_INVALID && m_iCurLogFileSeq != 0)
{
m_iCurLogFileSeq--;
if (m_pFile != NULL)
{
m_pFile->Close();
delete m_pFile;
m_pFile = NULL;
}
}
for (int iRunCount = 0; iRunCount < MAX_LOG_FILE_COUNT; iRunCount++)
{
if (m_pFile == NULL)
{
m_pFile = new CStdioFile;
if (m_pFile == NULL)
{
LeaveCriticalSection(&m_csWriteLog);
return m_enStatus = ENUM_LOG_INVALID;
}
BOOL bRet = m_pFile->Open(
g_pszLogFileName[(m_iCurLogFileSeq++)%MAX_LOG_FILE_COUNT],
CFile::modeWrite | CFile::modeCreate | CFile::typeBinary | CFile::shareDenyNone | CFile::modeNoTruncate);
if (bRet)
{
WriteUnicodeHeadToFile(m_pFile);
}
else
{
delete m_pFile;
m_pFile = NULL;
LeaveCriticalSection(&m_csWriteLog);
return m_enStatus = ENUM_LOG_INVALID;
}
}
if (m_pFile->GetLength() > MAX_LOG_FILE_LEN)
{
m_pFile->Close();
BOOL bRet = FALSE;
// 上一个文件是最大的那个文件或是写过一遍了的。
if (m_iCurLogFileSeq >= MAX_LOG_FILE_COUNT)
{
// 所有文件都是写满了,则强制从第一个文件开始写,同时先清空文件
bRet = m_pFile->Open(
g_pszLogFileName[(m_iCurLogFileSeq++)%MAX_LOG_FILE_COUNT],
CFile::modeWrite | CFile::modeCreate | CFile::typeBinary | CFile::shareDenyNone);
}
else
{
// 打开第二个文件,再检查是否过了最大值
bRet = m_pFile->Open(
g_pszLogFileName[(m_iCurLogFileSeq++)%MAX_LOG_FILE_COUNT],
CFile::modeWrite | CFile::modeCreate | CFile::typeBinary | CFile::shareDenyNone | CFile::modeNoTruncate);
}
if (bRet)
{
WriteUnicodeHeadToFile(m_pFile);
}
else
{
delete m_pFile;
m_pFile = NULL;
LeaveCriticalSection(&m_csWriteLog);
return m_enStatus = ENUM_LOG_INVALID;
}
}
else
{
break;
}
}
m_pFile->SeekToEnd();
LeaveCriticalSection(&m_csWriteLog);
return m_enStatus = ENUM_LOG_RUN;
}
int CSuperLog::WriteLog(CString &strLog,enLogInfoLevel enLevel/* = ENUM_LOG_LEVEL_RUN*/, bool bForce /*= false*/)
{
if (enLevel < m_iLogLevel)
{
return -1;
}
EnterCriticalSection(&m_csWriteLog);
if (!strLog.IsEmpty())
{
m_strWriteStrInfo += GetCurTimeStr();
// add log level info
if (enLevel == ENUM_LOG_LEVEL_ERROR)
{
m_strWriteStrInfo += _T("Error! ");
}
m_strWriteStrInfo += strLog;
m_strWriteStrInfo += _T("\r\n");
}
if ( bForce
|| m_strWriteStrInfo.GetLength() > MAX_STR_LOG_INFO_LEN
|| m_iWriteBinLogLen > MAX_BIN_LOG_INFO_LEN/10)
{
// write info
WriteLogToFile();
}
LeaveCriticalSection(&m_csWriteLog);
return 0;
}
int CSuperLog::WriteLog(TCHAR* pstrLog, enLogInfoLevel enLevel /*= ENUM_LOG_LEVEL_RUN*/, bool bForce /*= false*/)
{
if (pstrLog == NULL || enLevel < m_iLogLevel)
{
return -1;
}
EnterCriticalSection(&m_csWriteLog);
if (_tcslen(pstrLog) != 0)
{
m_strWriteStrInfo += GetCurTimeStr();
if (enLevel == ENUM_LOG_LEVEL_ERROR)
{
m_strWriteStrInfo += _T("Error! ");
}
m_strWriteStrInfo += pstrLog;
m_strWriteStrInfo += _T("\r\n");
}
if ( bForce
|| m_strWriteStrInfo.GetLength() > MAX_STR_LOG_INFO_LEN
|| m_iWriteBinLogLen > MAX_BIN_LOG_INFO_LEN/10)
{
// write info
WriteLogToFile();
}
LeaveCriticalSection(&m_csWriteLog);
return 0;
}
int CSuperLog::WriteUnicodeHeadToFile(CFile * pFile)
{
if (pFile == NULL)
{
return -1;
}
try
{
if (pFile->GetLength() == 0)
{
m_pFile->Write("\377\376", 2);
if (m_enStatus == ENUM_LOG_RUN)
{
m_pFile->WriteString(WELCOME_LOG_INFO);
}
m_pFile->Flush();
}
}
catch (...)
{
return -1;
}
return 0;
}
CString& CSuperLog::GetCurTimeStr()
{
g_tmCurTime = CTime::GetCurrentTime();// time(NULL);
g_strTime = g_tmCurTime.Format(_T("%Y-%m-%d %H:%M:%S "));
return g_strTime;
}
int CSuperLog::WriteLog(char* pszLog, int nLen,enLogInfoLevel enLevel /*= ENUM_LOG_LEVEL_RUN*/, bool bForce /*= false*/)
{
// 待实现
return -1;
if (nLen >= MAX_BIN_LOG_INFO_LEN || pszLog == NULL || enLevel < m_iLogLevel)
{
return -1;
}
EnterCriticalSection(&m_csWriteLog);
if (nLen + m_iWriteBinLogLen >= MAX_BIN_LOG_INFO_LEN)
{
// write info to file 待实现
memcpy(g_szWriteBinInfo, pszLog, nLen);
m_iWriteBinLogLen = nLen;
}
else
{
memcpy(g_szWriteBinInfo+m_iWriteBinLogLen, pszLog, nLen);
m_iWriteBinLogLen += nLen;
}
if ( bForce
|| m_strWriteStrInfo.GetLength() > MAX_STR_LOG_INFO_LEN
|| m_iWriteBinLogLen > MAX_BIN_LOG_INFO_LEN/10)
{
// write info to file
WriteLogToFile();
}
LeaveCriticalSection(&m_csWriteLog);
return 0;
}
int CSuperLog::WriteLogToFile()
{
if (m_pFile == NULL
|| (m_iWriteBinLogLen == 0 && m_strWriteStrInfo.IsEmpty())
|| m_enStatus == ENUM_LOG_INIT
|| m_enStatus == ENUM_LOG_EXITED
|| m_enStatus == ENUM_LOG_INVALID
)
{
return 0;
}
try
{
m_pFile->WriteString(m_strWriteStrInfo);
m_pFile->Flush();
}
catch (...)
{
m_enStatus = ENUM_LOG_INVALID;
}
m_strWriteStrInfo.Empty();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -