#include "Common.h" #include "Object.h" #include "Thread.h" #include "Timer.h" #include "Logger.h" #include #ifdef _WIN32 //#include //#pragma warning(disable:4201) //#include //#pragma warning(default:4201) //#pragma comment(lib, "winmm.lib") #include #else #include #endif // _WIN32 // my defines for portablity #ifdef _WIN32 #define ftime _ftime #define timeb _timeb #define vsnprintf _vsnprintf #define snprintf _snprintf #define FILECRETEFAIL_CAPTION "HLogger Message" #endif // _WIN32 #ifdef SINGLE_THREADED_MODEL #if _MSC_VER <= 1200 #define Lock() ((void)0) #define Unlock() ((void)0) #else #define Lock() __noop #define Unlock() __noop #endif #endif // SINGLE_THREADED_MODEL HLogger * g_pLogFile__Logger = NULL; HLogger::HLogger() { m_fhLog = -1; m_nLevel = 0; m_flagOption = dayWrite | timeWrite; m_bIsContinue = false; m_nFileSplitSize = 0; m_nFileLimitSize = 0; m_nLogFileNameExt = 0; m_bIsFileNameChange = false; m_nSrcLine = 0; m_szPathName[0] = '\0'; #ifndef SINGLE_THREADED_MODEL #ifdef _WIN32 InitializeCriticalSection(&m_csInstance); #else pthread_mutex_init(&m_mutex, NULL); #endif // _WIN32 #endif // SINGLE_THREADED_MODEL m_pExtension = NULL; m_szWriteString = (char *)malloc(MD_MAX_STRING); m_szLogString = (char *)malloc(MD_MAX_STRING); m_szTmpString = (char *)malloc(MD_MAX_STRING); } HLogger::~HLogger() { free(m_szWriteString); free(m_szLogString); free(m_szTmpString); #ifndef SINGLE_THREADED_MODEL #ifdef _WIN32 DeleteCriticalSection(&m_csInstance); #else pthread_mutex_destroy(&m_mutex); #endif // _WIN32 #endif // SINGLE_THREADED_MODEL } bool HLogger::Create(unsigned nLevel, bool bContinue, const char * szPathName, bool bIsBinary) { Lock(); m_bIsContinue = bContinue; m_bIsBinary = bIsBinary; bool bSuccess = OpenFile(nLevel, szPathName); Unlock(); return bSuccess; } void HLogger::Release() { Lock(); CloseFile(); m_nFileSplitSize = 0; m_nFileLimitSize = 0; m_nLogFileNameExt = 0; m_bIsFileNameChange = false; if (m_pExtension) { delete m_pExtension; m_pExtension = NULL; } Unlock(); } bool HLogger::OpenFile(unsigned nLevel, const char * szPathName) { if (m_fhLog != -1) return false; m_nLevel = nLevel; if (szPathName != NULL && !(szPathName[strlen(szPathName) - 1] == '/' || szPathName[strlen(szPathName) - 1] == '\\')) { // Full Path Name ==> equal. if (m_szPathName[0] == '\0') { strncpy(m_szPathName, szPathName, MD_MAX_PATH - 1); m_szPathName[MD_MAX_PATH - 1] = '\0'; } strncpy(m_szLogFileName, szPathName, MD_MAX_PATH - 1); m_szLogFileName[MD_MAX_PATH - 1] = '\0'; } else { m_bIsFileNameChange = true; // Directory ==> log name is date. ex) Start("log/") = log/20030201.log if (szPathName != NULL && m_szPathName[0] == '\0') { strncpy(m_szPathName, szPathName, MD_MAX_PATH - 1); m_szPathName[MD_MAX_PATH - 1] = '\0'; } char szDay[MD_MAX_DATE]; GetDateTime(szDay, NULL); sprintf(m_szLogFileName, "%s%s.log", m_szPathName, szDay); strncpy(m_szPrevDate, szDay, MD_MAX_DATE - 1); m_szPrevDate[MD_MAX_DATE - 1] = '\0'; //#ifdef _WIN32 // CreateDirectory(m_szPathName, NULL); //#else // mkdir(m_szPathName, S_IRWXU | S_IRWXG | S_IRWXO); //#endif } int oflag = O_CREAT | O_RDWR; if (m_bIsContinue == false) oflag |= O_TRUNC; #ifdef _WIN32 if (m_bIsBinary) oflag |= O_BINARY; else oflag |= O_TEXT; m_fhLog = open(m_szLogFileName, oflag, S_IREAD | S_IWRITE); #else m_fhLog = open(m_szLogFileName, oflag, S_IREAD | S_IWRITE | S_IRGRP | S_IROTH); #endif if (m_fhLog == -1) { char szMessage[MD_MAX_PATH + 32]; sprintf(szMessage, "[ERROR], Failed to create log file, [%s]\n", m_szLogFileName); #ifdef _WIN32 MessageBoxA(HWND_TOP, szMessage, FILECRETEFAIL_CAPTION, MB_OK | MB_ICONERROR); #else printf(szMessage); #endif return false; } if (m_bIsContinue) lseek(m_fhLog, 0L, SEEK_END); return true; } void HLogger::CloseFile() { if (m_fhLog == -1) return; if (m_nFileLimitSize > 0) { const char * pszEndTxt = "--------------------------------\nEnd of log writing.\n--------------------------------\n\n"; #ifdef _WIN32 #pragma warning(disable:4267) #endif write(m_fhLog, pszEndTxt, strlen(pszEndTxt)); #ifdef _WIN32 #pragma warning(default:4267) #endif } close(m_fhLog); m_fhLog = -1; } void HLogger::GetDateTime(char * szDate, char * szTime) { SYSTEMTIME systemTime; HTIMER()->GetSystemTime(&systemTime); if (szDate != NULL) sprintf(szDate, "%.4ld%.2ld%.2ld", systemTime.wYear, systemTime.wMonth, systemTime.wDay); if (szTime != NULL) sprintf(szTime, "%.2ld:%.2ld:%.2ld.%.3ld", systemTime.wHour, systemTime.wMinute, systemTime.wSecond, systemTime.wMilliseconds); } void HLogger::Write(int nLevel, const char * pszLog) { Lock(); if (m_fhLog == -1 || nLevel > m_nLevel || ((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel)) { Unlock(); return; } char * pszSwap = m_szLogString; m_szLogString = (char *)pszLog; m_nLogLength = (int)strlen(pszLog); WriteLog(false); m_szLogString = pszSwap; Unlock(); } void HLogger::Dump(int nLevel, const char * pszLog, size_t nSize, bool bWithHex) { Lock(); if (m_fhLog == -1 || nLevel > m_nLevel || ((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel)) { Unlock(); return; } if (nSize > MD_MAX_STRING - 3) nSize = MD_MAX_STRING - 3; strncpy(m_szLogString, pszLog, nSize); m_szLogString[nSize] = '\0'; m_nLogLength = (int)nSize; if (bWithHex) { char * pszTemp = m_szLogString + nSize; pszTemp[0] = '\n'; const char HEX[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; char cByte; unsigned i = 0, j = 1; for (; i < nSize; i++) { cByte = pszLog[i]; pszTemp[j++] = HEX[(cByte & 0xF0) >> 4]; pszTemp[j++] = HEX[(cByte & 0x0F) >> 0]; pszTemp[j++] = ' '; } m_nLogLength += j; } m_szLogString[m_nLogLength] = '\n'; m_szLogString[m_nLogLength + 1] = '\0'; m_nLogLength += 1; WriteLog(false); Unlock(); } void HLogger::Format(int nLevel, const char *fmt, ...) { Lock(); if (m_fhLog == -1 || nLevel > m_nLevel || ((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel)) { Unlock(); return; } va_list vaList; va_start(vaList, fmt); m_nLogLength = vsnprintf(m_szLogString, MD_MAX_STRING - 1, fmt, vaList); if (m_nLogLength < 0 || m_nLogLength >= MD_MAX_STRING) { m_nLogLength = MD_MAX_STRING; m_szLogString[MD_MAX_STRING - 1] = '\0'; } va_end(vaList); WriteLog(false); Unlock(); } void HLogger::Trace(const char * szSrcFileName, const unsigned nSrcLine, int nLevel, const char *fmt, ...) { Lock(); if (m_fhLog == -1 || nLevel > m_nLevel || ((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel)) { Unlock(); return; } #ifdef _WIN32 // remove path name const char * pPos = strrchr(szSrcFileName, '\\'); if (pPos == NULL) pPos = strrchr(szSrcFileName, '/'); if (pPos != NULL) { strncpy(m_szSrcFileName, ++pPos, MD_MAX_PATH); m_szSrcFileName[MD_MAX_PATH - 1] = '\0'; } else #endif // _WIN32 strncpy(m_szSrcFileName, szSrcFileName, MD_MAX_PATH - 1); m_szSrcFileName[MD_MAX_PATH - 1] = '\0'; m_nSrcLine = nSrcLine; va_list vaList; va_start(vaList, fmt); m_nLogLength = vsnprintf(m_szLogString, MD_MAX_STRING - 1, fmt, vaList); if (m_nLogLength < 0 || m_nLogLength >= MD_MAX_STRING) { m_nLogLength = MD_MAX_STRING; m_szLogString[MD_MAX_STRING - 1] = '\0'; } va_end(vaList); WriteLog(true); Unlock(); } void HLogger::SetSrcInfoWithLock(const char * szSrcFileName, const unsigned nSrcLine) { Lock(); #ifdef _WIN32 // remove path name const char * pPos = strrchr(szSrcFileName, '\\'); if (pPos == NULL) pPos = strrchr(szSrcFileName, '/'); if (pPos != NULL) { strncpy(m_szSrcFileName, ++pPos, MD_MAX_PATH); m_szSrcFileName[MD_MAX_PATH - 1] = '\0'; } else #endif // _WIN32 strncpy(m_szSrcFileName, szSrcFileName, MD_MAX_PATH - 1); m_szSrcFileName[MD_MAX_PATH - 1] = '\0'; m_nSrcLine = nSrcLine; } void HLogger::TraceWithUnlock(int nLevel) { if (m_fhLog == -1 || nLevel > m_nLevel || ((m_flagOption & onlyLevel) == onlyLevel && m_nLevel != nLevel)) { Unlock(); return; } WriteLog(true); Unlock(); } inline void HLogger::WriteLog(const bool bIsTrace) { m_szWriteString[0] = '\0'; m_nWriteLength = 0; if (m_bIsFileNameChange) { char szDate[MD_MAX_DATE]; GetDateTime(szDate, NULL); if (strcmp(m_szPrevDate, szDate) != 0) { CloseFile(); OpenFile(m_nLevel, NULL); m_nLogFileNameExt = 0; } } if (m_nFileSplitSize > 0 && m_nFileSplitSize <= lseek(m_fhLog, 0L, SEEK_CUR)) { // file split : filename.001, filename.002, ... char szLogFileName[MD_MAX_PATH], szFileName[MD_MAX_PATH]; char * pRear; pRear = strrchr(m_szLogFileName, '.'); strncpy(szFileName, m_szLogFileName, pRear - m_szLogFileName); szFileName[pRear - m_szLogFileName] = '\0'; sprintf(szLogFileName, "%s.%.3d", szFileName, ++m_nLogFileNameExt); CloseFile(); OpenFile(m_nLevel, szLogFileName); } if ((m_flagOption & dayWrite) == dayWrite) { GetDateTime(m_szWriteString, NULL); m_szWriteString[8] = ' '; m_szWriteString[9] = '\0'; m_nWriteLength += 9; } if ((m_flagOption & timeWrite) == timeWrite) { GetDateTime(NULL, m_szTmpString); memcpy(m_szWriteString + m_nWriteLength, m_szTmpString, 12); m_szWriteString[m_nWriteLength + 12] = '\t'; m_szWriteString[m_nWriteLength + 13] = '\0'; m_nWriteLength += 13; } if (bIsTrace) { m_nTracePathLength = sprintf(m_szTracePathName, "%s(%d)", m_szSrcFileName, m_nSrcLine); if (m_nTracePathLength < 26) m_nTracePathLength = sprintf(m_szTmpString, "%25s\t", m_szTracePathName); else if (m_nTracePathLength < 32) m_nTracePathLength = sprintf(m_szTmpString, "%31s\t", m_szTracePathName); else if (m_nTracePathLength < 38) m_nTracePathLength = sprintf(m_szTmpString, "%37s\t", m_szTracePathName); else m_nTracePathLength = sprintf(m_szTmpString, "%43s\t", m_szTracePathName); memcpy(m_szWriteString + m_nWriteLength, m_szTmpString, m_nTracePathLength + 1); m_nWriteLength += m_nTracePathLength; } if (m_nLogLength + m_nWriteLength > MD_MAX_STRING - 1) m_nLogLength = MD_MAX_STRING - m_nWriteLength - 1; memcpy(m_szWriteString + m_nWriteLength, m_szLogString, m_nLogLength); m_nWriteLength += m_nLogLength; if (m_nWriteLength >= MD_MAX_STRING - 1 || (m_flagOption & autoNewLine) == autoNewLine) { if (m_nWriteLength >= MD_MAX_STRING - 1) m_nWriteLength--; m_szWriteString[m_nWriteLength++] = '\n'; } #ifdef _WIN32 #pragma warning(disable:4267) #endif if (m_nFileLimitSize > 0 && m_nFileLimitSize <= lseek(m_fhLog, 0L, SEEK_CUR)) { const static char * pszFirstTxt = "Log writing was contiued from file end. See date and time of end line.\n--------------------------------\n"; #ifdef _WIN32 _chsize(m_fhLog, m_nFileLimitSize / 4); #else ftruncate(m_fhLog, m_nFileLimitSize / 4); #endif lseek(m_fhLog, 0L, SEEK_SET); write(m_fhLog, pszFirstTxt, strlen(pszFirstTxt)); } OnWrite(m_szWriteString, m_nWriteLength); if ((m_flagOption & consoleWrite) == consoleWrite) fwrite(m_szWriteString, sizeof(char), m_nWriteLength, stdout); //#ifdef _WIN32 //#pragma warning(default:4267) // _commit(m_fhLog); //#endif if (m_pExtension) m_pExtension->OnWrite(m_szWriteString, m_nWriteLength); }