#include "stdafx.h" #include "ServerLog.h" #include "../Utility/Debug/DebugUtils.h" CServerLog g_Log; CServerLog g_PacketLog("Packet", 0); CServerLog g_SessionLog("SessionLog", 0); CServerLog g_SkillLog("SkillLog", 0); enum LOG_CONSTANT { MAX_LOG_PER_SIZE = 16384, MAX_LOG_FILE_SIZE = 50 * 1024 * 1024, // 100Mega MAX_LOG_BUFFER = 256 * 1024, MAX_LOG_BUFFER_BOUND = 248 * 1024 }; static const char* s_LogType[MAX_LOG_TYPE] = { "NOR", // Normal "RUL", // Game manager things "INF", // Informations about current status "DET", // Detail "SER", // System call error "ERR", // Fatal error (must be fixed!) "DBG", // Debug related informations "WRN", // Warning (must be fixed!) }; CServerLog::CServerLog(const char* szLogName, const char* szPathName) : m_hFile(INVALID_HANDLE_VALUE), m_dwTotalFileWriteSize(0LL), m_dwTotalLoggedSize(0LL), m_dwCurrentFileWriteSize(0), m_dwBufferUsed(0), m_dwLogEnabled(0xFFFFFFFF) { if(0 != szLogName) { _snprintf(m_szProgramName, MAX_PATH - 1, "%s", szLogName); m_szProgramName[MAX_PATH - 1] = 0; } else { DbgUtils::SetProgramName(m_szProgramName, MAX_PATH); } if(0 != szPathName) { _snprintf(m_szLogPath, MAX_PATH - 1, "%s", szPathName); m_szLogPath[MAX_PATH - 1] = 0; } else { DbgUtils::SetProgramName(m_szLogPath, MAX_PATH); } m_lpBuffer = new (std::nothrow) char[MAX_LOG_BUFFER]; } CServerLog::~CServerLog() { ServerLogLock::Syncronize sync(m_ServerLogLock); SimpleLog(LOG_NORMAL, "·Î±×¸¦ ³¡³À´Ï´Ù."); if(0 != m_dwBufferUsed) { InternalFlush(); } if(INVALID_HANDLE_VALUE != m_hFile) { CloseHandle(m_hFile); } delete [] m_lpBuffer; m_lpBuffer = 0; } void _cdecl CServerLog::Log(const char* pFormat, ...) { // Lock and Push ServerLogLock::Syncronize sync(m_ServerLogLock); va_list arguments; va_start_ext(arguments, pFormat); int nLength = _vsntprintf(m_lpBuffer + m_dwBufferUsed, MAX_LOG_BUFFER - m_dwBufferUsed, pFormat, arguments); va_end(arguments); if(0 < nLength) { m_dwBufferUsed += nLength; m_dwTotalLoggedSize += nLength; } if(MAX_LOG_BUFFER_BOUND <= m_dwBufferUsed) { InternalFlush(); } } void _cdecl CServerLog::SimpleLog(LOG_TYPE eLogType, const char* pFormat, ...) { /* LOG_NORMAL, // ÀÏ¹Ý ·Î±× (Ŭ·¡½º »ý¼º, Á¾·á) LOG_RULE, // ¿î¿µ °ü·Ã ·Î±× LOG_INFO, // Á¤º¸ °ü·Ã ·Î±× */ if(!(m_dwLogEnabled & (1 << eLogType))) { // EnabledµÈ ·Î±×°¡ ¾Æ´Ï´Ù. ÂïÁö ¾Ê´Â´Ù. return; } if(0 != m_lpBuffer) { int nLogSize = 0; char szBuffer[MAX_LOG_PER_SIZE]; switch(eLogType) { case LOG_NORMAL: nLogSize = _snprintf(szBuffer, MAX_LOG_PER_SIZE, "[Ty-%s][", s_LogType[eLogType]); break; case LOG_RULE: case LOG_INFO: { SYSTEMTIME sysTime; GetLocalTime(&sysTime); nLogSize = _snprintf(szBuffer, MAX_LOG_PER_SIZE, "[Ty-%s][Tm-%04d-%02d-%02d %02d:%02d:%02d][Ex-", s_LogType[eLogType], sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond); } break; }; va_list arguments; va_start_ext(arguments, pFormat); nLogSize += _vsntprintf(szBuffer + nLogSize, MAX_LOG_PER_SIZE - nLogSize, pFormat, arguments); va_end(arguments); // Lock and Push ServerLogLock::Syncronize sync(m_ServerLogLock); int nLength = _snprintf(m_lpBuffer + m_dwBufferUsed, MAX_LOG_BUFFER - m_dwBufferUsed, "%s]\r\n", szBuffer); if(0 < nLength) { m_dwBufferUsed += nLength; m_dwTotalLoggedSize += nLength; } if(MAX_LOG_BUFFER_BOUND <= m_dwBufferUsed) { InternalFlush(); } } } void _cdecl CServerLog::DetailLog(LOG_TYPE eLogType, const char* pRtn, const char* pFileName, int nLine, const char* pFormat, ...) { /* LOG_DETAIL, // ÇÏÀÌ µðÅ×ÀÏ °ü·Ã ·Î±× LOG_SYSERR, // ½Ã½ºÅÛ ÇÔ¼ö ¿¡·¯ °ü·Ã ·Î±× LOG_ERROR, // ¿¡·¯ °ü·Ã ·Î±× LOG_DEBUG, // µð¹ö±× °ü·Ã ·Î±× LOG_WARN, // °æ°í °ü·Ã ·Î±× */ if(!(m_dwLogEnabled & (1 << eLogType))) { // EnabledµÈ ·Î±×°¡ ¾Æ´Ï´Ù. ÂïÁö ¾Ê´Â´Ù. return; } if(0 != m_lpBuffer) { SYSTEMTIME sysTime; GetLocalTime(&sysTime); int nLogSize = 0; char szBuffer[MAX_LOG_PER_SIZE]; nLogSize = _snprintf(szBuffer, MAX_LOG_PER_SIZE, "[Ty-%s][Tm-%04d-%02d-%02d %02d:%02d:%02d][Ex-", s_LogType[eLogType], sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond); va_list arguments; va_start_ext(arguments, pFormat); nLogSize += _vsntprintf(szBuffer + nLogSize, MAX_LOG_PER_SIZE - nLogSize, pFormat, arguments); va_end(arguments); ServerLogLock::Syncronize sync(m_ServerLogLock); int nLength = _snprintf(m_lpBuffer + m_dwBufferUsed, MAX_LOG_BUFFER - m_dwBufferUsed, "%s][Rt-%s][FN-%s][LN-%d]\r\n", szBuffer, pRtn, pFileName, nLine); if(0 < nLength) { m_dwBufferUsed += nLength; m_dwTotalLoggedSize += nLength; } if(m_dwBufferUsed >= MAX_LOG_BUFFER_BOUND || eLogType == LOG_SYSERR) { InternalFlush(); } } } void CServerLog::SetLogFileName(const char* szLogName, const char* szPathName) { ServerLogLock::Syncronize sync(m_ServerLogLock); if(0 < m_dwBufferUsed) { InternalFlush(); } if(INVALID_HANDLE_VALUE != m_hFile) { CloseHandle(m_hFile); m_hFile = INVALID_HANDLE_VALUE; } if(0 != szLogName) { _snprintf(m_szProgramName, MAX_PATH - 1, "%s", szLogName); m_szProgramName[MAX_PATH - 1] = 0; } else { DbgUtils::SetProgramName(m_szProgramName, MAX_PATH); } if(0 != szPathName) { _snprintf(m_szLogPath, MAX_PATH - 1, "%s", szPathName); m_szLogPath[MAX_PATH - 1] = 0; } else { DbgUtils::SetProgramName(m_szLogPath, MAX_PATH); } } HANDLE CServerLog::CreateLogFile() { // 1. ·Î±× µð·ºÅ丮¸¦ »ý¼º. // 2. ·Î±× ÆÄÀÏÀ» »ý¼º. // 3. ÆÄÀÏÀ» ¿­¾î¼­ ÇÚµé ¸®ÅÏ. char szTime[MAX_PATH]; char szFileName[MAX_PATH]; if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(m_szLogPath)) { if (!CreateDirectory(m_szLogPath, 0)) { return INVALID_HANDLE_VALUE; } } SYSTEMTIME sysTime; GetLocalTime(&sysTime); _snprintf(szTime, MAX_PATH, TEXT("%s%04d-%02d-%02d %02d,%02d,%02d-"), m_szProgramName, sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond); // create log file name in good order for(unsigned long dwSpinCount = 0; TRUE; ++dwSpinCount) { int nLength = _snprintf(szFileName, MAX_PATH, "%s/%s%04d.log", m_szLogPath, szTime, dwSpinCount); if(nLength < 0) { return INVALID_HANDLE_VALUE; } if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(szFileName)) { break; } } m_dwCurrentFileWriteSize = 0; return CreateFile(szFileName, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0); } void CServerLog::InternalFlush() { unsigned long dwWritten = 0; if(INVALID_HANDLE_VALUE == m_hFile) { m_hFile = CreateLogFile(); } WriteFile(m_hFile, m_lpBuffer, m_dwBufferUsed, &dwWritten, 0); m_dwCurrentFileWriteSize += dwWritten; m_dwBufferUsed = 0; if(MAX_LOG_FILE_SIZE < m_dwCurrentFileWriteSize) { CloseHandle(m_hFile); m_hFile = CreateLogFile(); }; } void CServerLog::Dump(const char* szSignature, char* lpDumpPos, size_t nLength) { FILE* fFile = fopen("DumpMemory.txt", "ab"); if(0 != fFile) { SYSTEMTIME sysTime; GetLocalTime(&sysTime); __try { fprintf(fFile, "\n %s : Dump Memory [%04d-%02d-%02d %02d,%02d,%02d]: %s \r\n<", m_szProgramName, sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, szSignature); fwrite(lpDumpPos, nLength, 1, fFile); } __finally { fprintf(fFile, ">\r\n"); fclose(fFile); } } } bool CServerLog::NewLog() { if(INVALID_HANDLE_VALUE != m_hFile) CloseHandle(m_hFile); m_hFile = CreateLogFile(); if(INVALID_HANDLE_VALUE == m_hFile) return false; else return true; }