X Tutup
/* * Copyright (C) 2012 Yee Young Han (http://blog.naver.com/websearch) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "FileUtility.h" #include #include #include #include "Log.h" #include "TimeUtility.h" #ifdef WIN32 #include #else #include #include #endif #include "MemoryDebug.h" // CLog Ŭ·¡½ºÀÇ Á¤Àû º¯¼ö¸¦ ÃʱâÈ­ ÇÑ´Ù. char * CLog::m_pszDirName = NULL; char CLog::m_szDate[9] = { '\0' }; FILE * CLog::m_sttFd = NULL; CSipMutex * CLog::m_pThreadMutex = NULL; int CLog::m_iLevel = LOG_ERROR; int CLog::m_iMaxLogSize = DEFAULT_LOG_FILE_SIZE; int CLog::m_iLogSize = 0; int64_t CLog::m_iMaxFolderSize = DEFAULT_LOG_FOLDER_SIZE; int64_t CLog::m_iFolderSize = 0; int CLog::m_iIndex = 1; ILogCallBack * CLog::m_pclsCallBack = NULL; /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏÀ» ÀúÀåÇÒ µð·ºÅ丮¸¦ ¼³Á¤ÇÑ´Ù. ¸¸¾à thread mutex °¡ ¼³Á¤µÇ¾î ÀÖÁö ¾ÊÀ¸¸é ¾²·¹µå mutex ¸¦ »ý¼ºÇÑ´Ù. * @param pszDirName [in] ·Î±× ÆÄÀÏÀ» ÀúÀåÇÒ µð·ºÅ丮 * @return ¼º°øÇϸé true ¸¦ ¸®ÅÏÇÏ°í ±×·¸Áö ¾ÊÀ¸¸é false ¸¦ ¸®ÅÏÇÑ´Ù. */ bool CLog::SetDirectory( const char * pszDirName ) { if( pszDirName == NULL ) return false; if( m_pThreadMutex == NULL ) { m_pThreadMutex = new CSipMutex(); if( m_pThreadMutex == NULL ) return false; } if( m_pThreadMutex->acquire() == false ) return false; if( m_pszDirName == NULL ) { int iLen = (int)strlen(pszDirName); m_pszDirName = new char[ iLen + 1 ]; if( m_pszDirName == NULL ) return false; sprintf( m_pszDirName, "%s", pszDirName ); #ifdef WIN32 if( m_pszDirName[iLen-1] == '\\' ) #else if( m_pszDirName[iLen-1] == '/' ) #endif { m_pszDirName[iLen-1] = '\0'; } } m_pThreadMutex->release(); if( CDirectory::Create( m_pszDirName ) == false ) return false; m_iFolderSize = CDirectory::GetSize( m_pszDirName ); return true; } /** * @ingroup SipPlatform * @brief Ŭ·¡½º º¯¼ö¸¦ ÃʱâÈ­½ÃŲ´Ù. */ void CLog::Release() { if( CLog::m_pszDirName ) { delete [] m_pszDirName; m_pszDirName = NULL; } if( m_pThreadMutex ) { delete CLog::m_pThreadMutex; m_pThreadMutex = NULL; } } /** * @ingroup SipPlatform * @brief ·Î±× Ãâ·Â callback ÀÎÅÍÆäÀ̽º¸¦ µî·ÏÇÑ´Ù. * @param pclsCallBack ·Î±× Ãâ·Â callback ÀÎÅÍÆäÀ̽º */ void CLog::SetCallBack( ILogCallBack * pclsCallBack ) { m_pclsCallBack = pclsCallBack; } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏ¿¡ ·Î±×¸¦ ÀúÀåÇÑ´Ù. * @param iLevel [in] ·Î±× ÆÄÀÏ ·¹º§ * @param fmt [in] ·Î±× ÆÄÀÏ¿¡ ÀúÀåÇÒ Æ÷¸Ë ¹®ÀÚ¿­ * @param ... [in] fmt Æ÷¸Ë¿¡ ÀÔ·ÂÇÒ ÀÎÀÚµé * @return ÀԷ¿¡ ¼º°øÇϸé 0 À» ¸®ÅÏÇÑ´Ù. * ÀԷ°ªÀÌ À߸øµÈ °æ¿ì¿¡´Â -1À» ¸®ÅÏÇÑ´Ù. * mutex lock ¿¡ ½ÇÆÐÇÑ °æ¿ì¿¡´Â -1À» ¸®ÅÏÇÑ´Ù. * ·Î±× ÆÄÀÏ Open ¿¡ ½ÇÆÐÇϸé -1À» ¸®ÅÏÇÑ´Ù. * ·Î±× ·¹º§ÀÌ ¼³Á¤µÈ ·Î±× ·¹º§°ú ÀÏÄ¡ÇÏÁö ¾Ê´Â °æ¿ì¿¡´Â 1À» ¸®ÅÏÇÑ´Ù. */ int CLog::Print( EnumLogLevel iLevel, const char * fmt, ... ) { if( ( m_iLevel & iLevel ) == 0 ) return 1; va_list ap; char szBuf[LOG_MAX_SIZE]; char szDate[9], szHeader[30]; int iResult = 0; struct tm sttTm; switch( iLevel ) { case LOG_ERROR: snprintf( szHeader, sizeof(szHeader), "[ERROR] " ); break; case LOG_INFO: snprintf( szHeader, sizeof(szHeader), "[INFO] " ); break; case LOG_DEBUG: snprintf( szHeader, sizeof(szHeader), "[DEBUG] " ); break; case LOG_NETWORK: snprintf( szHeader, sizeof(szHeader), "[NETWORK] " ); break; case LOG_SYSTEM: snprintf( szHeader, sizeof(szHeader), "[SYSTEM] " ); break; case LOG_SQL: snprintf( szHeader, sizeof(szHeader), "[SQL] " ); break; default: memset( szHeader, 0, sizeof(szHeader) ); break; } // ÇöÀçÀÇ ½Ã°£À» ±¸ÇÑ´Ù. struct timeval sttTime; gettimeofday( &sttTime, NULL ); #ifdef WIN32 _localtime32_s( &sttTm, &sttTime.tv_sec ); #else localtime_r( &sttTime.tv_sec, &sttTm ); #endif snprintf( szDate, sizeof(szDate), "%04d%02d%02d", sttTm.tm_year + 1900, sttTm.tm_mon + 1, sttTm.tm_mday ); if( m_pThreadMutex && m_pThreadMutex->acquire() == false ) return -1; if( m_pszDirName && strcmp( m_szDate, szDate ) ) { // ÇöÀçÀÇ ³¯Â¥¿Í Ŭ·¡½º¿¡ ÀúÀåµÈ ³¯Â¥°¡ ´Ù¸¥ °æ¿ì¿¡´Â ·Î±× ÆÄÀÏÀ» »õ·Î // Á¦ÀÛÇÏ¿©¼­ Open ÇÑ´Ù. char szFileName[FULLPATH_FILENAME_MAX_SIZE]; m_iIndex = 1; OPEN_FILE: m_iLogSize = 0; snprintf( szFileName, sizeof(szFileName), "%s%c%04d%02d%02d_%d.txt", m_pszDirName, DIR_SEP, sttTm.tm_year + 1900, sttTm.tm_mon + 1, sttTm.tm_mday, m_iIndex ); // ÀÌ¹Ì Open µÈ ÆÄÀÏÀÌ ÀÖ´Â °æ¿ì¿¡´Â À̸¦ ´Ý´Â´Ù. if( m_sttFd ) { fclose( m_sttFd ); m_sttFd = NULL; } DeleteOldFile(); if( m_iMaxLogSize > 0 ) { int64_t iFileSize = GetFileSize( szFileName ); if( iFileSize >= m_iMaxLogSize ) { ++m_iIndex; goto OPEN_FILE; } m_iLogSize = (int)iFileSize; } m_sttFd = fopen( szFileName, "ab" ); if( m_sttFd == NULL ) { printf( "log file(%s) open error\n", szFileName ); iResult = -1; } snprintf( m_szDate, sizeof(m_szDate), "%s", szDate ); } else if( m_iMaxLogSize > 0 && m_iLogSize >= m_iMaxLogSize ) { ++m_iIndex; goto OPEN_FILE; } if( m_pThreadMutex ) m_pThreadMutex->release(); va_start( ap, fmt ); vsnprintf( szBuf, sizeof(szBuf)-1, fmt, ap ); va_end( ap ); if( m_pThreadMutex && m_pThreadMutex->acquire() == false ) return -1; if( m_sttFd ) { int iWrite; #ifdef WIN32 iWrite = fprintf( m_sttFd, "[%02d:%02d:%02d.%06u] %s[%u] %s\r\n" , sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, sttTime.tv_usec, szHeader, GetCurrentThreadId(), szBuf ); #else iWrite = fprintf( m_sttFd, "[%02d:%02d:%02d.%06u] %s[%lu] %s\n" , sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, (unsigned int)sttTime.tv_usec, szHeader, (unsigned long)pthread_self(), szBuf ); #endif fflush( m_sttFd ); m_iLogSize += iWrite; m_iFolderSize += iWrite; } else if( m_pclsCallBack ) { #ifdef WIN32 m_pclsCallBack->Print( iLevel, "[%u] %s", GetCurrentThreadId(), szBuf ); #else m_pclsCallBack->Print( iLevel, "[%u] %s", (unsigned long)pthread_self(), szBuf ); #endif } else { #ifdef WIN32 printf( "[%02d:%02d:%02d] %s%s\r\n" , sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, szHeader, szBuf ); #else printf( "[%02d:%02d:%02d] %s%s\n" , sttTm.tm_hour, sttTm.tm_min, sttTm.tm_sec, szHeader, szBuf ); #endif } if( m_pThreadMutex ) m_pThreadMutex->release(); return iResult; } /** * @ingroup SipPlatform * @brief ÀÀ¿ë¿¡¼­ ·Î±×¸¦ Ãâ·ÂÇÏ´Â °æ¿ì, FILE ÇÚµéÀ» ÀÀ¿ë ÇÔ¼ö·Î Àü´ÞÇÑ´Ù. * @param func ·Î±× Ãâ·Â ÇÔ¼ö */ void CLog::Print( void (* func)( FILE * fd ) ) { if( m_sttFd == NULL ) return; if( m_pThreadMutex && m_pThreadMutex->acquire() == false ) return; func( m_sttFd ); fflush( m_sttFd ); if( m_pThreadMutex ) m_pThreadMutex->release(); } /** * @ingroup SipPlatform * @brief ·Î±× ·¹º§À» °¡Á®¿Â´Ù. * @return ·Î±× ·¹º§À» ¸®ÅÏÇÑ´Ù. */ int CLog::GetLevel( ) { return m_iLevel; } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏ¿¡ ÀúÀåÇÒ ·Î±× ·¹º§À» ¼³Á¤ÇÑ´Ù. ¿©·¯ ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, '|' ¿¬»êÀÚ¸¦ ÀÌ¿ëÇÏ¿©¼­ ¿©·¯ ·Î±× ·¹º§À» ¼³Á¤ÇÒ ¼ö ÀÖ´Ù. * @param iLevel [in] µð¹ö±× ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, LOG_DEBUG ¸¦ ¼³Á¤ÇÑ´Ù. * Á¤º¸ ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, LOG_INFO ¸¦ ¼³Á¤ÇÑ´Ù. * ¿¡·¯ ·Î±×¸¦ ÀúÀåÇÒ °æ¿ì, LOG_ERROR ¸¦ ¼³Á¤ÇÑ´Ù. */ void CLog::SetLevel( int iLevel ) { m_iLevel = LOG_ERROR | LOG_SYSTEM; m_iLevel |= iLevel; } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏ¿¡ ÀúÀåÇÒ ·Î±× ·¹º§À» ¸ðµÎ »èÁ¦ÇÑ´Ù. * - ·Î±× ÆÄÀÏ¿¡ ·Î±×°¡ ÀúÀåµÇÁö ¾Ê´Â´Ù. */ void CLog::SetNullLevel() { m_iLevel = 0; } /** * @ingroup SipPlatform * @brief µð¹ö±× ·Î±× ·¹º§À» ¼³Á¤ÇÑ´Ù. */ void CLog::SetDebugLevel( ) { m_iLevel |= LOG_DEBUG; } /** * @ingroup SipPlatform * @brief ÀÔ·ÂÇÑ ·Î±× ·¹º§ÀÌ ÇöÀç Ãâ·ÂÇÒ ¼ö ÀÖ´Â ·Î±× ·¹º§ÀÎÁö ºÐ¼®ÇÏ¿© ÁØ´Ù. * @param iLevel [in] ·Î±× ·¹º§ * @return ÇöÀç Ãâ·ÂÇÒ ¼ö ÀÖ´Â ·Î±× ·¹º§ÀÎ °æ¿ì¿¡´Â true ¸¦ ¸®ÅÏÇÏ°í ±×·¸Áö ¾ÊÀ¸¸é false ¸¦ ¸®ÅÏÇÑ´Ù. */ bool CLog::IsPrintLogLevel( EnumLogLevel iLevel ) { if( ( m_iLevel & iLevel ) == 0 ) return false; return true; } /** * @ingroup SipPlatform * @brief ·Î±×¸¦ ÀúÀåÇÒ ÃÖ´ë ÆÄÀÏ Å©±â¸¦ ¼³Á¤ÇÑ´Ù. * @param iSize ·Î±×¸¦ ÀúÀåÇÒ ÃÖ´ë ÆÄÀÏ Å©±â */ void CLog::SetMaxLogSize( int iSize ) { if( iSize < MIN_LOG_FILE_SIZE ) { iSize = MIN_LOG_FILE_SIZE; } else if( iSize > MAX_LOG_FILE_SIZE ) { iSize = MAX_LOG_FILE_SIZE; } m_iMaxLogSize = iSize; } /** * @ingroup SipPlatform * @brief ·Î±× Æú´õ ÃÖ´ë Å©±â¸¦ ¼³Á¤ÇÑ´Ù. * @param iSize ·Î±× Æú´õ ÃÖ´ë Å©±â */ void CLog::SetMaxFolderSize( int64_t iSize ) { // ÃÖ¼Ò 30ÀÏ ·Î±× ÆÄÀÏ ÀúÀå °ø°£À» È®º¸ÇÑ´Ù. if( m_iMaxLogSize == 0 ) { if( iSize < ( MIN_LOG_FILE_SIZE * 30 ) ) { iSize = MIN_LOG_FILE_SIZE * 30; } } else { if( iSize < m_iMaxLogSize * 30 ) { iSize = m_iMaxLogSize * 30; } } m_iMaxFolderSize = iSize; } /** * @ingroup SipPlatform * @brief ·Î±×ÆÄÀÏÀÇ À妽º ¹øÈ£¸¦ ¸®ÅÏÇÑ´Ù. * @return ·Î±×ÆÄÀÏÀÇ À妽º ¹øÈ£¸¦ ¸®ÅÏÇÑ´Ù. */ int CLog::GetLogIndex() { return m_iIndex; } bool LogFileCompare( const std::string & strFirst, const std::string & strSecond ) { int iFirstLen = (int)strFirst.length(); int iSecondLen = (int)strSecond.length(); if( iFirstLen < 10 ) return true; if( iSecondLen < 10 ) return false; int n = strncmp( strFirst.c_str(), strSecond.c_str(), 8 ); if( n < 0 ) return true; if( n > 0 ) return false; int iFirstIndex = atoi( strFirst.c_str() + 9 ); int iSecondIndex = atoi( strSecond.c_str() + 9 ); return ( iFirstIndex < iSecondIndex ); } /** * @ingroup SipPlatform * @brief ·Î±× Æú´õÀÇ Å©±â°¡ ¼³Á¤µÈ Å©±âº¸´Ù Å« °æ¿ì, ¿À·¡µÈ ·Î±× ÆÄÀÏÀ» »èÁ¦ÇÑ´Ù. */ void CLog::DeleteOldFile( ) { if( m_iMaxFolderSize == 0 ) return; if( m_pszDirName == NULL ) return; if( m_iFolderSize >= m_iMaxFolderSize ) { int64_t iWantSize = m_iMaxFolderSize * 8 / 10; FILE_LIST clsFileList; FILE_LIST::iterator itList; int64_t iFileSize; CDirectory::FileList( m_pszDirName, clsFileList ); clsFileList.sort( LogFileCompare ); for( itList = clsFileList.begin(); itList != clsFileList.end(); ++itList ) { std::string strFileName = m_pszDirName; CDirectory::AppendName( strFileName, itList->c_str() ); iFileSize = GetFileSize( strFileName.c_str() ); #ifdef WIN32 DeleteFile( strFileName.c_str() ); #else unlink( strFileName.c_str() ); #endif m_iFolderSize -= iFileSize; if( m_iFolderSize < iWantSize ) break; } } } /** * @ingroup SipPlatform * @brief ·Î±× ÆÄÀÏ ¸®½ºÆ®¸¦ ¿À·¡µÈ ³¯Â¥¿¡¼­ ÃÖ±Ù ³¯Â¥·Î Á¤·ÄÇÑ´Ù. * @param clsFileList ·Î±× ÆÄÀÏ ¸®½ºÆ® */ void CLog::SortFileList( FILE_LIST & clsFileList ) { clsFileList.sort( LogFileCompare ); }
X Tutup