Index: ext/libicpf/src/libicpf/log.cpp =================================================================== diff -u -N --- ext/libicpf/src/libicpf/log.cpp (revision 9c8dee07d9aecabc260a856da2b2dc350b7098a2) +++ ext/libicpf/src/libicpf/log.cpp (revision 0) @@ -1,685 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2001-2008 by J�zef Starosczyk * -* ixen@copyhandler.com * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU Library General Public License * -* (version 2) as published by the Free Software Foundation; * -* * -* 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 Library 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. * -***************************************************************************/ -/** \file log.cpp - * \brief Contains the implamentation of a log class. - */ -#include "log.h" -#include -#include "exception.h" -#include -#include -#include -#include -#include "macros.h" - -#if defined(_WIN32) || defined(_WIN64) - #include - #include - #include -#else - #include -#endif - -#if defined(_WIN32) || defined(_WIN64) - #define ENDL _t("\r\n") -#else - #define ENDL _t("\n") -#endif - -BEGIN_ICPF_NAMESPACE - -/// Table of strings representing the log message types -const tchar_t* __logtype_str[] = { _t("debug"), _t("info"), _t("warning"), _t("error") }; - -/** Constructs a log_file object. - * \param[in] bGlobal - states if this should be treates as a global instance of the log_file. - * Only one global log_file instance could exist in the application. - */ -log_file::log_file() : - m_pszPath(NULL), - m_iMaxSize(262144), - m_bLogStd(false), - m_iLogLevel(level_debug), - m_lock() -{ -#ifdef WIN32 - _fmode=_O_BINARY; -#endif -} - -/** Standard destructor - */ -log_file::~log_file() -{ - delete [] m_pszPath; -} - -/** Initializes the constructed log file. - * \param[in] pszPath - path to a log file to write to - * \param[in] iMaxSize - maximum size of a log file - * \param[in] iLogLevel - minimum log level of the messages to log - * \param[in] bLogStd - log the messages also to stdout/stderr - * \param[in] bClean - cleans the log file upon opening - */ -void log_file::init(const tchar_t* pszPath, int_t iMaxSize, int_t iLogLevel, bool bLogStd, bool bClean) -{ - // store the path and other params - delete [] m_pszPath; - m_pszPath=new tchar_t[_tcslen(pszPath)+1]; - _tcscpy(m_pszPath, pszPath); - - m_iMaxSize=iMaxSize; - m_bLogStd=bLogStd; - m_iLogLevel=iLogLevel; - - // try to open a file - FILE* pFile=_tfopen(pszPath, bClean ? _t("w") : _t("a")); - if (pFile == NULL) - THROW(exception::format(_t("[log_file::init()] Could not open the specified file (") TSTRFMT _t(")")), 0, 0, 0); - - fclose(pFile); -} - -// ============================================================================ -/// icpf::log_file::is_initialized -/// @date 2009/05/19 -/// -/// @brief Checks is the log_file object has been initialized. -/// @return True if it has been initialized, false otherwise. -// ============================================================================ -bool log_file::is_initialized() const throw() -{ - return m_pszPath != 0; -} - -// ============================================================================ -/// icpf::log_file::set_log_level -/// @date 2009/05/23 -/// -/// @brief Changes the log level for this class. -/// @param[in] iLogLevel New log level. -// ============================================================================ -void log_file::set_log_level(int_t iLogLevel) throw() -{ - m_iLogLevel = iLogLevel; -} - -// ============================================================================ -/// icpf::log_file::set_max_size -/// @date 2009/05/23 -/// -/// @brief Sets the max size of the log file. -/// @param[in] iMaxSize Max size of the log file. -// ============================================================================ -void log_file::set_max_size(int_t iMaxSize) throw() -{ - BOOST_ASSERT(iMaxSize > 0); - if(iMaxSize > 0) - m_iMaxSize = iMaxSize; -} - -/** Retrieves the current size of a log file. - * Quite slow function - have to access the file by opening and closing it. - * \return Current file size. - */ -int_t log_file::size() const -{ - assert(m_pszPath); - if(!m_pszPath) - return -1; - - int_t iSize=-1; - FILE* pFile=_tfopen(m_pszPath, _t("r")); - if (pFile != NULL) - { - if (fseek(pFile, 0, SEEK_END) == 0) - iSize=ftell(pFile); - - fclose(pFile); - } - - return iSize; -} - -/** Truncates the current log file content so when adding some new text the - * file size won't exceed the maximum size specified in init(). - * \param[in] iAdd - size of the new string to be added to the log file - * \return True if truncate succeeded or false if not. - */ -bool log_file::truncate(int_t iAdd) const -{ - assert(m_pszPath); - if(!m_pszPath) - return false; - - // if we doesn't need to truncate anything - if (m_iMaxSize <= 0) - return true; - - // make some checks - int_t iSize=size(); - if (iSize <= 0 || iSize+iAdd < m_iMaxSize) - return false; - - // establish the new file size (1/3rd of the current size or max_size-add_size) - int_t iNewSize=minval((int_t)(iSize*0.66), m_iMaxSize-iAdd) & ~1; - -#ifdef _WIN32 - // win32 does not have the ftruncate function, so we have to make some API calls - HANDLE hFile=CreateFile(m_pszPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile != INVALID_HANDLE_VALUE) - { - // seek - if (SetFilePointer(hFile, iSize-iNewSize, NULL, FILE_BEGIN) != INVALID_SET_FILE_POINTER) - { - // read the string to the eol - DWORD dwRD; - tchar_t szBuffer[4096/sizeof(tchar_t)]; - if (ReadFile(hFile, szBuffer, 4096, &dwRD, NULL)) - { - dwRD/=sizeof(tchar_t); - szBuffer[(dwRD > 0) ? dwRD-1 : 0]=_t('\0'); - - // replace the /r and /n in the log to the \0 - for (DWORD i=0;i 0) - { - // seek to the dst - fseek(pFile, iDst, SEEK_SET); - - fflush(pFile); - // write the buffer to the dest offset - tWR=fwrite(szBuffer, 1, tRD, pFile); - iDst+=tWR; - } - - iSrc+=tRD; - } - while(tRD != 0); - - // now truncate the file to the needed size - ftruncate(fileno(pFile), iDst); - - fclose(pFile); - return true; - } - - fclose(pFile); - } -#endif - - return false; -} - -/** Logs a formatted message to a log file. - * \param[in] iType - type of the log message (LT_*) - * \param[in] bStd - log also to stdout/stderr if true - * \param[in] pszStr - format string for the following parameters - */ -void log_file::log(int_t iType, bool bStd, const tchar_t* pszStr, ...) -{ - if (iType < m_iLogLevel) - return; - - va_list va; - va_start(va, pszStr); - logv(iType, bStd, pszStr, va); - va_end(va); -} - -/** Logs a formatted message to a log file. - * \param[in] iType - type of the log message (LT_*) - * \param[in] bStd - log also to stdout/stderr if true - * \param[in] pszStr - format string for the following parameters - * \param[in] va - variable argument list - */ -void log_file::logv(int_t iType, bool bStd, const tchar_t* pszStr, va_list va) -{ - if (iType < m_iLogLevel) - return; - - tchar_t szBuf1[2048]; - _vsntprintf(szBuf1, 2048, pszStr, va); // user passed stuff - - logs(iType, bStd, szBuf1); -} - -/** Logs an unformatted message to a log file. - * \param[in] iType - type of the log message (LT_*) - * \param[in] bStd - log also to stdout/stderr if true - * \param[in] pszStr - message string - */ -void log_file::logs(int_t iType, bool bStd, const tchar_t* pszStr) -{ - assert(m_pszPath); - if(!m_pszPath) - return; - - if (iType < m_iLogLevel || iType < 0 || iType >= sizeof(__logtype_str)) - return; - - // log time - time_t t=time(NULL); - tchar_t szData[128]; - _tcscpy(szData, _tctime(&t)); - size_t tLen=_tcslen(szData)-1; - while(szData[tLen] == _t('\n')) - szData[tLen--]=_t('\0'); - - m_lock.lock(); - - // check the size constraints - truncate((int_t)(_tcslen(pszStr)+1)); -#if defined(UNICODE) && (defined(_WIN32) || defined(_WIN64)) - FILE* pFile=_tfopen(m_pszPath, _t("ab")); -#else - FILE* pFile=_tfopen(m_pszPath, _t("at")); -#endif - bool bFailed=false; - if (pFile) - { - if (_ftprintf(pFile, _t("[") TSTRFMT _t("] [") TSTRFMT _t("] ") TSTRFMT ENDL, szData, __logtype_str[iType], pszStr) < 0) - bFailed=true; - fclose(pFile); - } - else - bFailed=true; - if (bFailed || (m_bLogStd && !bStd)) - { - switch(iType) - { - case level_error: - _ftprintf(stderr, _t("[") TSTRFMT _t("] [") TSTRFMT _t("] ") TSTRFMT ENDL, szData, __logtype_str[iType], pszStr); - break; - default: - _ftprintf(stdout, _t("[") TSTRFMT _t("] [") TSTRFMT _t("] ") TSTRFMT ENDL, szData, __logtype_str[iType], pszStr); - } - } - else if (bStd) - { - switch(iType) - { - case level_error: - _ftprintf(stderr, TSTRFMT _t(": ") TSTRFMT ENDL, __logtype_str[iType], pszStr); - break; - case level_info: - _ftprintf(stdout, TSTRFMT ENDL, pszStr); - break; - default: - _ftprintf(stdout, TSTRFMT _t(": ") TSTRFMT ENDL, __logtype_str[iType], pszStr); - } - } - - m_lock.unlock(); -} - -#ifndef SKIP_LEVEL_DEBUG -/** Logs a formatted debug message to a log file. - * \param[in] pszStr - format string for the given parameters - */ -void log_file::logd(const tchar_t* pszStr) -{ - if (m_iLogLevel > level_debug) - return; - - logs(level_debug, false, pszStr); -} - -/** Logs a formatted debug message to a log file. -* \param[in] pszStr - format string for the given parameters -*/ -void log_file::logdv(const tchar_t* pszStr, ...) -{ - if (m_iLogLevel > level_debug) - return; - - va_list va; - va_start(va, pszStr); - logv(level_debug, false, pszStr, va); - va_end(va); -} - -/** Logs a formatted debug message to a log file(also outputs to stdout). - * \param[in] pszStr - format string for the given parameters - */ -void log_file::logds(const tchar_t* pszStr, ...) -{ - if (m_iLogLevel > level_debug) - return; - - va_list va; - va_start(va, pszStr); - logv(level_debug, true, pszStr, va); - va_end(va); -} - -#else -void log_file::logd(const tchar_t* /*pszStr*/) -{ -} - -void log_file::logdv(const tchar_t* /*pszStr*/, ...) -{ -} - -void log_file::logds(const tchar_t* /*pszStr*/, ...) -{ -} -#endif - -#ifndef SKIP_LEVEL_INFO -/** Logs a formatted informational message to a log file. - * \param[in] pszStr - format string for the given parameters - */ -void log_file::logi(const tchar_t* pszStr) -{ - if (m_iLogLevel > level_info) - return; - - logs(level_info, false, pszStr); -} - -/** Logs a formatted informational message to a log file. -* \param[in] pszStr - format string for the given parameters -*/ -void log_file::logiv(const tchar_t* pszStr, ...) -{ - if (m_iLogLevel > level_info) - return; - - va_list va; - va_start(va, pszStr); - logv(level_info, false, pszStr, va); - va_end(va); -} - -/** Logs a formatted informational message to a log file(also outputs to stdout). - * \param[in] pszStr - format string for the given parameters - */ -void log_file::logis(const tchar_t* pszStr, ...) -{ - if (m_iLogLevel > level_info) - return; - - va_list va; - va_start(va, pszStr); - logv(level_info, true, pszStr, va); - va_end(va); -} -#else -void log_file::logi(const tchar_t* /*pszStr*/) -{ -} - -void log_file::logiv(const tchar_t* /*pszStr*/, ...) -{ -} - -void log_file::logis(const tchar_t* /*pszStr*/, ...) -{ -} - -#endif - -#ifndef SKIP_LEVEL_WARNING -/** Logs a formatted warning message to a log file. - * \param[in] pszStr - format string for the given parameters - */ -void log_file::logw(const tchar_t* pszStr) -{ - if (m_iLogLevel > level_warning) - return; - - logs(level_warning, false, pszStr); -} - -/** Logs a formatted warning message to a log file. -* \param[in] pszStr - format string for the given parameters -*/ -void log_file::logwv(const tchar_t* pszStr, ...) -{ - if (m_iLogLevel > level_warning) - return; - - va_list va; - va_start(va, pszStr); - logv(level_warning, false, pszStr, va); - va_end(va); -} - -/** Logs a formatted warning message to a log file(also outputs to stdout). - * \param[in] pszStr - format string for the given parameters - */ -void log_file::logws(const tchar_t* pszStr, ...) -{ - if (m_iLogLevel > level_warning) - return; - va_list va; - va_start(va, pszStr); - logv(level_warning, true, pszStr, va); - va_end(va); -} - -#else -void log_file::logw(const tchar_t* /*pszStr*/) -{ -} - -void log_file::logwv(const tchar_t* /*pszStr*/, ...) -{ -} - -void log_file::logws(const tchar_t* /*pszStr*/, ...) -{ -} - -#endif - -/** Logs a formatted error message to a log file. - * \param[in] pszStr - format string for the given parameters - */ -void log_file::loge(const tchar_t* pszStr) -{ - logs(level_error, false, pszStr); -} - -/** Logs a formatted error message to a log file. -* \param[in] pszStr - format string for the given parameters -*/ -void log_file::logev(const tchar_t* pszStr, ...) -{ - va_list va; - va_start(va, pszStr); - logv(level_error, false, pszStr, va); - va_end(va); -} - -/** Logs a formatted error message to a log file(also outputs to stderr). - * \param[in] pszStr - format string for the given parameters - */ -void log_file::loges(const tchar_t* pszStr, ...) -{ - va_list va; - va_start(va, pszStr); - logv(level_error, true, pszStr, va); - va_end(va); -} - -/** Logs a formatted error message to a log file(also outputs to stderr). - * As an addition the first string %err is replaced with a given error - * followed by the error description (system-based). - * \param[in] pszStr - format string for the given parameters - * \param[in] iSysErr - system error to be shown - */ -void log_file::logerr(const tchar_t* pszStr, int_t iSysErr, ...) -{ - tchar_t szNewFmt[2048]; - if (prepare_fmt(pszStr, iSysErr, szNewFmt)) - { - va_list va; - va_start(va, iSysErr); - logv(level_error, false, szNewFmt, va); - va_end(va); - } - else - { - va_list va; - va_start(va, iSysErr); - logv(level_error, false, pszStr, va); - va_end(va); - } -} - -/** Logs a formatted error message to a log file(also outputs to stderr). - * As an addition the first string %err is replaced with a given error - * followed by the error description (system-based). - * This function differ from logerr() with logging the output string - * also to the stderr. - * \param[in] pszStr - format string for the given parameters - * \param[in] iSysErr - system error to be shown - */ -void log_file::logerrs(const tchar_t* pszStr, int_t iSysErr, ...) -{ - tchar_t szNewFmt[2048]; - if (prepare_fmt(pszStr, iSysErr, szNewFmt)) - { - va_list va; - va_start(va, iSysErr); - logv(level_error, true, szNewFmt, va); - va_end(va); - } - else - { - va_list va; - va_start(va, iSysErr); - logv(level_error, true, pszStr, va); - va_end(va); - } -} - -/** Function prepares a format string with error number and an error message - * for use with logerr() and logerrs() functions. - * \param[in] pszStr - input format string (%err will be replaced with a 0x%lx (error message) - * \param[in] iSysError - system error to parse - * \param[out] pszOut - pointer to a buffer that will receive the data (must be 2048 bytes in size) - * \return If the %err string was found and replaced within a given format string. - */ -bool log_file::prepare_fmt(const tchar_t* pszStr, int_t iSysErr, tchar_t* pszOut) const -{ - // find the %err in pszStr - const tchar_t* pszFnd=_tcsstr(pszStr, _t("%err")); - if (pszFnd) - { - // find an error description for the error - tchar_t* pszErrDesc=NULL; -#ifdef _WIN32 - tchar_t szErrDesc[512]; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, (DWORD)iSysErr, 0, szErrDesc, 512, NULL); - pszErrDesc=szErrDesc; -#else - pszErrDesc=strerror(iSysErr); -#endif - - // format a string with err no and desc - tchar_t szError[1024]; - _sntprintf(szError, 1023, _t("0x%lx (%s)"), iSysErr, pszErrDesc); - szError[1023] = _T('\0'); - - // replace %err with the new data - pszOut[0]=_t('\0'); - _tcsncat(pszOut, pszStr, (size_t)(pszFnd-pszStr)); - _tcscat(pszOut, szError); - _tcscat(pszOut, pszFnd+4); - - return true; - } - else - return false; -} - -END_ICPF_NAMESPACE