/************** Begin of log.c *******************************************/ /* * log.cpp * * added by jesse in 2008-2-3 * 日志相关代码的定义文件 */ #ifdef HAVE_CONFIG_H #endif #include "log4c/config.h" #include #include #ifdef HAVE_ALLOCA_H #include #endif #include "sd/sprintf.h" #include "sd/malloc.h" #include "sd/factory.h" #include "log4c/appender.h" #include "log4c/priority.h" #include "log4c/logging_event.h" #include "log4c/category.h" #include "log4c/rc.h" #include "sd/error.h" #include "sd/sd_xplatform.h" #include "sd/sd_xplatform.h" #include #include "log4c/vos.h" #include "log4c/log.h" #include "GlobalMacro.h" ////////////////////////////////////////////////////////////////////////// ///下面括起来代码和log_check拷贝自init.c typedef struct log_c_rcfile { TCHAR name[256]; time_t ctime; int exists; } log_c_rcfile_t; static log_c_rcfile_t log_c_rcfiles[] = { #if 1 { _T("$LOG4C_RCPATH/log4crc.txt") }, { _T("$HOME/log4crc.txt") }, #endif { _T("./log4crc.txt") } }; static const int log_c_nrcfiles = sizeof(log_c_rcfiles) / sizeof(log_c_rcfiles[0]); ////////////////////////////////////////////////////////////////////////// static SEM_ID gs_semphore = NULL; static int gs_iModuleUsage_shmid = 0; ////////////////////////////////////////////////////////////////////////// /************************************************************************/ /* 函数:[3/11/2016 IT]; /* 描述:日志模块初始化; /* 参数:; /* [IN] :; /* 返回:成功返回0; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ int log_init() { ///设置两个环境变量SD_DEBUG和SD_ERROR,使sd_debug和sd_error两个函数起作用 ///putenv("SD_DEBUG=SD_DEBUG"); ///putenv("SD_ERROR=SD_ERROR"); log_check(); return log4c_init(); } /************************************************************************/ /* 函数:log_init_with_cfg_file[3/11/2016 IT]; /* 描述:日志模块初始化,指定配置文件名称; /* 参数:; /* [IN] strCfgFileName:配置文件名; /* 返回:成功返回0; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ int log_init_with_cfg_file(const TCHAR *strCfgFileName) { log_check_with_cfg_file(strCfgFileName); return log4c_init_with_cfg_file(strCfgFileName); } extern void ReleaseModuleUsage(); /************************************************************************/ /* 函数:log_fini[3/11/2016 IT]; /* 描述:日志模块清理; /* 参数:; /* [IN] :; /* 返回:成功返回0; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ int log_fini() { int iResult = log4c_fini(); // 解决资源泄漏 [4/18/2009 jesse]; VOS_DELETE_SEM(gs_semphore); ReleaseModuleUsage(); return iResult; } /************************************************************************/ /* 函数:log_check[3/11/2016 IT]; /* 描述:检测配置文件是否存在; /* 参数:; /* [IN] :; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ const int log_check(void) { int iReturn = 0; BOOL bCfgFileExist = FALSE; int i = 0; _tprintf(_T("check configuration files...\n")); /* check configuration files */ _tprintf(_T("looking for conf files...\n")); #if 1 _sntprintf( log_c_rcfiles[0].name, sizeof(log_c_rcfiles[0].name) - 1, _T("%s/log4crc.txt"), _tgetenv(_T("LOG4C_RCPATH")) ? _tgetenv(_T("LOG4C_RCPATH")) : LOG4C_RCPATH); _sntprintf( log_c_rcfiles[1].name, sizeof(log_c_rcfiles[1].name) - 1, _T("%s/.log4crc.txt"), _tgetenv(_T("HOME")) ? _tgetenv(_T("HOME")) : _T("")); #endif for (i = 0; i < log_c_nrcfiles; i++) { _tprintf(_T("checking for conf file at '%s'\n"), log_c_rcfiles[i].name); if (SD_ACCESS_READ(log_c_rcfiles[i].name)) { continue; } if (SD_STAT_CTIME(log_c_rcfiles[i].name,&log_c_rcfiles[i].ctime) != 0) { sd_error(_T("sd_stat_ctime %s failed"), log_c_rcfiles[i].name); } log_c_rcfiles[i].exists=1; bCfgFileExist = TRUE; #if 0 if (log4c_load(log_c_rcfiles[i].name) == -1) { sd_error("loading %s failed", log_c_rcfiles[i].name); iReturn = -1; } else { printf("loading %s succeeded\n", log_c_rcfiles[i].name); break; } #endif } if (TRUE == bCfgFileExist) { _tprintf(_T("find configuration file\n")); } else { _tprintf(_T("can't find configuration file,\nplease put you conf file in the same dir of execute file.\n")); } return iReturn; } /************************************************************************/ /* 函数:log_check_with_cfg_file[3/11/2016 IT]; /* 描述:检测配置文件是否存在,只检测传入的配置文件名; /* 参数:; /* [IN] strCfgFileName:配置文件名; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ const int log_check_with_cfg_file(const TCHAR *strCfgFileName) { int iReturn = 0; BOOL bCfgFileExist = FALSE; int i = 0; _tprintf(_T("check configuration files...\n")); /* check configuration files */ _tprintf(_T("looking for conf files...\n")); #if 1 _sntprintf( log_c_rcfiles[0].name, sizeof(log_c_rcfiles[0].name) - 1, _T("%s/log4crc.txt"), _tgetenv(_T("LOG4C_RCPATH")) ? _tgetenv(_T("LOG4C_RCPATH")) : LOG4C_RCPATH); _sntprintf( log_c_rcfiles[1].name, sizeof(log_c_rcfiles[1].name) - 1, _T("%s/.log4crc.txt"), _tgetenv(_T("HOME")) ? _tgetenv(_T("HOME")) : _T("")); #endif if(NULL == strCfgFileName) { iReturn = -1; } else { _tprintf(_T("checking for conf file at '%s'\n"), strCfgFileName); if (SD_ACCESS_READ(strCfgFileName)) { iReturn = -1; } else { if (SD_STAT_CTIME(strCfgFileName,&log_c_rcfiles[i].ctime) != 0) { sd_error(_T("sd_stat_ctime %s failed"), strCfgFileName); } bCfgFileExist = TRUE; #if 0 if (log4c_load(strCfgFileName) == -1) { sd_error("loading %s failed", strCfgFileName); iReturn = -1; } else { printf("loading %s succeeded\n", strCfgFileName); } #endif } } if (TRUE == bCfgFileExist) { _tprintf(_T("find configuration file\n")); } else { _tprintf(_T("can't find configuration file,\nplease put you conf file in the same dir of execute file.\n")); } return iReturn; } /************************************************************************/ /* 函数:log_msg[3/11/2016 IT]; /* 描述:日志记录为一个字符串指针指向的内容; /* 参数:; /* [IN] strFile:文件名; /* [IN] iLineNum:行号; /* [IN] strCatName:Category名; /* [IN] iPriority:日志记录级别; /* [IN] strFormat:日志内容格式; /* [IN] ...:日志内容; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ void log_msg(const TCHAR *strFile, const int iLineNum, const TCHAR *strCatName, const int iPriority, const TCHAR *strFormat, ...) { const log4c_category_t* a_category = log4c_category_get(strCatName); if (log4c_category_is_priority_enabled(a_category, iPriority)) { va_list va; va_start(va, strFormat); ///下面从带路径的文件名解析出不带路径的纯文件名 { ///static SEM_ID semphore = NULL; const TCHAR * strFilePath = strFile; const TCHAR * strFileName = _tcsrchr(strFilePath, _T('/')); TCHAR strMsgBuffer[LOG4C_BUFFER_SIZE_MAX] = {0}; ///为线程安全这里加锁,[2/15/2008 jesse] if (NULL == gs_semphore) { gs_semphore = VOS_CreateMSem(VOS_SEM_Q_FIFO); } VOS_TakeSem(gs_semphore, VOS_WAIT_FOREVER); if (strFileName != NULL) { strFileName++; } else { strFileName = _tcsrchr(strFilePath, _T('\\')); if (strFileName != NULL) { strFileName++; } else { strFileName = strFilePath; } } _sntprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, _T("%-8s(%d) %s\n"), strFileName, iLineNum, strFormat); log4c_category_vlog(a_category, iPriority, strMsgBuffer, va); // 解锁 [2/15/2008 jesse] VOS_GiveSem(gs_semphore); } va_end(va); } } /************************************************************************/ /* 函数:[3/11/2016 IT]; /* 描述:日志记录为一个字符串指针指向的内容; /* 参数:; /* [IN] strFile:文件名; /* [IN] strFuncName:函数名; /* [IN] iLineNum:行号; /* [IN] strCatName:Category名; /* [IN] iPriority:日志记录级别; /* [IN] strFormat:日志内容格式; /* [IN] ...:日志内容; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ void log_msg_func( const TCHAR *strFile, const TCHAR *strFuncName, const int iLineNum, const TCHAR *strCatName, const int iPriority, const TCHAR *strFormat, ... ) { const log4c_category_t* a_category = log4c_category_get(strCatName); if (log4c_category_is_priority_enabled(a_category, iPriority)) { va_list va; va_start(va, strFormat); ///下面从带路径的文件名解析出不带路径的纯文件名 { ///static SEM_ID semphore = NULL; const TCHAR * strFilePath = strFile; const TCHAR * strFileName = _tcsrchr(strFilePath, _T('/')); TCHAR strMsgBuffer[LOG4C_BUFFER_SIZE_MAX] = {0}; ///为线程安全这里加锁,[2/15/2008 jesse] if (NULL == gs_semphore) { gs_semphore = VOS_CreateMSem(VOS_SEM_Q_FIFO); } VOS_TakeSem(gs_semphore, VOS_WAIT_FOREVER); if (strFileName != NULL) { strFileName++; } else { strFileName = _tcsrchr(strFilePath, _T('\\')); if (strFileName != NULL) { strFileName++; } else { strFileName = strFilePath; } } _sntprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, _T("%-8s(%d) Function:%s %s\n"), strFileName, iLineNum, strFuncName, strFormat); log4c_category_vlog(a_category, iPriority, strMsgBuffer, va); // 解锁 [2/15/2008 jesse] VOS_GiveSem(gs_semphore); } va_end(va); } } /** 日志记录,不记录文件名和行号 日志记录为一个字符串指针指向的内容 @return void 作者:jesse 日期:2008-2-3 */ void log_msg_no_file_num( const TCHAR *strCatName, ///category名 const int iPriority, ///日志记录级别 const TCHAR *strFormat, ///日志内容格式 ... ///日志内容 ) { const log4c_category_t* a_category = log4c_category_get(strCatName); if (log4c_category_is_priority_enabled(a_category, iPriority)) { va_list va; va_start(va, strFormat); { ///static SEM_ID semphore = NULL; TCHAR strMsgBuffer[10240] = {0}; ///为线程安全这里加锁,[2/15/2008 jesse] if (NULL == gs_semphore) { gs_semphore = VOS_CreateMSem(VOS_SEM_Q_FIFO); } VOS_TakeSem(gs_semphore, VOS_WAIT_FOREVER); _sntprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, _T("%s\n"), strFormat); log4c_category_vlog(a_category, iPriority, strMsgBuffer, va); // 解锁 [2/15/2008 jesse] VOS_GiveSem(gs_semphore); } va_end(va); } } /** 日志记录,不记录文件名和行号,没有任何layout转换,直接输出相应的字符文本到日志中 此条记录没有行号,也没有线程号,也没有回车等 日志记录为一个字符串指针指向的内容 @return void 作者:jesse 日期:2008-9-14 */ void log_msg_no_file_num_no_layout( const TCHAR *strCatName, ///category名 const int iPriority, ///日志记录级别 const TCHAR *strFormat, ///日志内容格式 ... ///日志内容 ) { const log4c_category_t* a_category = log4c_category_get(strCatName); if (log4c_category_is_priority_enabled(a_category, iPriority)) { va_list va; va_start(va, strFormat); { ///static SEM_ID semphore = NULL; TCHAR strMsgBuffer[10240] = {0}; ///为线程安全这里加锁,[2/15/2008 jesse] if (NULL == gs_semphore) { gs_semphore = VOS_CreateMSem(VOS_SEM_Q_FIFO); } VOS_TakeSem(gs_semphore, VOS_WAIT_FOREVER); _sntprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, _T("%s"), strFormat); log4c_category_vlog_no_file_num_no_layout(a_category, iPriority, strMsgBuffer, va); // 解锁 [2/15/2008 jesse] VOS_GiveSem(gs_semphore); } va_end(va); } } /** 设置appender @return int: 作者:jesse 日期:2008-2-3 */ int log_setappender( const TCHAR *strCatName, ///category名 const TCHAR *strAppenderName ///appender名 ) { log4c_category_set_appender(log4c_category_get(strCatName), log4c_appender_get(strAppenderName)); return(0); } /** 日志记录 支持类似printf函数的带格式输出 @return void 作者:jesse 日期:2008-2-3 */ void log_log( const TCHAR *strCatName, ///category名 const int iPriority, ///日志记录级别 const TCHAR* strFormat, ///日志内容格式 ... ///日志内容 ) { const log4c_category_t* a_category = log4c_category_get(strCatName); if (log4c_category_is_priority_enabled(a_category, iPriority)) { va_list va; va_start(va, strFormat); log4c_category_vlog(a_category, iPriority, strFormat, va); va_end(va); } } #if 0 /** 日志记录Wrapper函数 日志记录为一个字符串指针指向的内容 @return int:return 0 for success 作者:jesse 日期:2008-2-4 */ void log_msg_wrapper ( const int iPriority, ///日志记录级别 const char *strFormat, ///日志内容格式 ... ///日志内容 ) { const log4c_category_t* a_category = log4c_category_get(DEFAULT_LOG_CATEGORY_NAME); ///log_msg(__FILE__, __LINE__, DEFAULT_LOG_CATEGORY_NAME, iPriority, strFormat); if (log4c_category_is_priority_enabled(a_category, iPriority)) { char strMsg[10240] = {0}; va_list va; va_start(va, strFormat); { int iSprintSize = 0; iSprintSize = vsnprintf(strMsg, sizeof(strMsg), strFormat, va); if ( iSprintSize >= sizeof(strMsg)) { sd_error("truncating message of %d bytes (bufsize = %d)", iSprintSize, sizeof(strMsg)); } } va_end(va); log4c_category_vlog(a_category, iPriority, strMsg, va); } } #endif const LOG_PARAM log_vsprintf_wrapper( const int iPriority, ///日志记录级别 const TCHAR* strFormat, ///日志内容格式 ... ///日志内容 ) { LOG_PARAM log_param; va_list va; va_start(va, strFormat); { #if 1 _vsntprintf(log_param.strMsg, LOG4C_BUFFER_SIZE_DEFAULT, strFormat, va); #else memcpy(log_param.strMsg, sd_vsprintf( strFormat, va), sizeof(log_param.strMsg)); #endif } va_end(va); log_param.iPriority = iPriority; return log_param; } const LOG_PARAM log_condition_vsnprintf_wrapper( const int iCondition, ///条件 const int iPriority, ///日志记录级别 const TCHAR* strFormat, ///日志内容格式 ... ///日志内容 ) { LOG_PARAM log_param; va_list va; va_start(va, strFormat); { #if 1 _vsntprintf(log_param.strMsg, LOG4C_BUFFER_SIZE_DEFAULT, strFormat, va); #else memcpy(log_param.strMsg, sd_vsprintf( strFormat, va), sizeof(log_param.strMsg)); #endif } va_end(va); log_param.iCondition = iCondition; log_param.iPriority = iPriority; return log_param; } void log_hex_dump_vsnprintf_wrapper( const int iPriority, ///日志记录级别 const TCHAR* strHexBuf, ///缓冲区首地址 const int iHexBufLen, ///缓冲区长度 ... ///日志内容 ) { TCHAR *strBuffer = (TCHAR *)malloc(LOG4C_BUFFER_SIZE_MAX); memset(strBuffer, 0, LOG4C_BUFFER_SIZE_MAX); log4c_sprintf_data((TCHAR*)(strHexBuf), (iHexBufLen), strBuffer); log_msg_no_file_num( DEFAULT_LOG_CATEGORY_NAME, iPriority, strBuffer ); } const LOG_PARAM log_vsnprintf_wrapper_msg(const TCHAR* strFormat/*日志内容格式*/, .../*日志内容*/) { LOG_PARAM log_param; va_list va; va_start(va, strFormat); { #if 1 _vsntprintf(log_param.strMsg, LOG4C_BUFFER_SIZE_DEFAULT, strFormat, va); #else memcpy(log_param.strMsg, sd_vsprintf( strFormat, va), sizeof(log_param.strMsg)); #endif } va_end(va); return log_param; } void log_msg_wrapper( const TCHAR *strFileName,///文件名 const int iLineNum, ///行号 const TCHAR *strCatName, ///category名 const int iPriority, ///日志记录级别 const TCHAR *strFormat, ///日志内容格式 ... ///日志内容 ) { const log4c_category_t* a_category = log4c_category_get(strCatName); if (log4c_category_is_priority_enabled(a_category, iPriority)) { va_list va; va_start(va, strFormat); log4c_category_vlog(a_category, iPriority, strFormat, va); va_end(va); } } /**宏参数抽取format函数 本函数接受LOG_DEBUG(X)的参数,并从该宏定义的参数中返回format的值 @return const char* : strFormat 作者:jesse 日期:2008-2-4 */ const TCHAR* log_get_format_wrapper( const int iPriority, ///日志记录级别 const TCHAR* strFormat, ///日志内容格式 ... ///日志内容 ) { return strFormat; #if 0 char* buffer = strdup(strFormat); return buffer; #endif } /**宏参数抽取priority函数 本函数接受LOG_DEBUG(X)的参数,并从该宏定义的参数中返回priority的值 @return const int : iPriority. 作者:jesse 日期:2008-2-4 */ const int log_get_priority_wrapper( const int iPriority, ///日志记录级别 const TCHAR* strFormat, ///日志内容格式 ... ///日志内容 ) { return iPriority; } /** 将大小为count的缓冲区中内容按字节以16进制字符串打印出来, 返回值即为指向相应的字符串, 该返回指向的存储区域要调用本函数的用户显示的进行删除 */ void log4c_sprintf_data(TCHAR *buff, int count, TCHAR *dest_buffer) { int i,j,c; int printnext=1; TCHAR str[10] = {0};///由于这里要进行格式输出如"%.4x "等,这里给出10个字符作为格式输出冗余 if(count) { if(count%16) { c=count+(16-count%16); } else { c=count; } } else { c=count; } for(i=0;i= 0x20 && (buff[j]&0xff)<=0x7e) { _sntprintf(str, sizeof(str), _T("%c"), buff[j]&0xff); _tcscat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); } else { _sntprintf(str, sizeof(str), _T(".")); _tcscat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); } } else { _sntprintf(str, sizeof(str), _T(" ")); _tcscat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); ///ostr << str; } } _sntprintf(str, sizeof(str), _T("\n")); _tcscat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); printnext=1; } } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// static TCHAR gs_strFileContent_InC[] = _T("\r\n") _T("\r\n") _T("\r\n") _T("\r\n") _T(" \r\n") _T(" 0\r\n") _T(" \r\n") _T(" 0\r\n") _T(" 1\r\n") _T(" \r\n") _T("\r\n") _T(" \r\n") _T("\r\n") _T(" \r\n") _T(" \r\n") _T("\r\n") _T(" \r\n") _T(" \r\n") _T(" \r\n") _T("\r\n"); static TCHAR gs_strDefualtFileName[] = _T("log4crc.txt"); int log_init_with_string( const TCHAR *strFileContent, const TCHAR *strFileName ) { int iResult = FAILURE; const TCHAR * strLocalFileContent = NULL; const TCHAR * strLocalFileName = NULL; PAssertNotNull_ReturnWithValue(strFileContent, FAILURE); PAssertNotNull_ReturnWithValue(strFileName, FAILURE); strLocalFileContent = (_tcslen(strFileContent) > 0 ? strFileContent:gs_strFileContent_InC); strLocalFileName = (_tcslen(strFileName) > 0 ? strFileName:gs_strDefualtFileName); /** 若文件已存在则不重新生成配置文件了 否则生成新的配置文件 */ if (OK != SD_ACCESS_READ(strLocalFileName)) { ///文件不存在新建 FILE *file = _tfopen(strLocalFileName, _T("wb")); if (NULL != file) { fwrite(strLocalFileContent, 1, _tcslen(strLocalFileContent), file); fclose(file); } } else { ///文件存在,do nothing,使用原来的配置文件就OK了。 } ////////////////////////////////////////////////////////////////////////// ///调用Init函数进行实际的日志模块初始化工作 iResult = log_init_with_cfg_file_wrapper(strLocalFileName); return iResult; } int log_init_with_cfg_file_wrapper(const TCHAR * strConfigFile) { int iResult = FAILURE; PAssertNotNull_ReturnWithValue(strConfigFile, FAILURE); ///调用log4c的函数来初始化日志 if (_tcslen(strConfigFile) > 0) { iResult = log_init_with_cfg_file(strConfigFile); } if ( OK != iResult) { iResult = log_init(); } return iResult; } /*****************************新增的一些日志模块配置属性设置类****************/ #define MAX_FILE_NAME_LEN 512 struct ST_LogProperty { TCHAR m_strLogCfgFileName[MAX_FILE_NAME_LEN]; TCHAR m_strLogFileName[MAX_FILE_NAME_LEN]; int m_iLogFileSize; TCHAR m_strLogLevel[128]; int m_iLogFileNum; BOOL m_bReReadLogCfgFile; }; typedef struct ST_LogProperty LogProperty; static LogProperty gs_st_LogProperty = { _T("log4crc.txt"), _T("log"), 1048576, _T("notice"), 15, TRUE }; static TCHAR gs_strFileContentFormat[] = _T("\n") _T("\n") _T("\n") _T("\n") _T(" \n") _T(" 0\n") _T(" \n") _T(" 0\n") _T(" %d\n") _T(" \n") _T("\n") _T(" \n") _T("\n") _T(" \n") _T(" \n") _T("\n") _T(" \n") _T(" \n") _T(" \n") _T("\n"); static TCHAR gs_strFileContentBuffer[4096] = {0}; // 第一步;LOG4C设置日志配置文件名 void log_set_log_cfg_file_name(const TCHAR *strFileName) { PAssertNotNull_Return(strFileName); _tcsncpy(gs_st_LogProperty.m_strLogCfgFileName, strFileName, sizeof(gs_st_LogProperty.m_strLogCfgFileName)); } void log_set_log_file_name(const TCHAR *strFileName) { PAssertNotNull_Return(strFileName); _tcsncpy(gs_st_LogProperty.m_strLogFileName, strFileName, sizeof(gs_st_LogProperty.m_strLogFileName)); } // 设置日志级别; void log_set_log_level(const TCHAR *strLogLevel) { _tcsncpy(gs_st_LogProperty.m_strLogLevel, strLogLevel, sizeof(gs_st_LogProperty.m_strLogLevel)); } void log_set_log_file_size(const int iFileSize) { gs_st_LogProperty.m_iLogFileSize = iFileSize; } void log_set_log_file_num(const int iFileNum) { gs_st_LogProperty.m_iLogFileNum = iFileNum; } void log_set_reread_log_cfg_file(const BOOL bReReadLogCfgFile) { gs_st_LogProperty.m_bReReadLogCfgFile = bReReadLogCfgFile; } // 生效; int log_init_with_param() { _sntprintf( gs_strFileContentBuffer, sizeof(gs_strFileContentBuffer), gs_strFileContentFormat, gs_st_LogProperty.m_bReReadLogCfgFile, gs_st_LogProperty.m_strLogLevel, gs_st_LogProperty.m_iLogFileSize, gs_st_LogProperty.m_iLogFileNum, gs_st_LogProperty.m_strLogFileName ); return log_init_with_string(gs_strFileContentBuffer, gs_st_LogProperty.m_strLogCfgFileName); } /************************************************************************/ /************************************************************************/ // Instruct the compiler to put the g_lModuleUsage data // variable in its own data section, called Shared. We // then instruct the linker that we want the data in this // section to be shared by all instances of this application. #ifdef WIN32 #pragma data_seg("LogShared") /** 数据库日志模块运行的实例个数 避免多个日志模块的运行实例使用同一个配置文件,避免使用同一个log文件来记录日志而产生冲突 */ long g_lLogModuleUsage = -1; #pragma data_seg() // Instruct the linker to make the Shared section // readable, writable, and shared. #pragma comment(linker, "/section:LogShared,rws") #else // long g_lLogModuleUsage __attribute__((section ("shared"), shared)) = -1; // int g_lLogModuleUsage __attribute__((section ("shared"), shared)) = -1; // extern long GetModuleUsage(); // long g_lLogModuleUsage = GetModuleUsage(); long g_lLogModuleUsage = -1; #endif int log_init_with_param_multi_process() { TCHAR strLogCfgFileName[MAX_FILE_NAME_LEN] = {0}; TCHAR strLogFileName[MAX_FILE_NAME_LEN] = {0}; TCHAR strLogModuleUsageNum[MAX_FILE_NAME_LEN] = {0}; IncreaseLogModuleUsage(); //snprintf(gs_st_LogProperty.m_strLogCfgFileName, sizeof(gs_st_LogProperty.m_strLogCfgFileName), // "%s%d", gs_st_LogProperty.m_strLogCfgFileName, g_lLogModuleUsage); //snprintf(gs_st_LogProperty.m_strLogFileName, sizeof(gs_st_LogProperty.m_strLogFileName), // "%s%d", gs_st_LogProperty.m_strLogFileName, g_lLogModuleUsage); _sntprintf(strLogModuleUsageNum, sizeof(strLogModuleUsageNum), _T("%d"), g_lLogModuleUsage); _tcscat(gs_st_LogProperty.m_strLogCfgFileName, strLogModuleUsageNum); _tcscat(gs_st_LogProperty.m_strLogFileName, strLogModuleUsageNum); return log_init_with_param(); } extern long GetModuleUsage(); extern void SetModuleUsage(long lModuleUsage); void IncreaseLogModuleUsage() { #ifdef WIN32 InterlockedIncrement((long*) &g_lLogModuleUsage); #else g_lLogModuleUsage = GetModuleUsage(); g_lLogModuleUsage ++; SetModuleUsage(g_lLogModuleUsage); #endif } /************************************************************************/ /************************************************************************/ ///下面为LOG4C_BLOCK_XXX相关宏定义的实现代码 ///进行LOG4C_BLOCK_BEGIN和LOG4C_BLOCK_END宏定义使用的Block结构 struct ST_Block { #define BLOCK_FREE 0 #define BLOCK_BUSY 1 ///标志是否被使用 int iUseStatus; ///线程ID TASK_ID threadId; ///Block的层次 int iBlockLevel; void (*Init)(struct ST_Block *ptrThis); void (*Reset)(struct ST_Block *ptrThis); int (*GetUseStatus)(struct ST_Block *ptrThis); TASK_ID (*GetThreadId)(struct ST_Block *ptrThis); int (*GetBlockLevel)(struct ST_Block *ptrThis); void (*SetUseStatus)(struct ST_Block *ptrThis, int iUseStatus); void (*SetThreadId)(struct ST_Block *ptrThis, TASK_ID threadId); void (*SetBlockLevel)(struct ST_Block *ptrThis, int iBlockLevel); }; typedef struct ST_Block Block; /**一个ST_BlockGroup包含5个ST_Block ST_BlockGroup中作为ST_BlockManager中管理的节点 */ struct ST_BlockGroup { #define BLOCK_GROUP_BLOCK_NUM (5) Block aBlock[BLOCK_GROUP_BLOCK_NUM]; struct ST_BlockGroup *ptrBlockGroupPre; struct ST_BlockGroup *ptrBlockGroupNext; void (*Init)(struct ST_BlockGroup *ptrThis); Block *(*GetThreadBlock)(struct ST_BlockGroup *ptrThis, TASK_ID threadId); Block *(*GetFreeBlock)(struct ST_BlockGroup *ptrThis); }; typedef struct ST_BlockGroup BlockGroup; struct ST_BlockManager { BlockGroup *ptrBlockGroupHeader; BlockGroup *ptrBlockGroupTail; Block *(*GetThreadBlock)(struct ST_BlockManager *ptrThis, TASK_ID threadId); Block *(*GetFreeBlock)(struct ST_BlockManager *ptrThis); }; typedef struct ST_BlockManager BlockManager; extern Block *BlockManager_GetThreadBlock(BlockManager *ptrThis, TASK_ID threadId); extern Block *BlockManager_GetFreeBlock(BlockManager *ptrThis); BlockManager g_blockManager = { NULL, NULL, BlockManager_GetThreadBlock, BlockManager_GetFreeBlock }; extern void Block_Reset(Block *ptrThis); extern int Block_GetUseStatus(Block *ptrThis); extern TASK_ID Block_GetThreadId(Block *ptrThis); extern int Block_GetBlockLevel(Block *ptrThis); extern void Block_SetUseStatus(Block *ptrThis, int iUseStatus); extern void Block_SetThreadId(Block *ptrThis, TASK_ID threadId); extern void Block_SetBlockLevel(Block *ptrThis, int iBlockLevel); /**ST_Block的初始化代码 @param :Block *ptrThis @rerurn void. */ void Block_Init(Block *ptrThis) { PAssert_Return(ptrThis); memset(ptrThis, 0, sizeof(*ptrThis)); ///设置本结构的成员函数 ptrThis->Init = Block_Init; ptrThis->Reset = Block_Reset; ptrThis->SetBlockLevel = Block_SetBlockLevel; ptrThis->GetBlockLevel = Block_GetBlockLevel; ptrThis->SetThreadId = Block_SetThreadId; ptrThis->GetThreadId = Block_GetThreadId; ptrThis->SetUseStatus = Block_SetUseStatus; ptrThis->GetUseStatus = Block_GetUseStatus; return; } /**ST_Block的重置代码 @param :Block *ptrThis @rerurn void. */ void Block_Reset(Block *ptrThis) { PAssert_Return(ptrThis); Block_Init(ptrThis); return; } /**ST_Block的获取成员变量iUseStatus的函数 其实直接引用成员变量就可以了,这里为了练习C实现C++而特意实现的 @param :int @rerurn void. */ int Block_GetUseStatus(Block *ptrThis) { PAssert_ReturnWithValue(ptrThis, 0); return ptrThis->iUseStatus; } /**ST_Block的获取成员变量threadId的函数 其实直接引用成员变量就可以了,这里为了练习C实现C++而特意实现的 @param :TASK_ID. @rerurn void. */ TASK_ID Block_GetThreadId(Block *ptrThis) { PAssert_ReturnWithValue(ptrThis, 0); return ptrThis->threadId; } /**ST_Block的获取成员变量iBlockLevel的函数 其实直接引用成员变量就可以了,这里为了练习C实现C++而特意实现的 @param :int. @rerurn void. */ int Block_GetBlockLevel(Block *ptrThis) { PAssert_ReturnWithValue(ptrThis, 0); return ptrThis->iBlockLevel; } /**ST_Block的设置成员变量iUseStatus的函数 其实直接引用成员变量就可以了,这里为了练习C实现C++而特意实现的 @param :Block *ptrThis @param :int @rerurn void. */ void Block_SetUseStatus(Block *ptrThis, int iUseStatus) { PAssert_Return(ptrThis); ptrThis->iUseStatus = iUseStatus; } /**ST_Block的设置成员变量threadId的函数 其实直接引用成员变量就可以了,这里为了练习C实现C++而特意实现的 @param :Block *ptrThis @param :TASK_ID. @rerurn void. */ void Block_SetThreadId(Block *ptrThis, TASK_ID threadId) { PAssert_Return(ptrThis); ptrThis->threadId = threadId; } /**ST_Block的设置成员变量iBlockLevel的函数 其实直接引用成员变量就可以了,这里为了练习C实现C++而特意实现的 @param :Block *ptrThis @param :int. @rerurn void. */ void Block_SetBlockLevel(Block *ptrThis, int iBlockLevel) { PAssert_Return(ptrThis); ptrThis->iBlockLevel = iBlockLevel; } extern Block *BlockGroup_GetThreadBlock(BlockGroup *ptrThis, TASK_ID threadId); extern Block *BlockGroup_GetFreeBlock(BlockGroup *ptrThis); /**ST_BlockGroup的初始化代码 @param :Block *ptrThis @rerurn void. */ void BlockGroup_Init(BlockGroup *ptrThis) { int i = 0; PAssert_Return(ptrThis); memset(ptrThis, 0, sizeof(*ptrThis)); ptrThis->Init = BlockGroup_Init; ptrThis->GetThreadBlock = BlockGroup_GetThreadBlock; ptrThis->GetFreeBlock = BlockGroup_GetFreeBlock; ///初始化每个Block for (i = 0; i < BLOCK_GROUP_BLOCK_NUM; i++) { Block *ptrBlock = &ptrThis->aBlock[i]; ptrBlock->Init = Block_Init; ptrBlock->Init(ptrBlock); } return; } /**从ST_BlockGroup中获取给定线程的Block的指针 @param :Block *ptrThis @param :TASK_ID threadId @rerurn Block *. */ Block *BlockGroup_GetThreadBlock(BlockGroup *ptrThis, TASK_ID threadId) { Block *ptrBlockReturn = NULL; int i = 0; PAssert_ReturnWithValue(ptrThis, NULL); for (i = 0; i < BLOCK_GROUP_BLOCK_NUM; i++) { Block *ptrBlock = &ptrThis->aBlock[i]; if (ptrBlock->GetThreadId(ptrBlock) == threadId) { ptrBlockReturn = ptrBlock; break; } } return ptrBlockReturn; } /**从ST_BlockGroup中获取空闲的Block的指针 @param :BlockGroup *ptrThis @rerurn Block *. */ Block *BlockGroup_GetFreeBlock(BlockGroup *ptrThis) { Block *ptrBlockReturn = NULL; int i = 0; PAssert_ReturnWithValue(ptrThis, NULL); for (i = 0; i < BLOCK_GROUP_BLOCK_NUM; i++) { Block *ptrBlock = &ptrThis->aBlock[i]; if (ptrBlock->GetUseStatus(ptrBlock) == BLOCK_FREE) { ptrBlockReturn = ptrBlock; break; } } return ptrBlockReturn; } Block *BlockManager_GetThreadBlock(BlockManager *ptrThis, TASK_ID threadId) { Block *ptrBlockReturn = NULL; BlockGroup *ptrBlockGroup = NULL; PAssert_ReturnWithValue(ptrThis, NULL); if (NULL == ptrThis->ptrBlockGroupHeader) { BlockGroup *ptrGroupBlock = (BlockGroup *)malloc(sizeof(BlockGroup)); ptrGroupBlock->Init = BlockGroup_Init; ptrGroupBlock->Init(ptrGroupBlock); ptrThis->ptrBlockGroupHeader = ptrGroupBlock; ptrThis->ptrBlockGroupTail = ptrGroupBlock; } PAssert_ReturnWithValue(ptrThis->ptrBlockGroupHeader, NULL); ptrBlockGroup = ptrThis->ptrBlockGroupHeader; do { ptrBlockReturn = ptrBlockGroup->GetThreadBlock(ptrBlockGroup, threadId); if (NULL != ptrBlockReturn) { break; } else { ptrBlockGroup = ptrBlockGroup->ptrBlockGroupNext; } } while (NULL != ptrBlockGroup); ///此时找遍所有的链表都没有找到相应的Block,则重新找块没用的Block if (NULL == ptrBlockReturn) { ptrBlockReturn = ptrThis->GetFreeBlock(ptrThis); } return ptrBlockReturn; } Block *BlockManager_GetFreeBlock(BlockManager *ptrThis) { Block *ptrBlockReturn = NULL; PAssert_ReturnWithValue(ptrThis, NULL); if(NULL == ptrThis->ptrBlockGroupHeader) { ///原来没有空间则动态分配 BlockGroup *ptrGroupBlock = (BlockGroup *)malloc(sizeof(BlockGroup)); ptrGroupBlock->Init = BlockGroup_Init; ptrGroupBlock->Init(ptrGroupBlock); ptrThis->ptrBlockGroupHeader = ptrGroupBlock; ptrThis->ptrBlockGroupTail = ptrGroupBlock; ptrBlockReturn = ptrGroupBlock->GetFreeBlock(ptrGroupBlock); } else { BlockGroup *ptrBlockGroup = ptrThis->ptrBlockGroupHeader; do { ptrBlockReturn = ptrBlockGroup->GetFreeBlock(ptrBlockGroup); if (NULL != ptrBlockReturn) { break; } else { ptrBlockGroup = ptrBlockGroup->ptrBlockGroupNext; } } while (NULL != ptrBlockGroup); ///此时找遍所有的链表都没有找到空闲空间,则进行动态分配 if(NULL == ptrBlockReturn) { BlockGroup *ptrBlockGroup = (BlockGroup *)malloc(sizeof(BlockGroup)); ptrBlockGroup->Init = BlockGroup_Init; ptrBlockGroup->Init(ptrBlockGroup); ptrThis->ptrBlockGroupTail->ptrBlockGroupNext = ptrBlockGroup; ptrBlockGroup->ptrBlockGroupPre = ptrThis->ptrBlockGroupTail; ptrThis->ptrBlockGroupTail = ptrBlockGroup; ptrBlockReturn = ptrBlockGroup->GetFreeBlock(ptrBlockGroup); } } return ptrBlockReturn; } void log4c_block_begin(const TCHAR * fileName, int lineNum, const TCHAR * traceName) { TASK_ID threadId = VOS_GetSelfTaskID(); int i = 0; Block *ptrBlock = NULL; PAssert_Return(fileName); PAssert_Return(traceName); ptrBlock = g_blockManager.GetThreadBlock(&g_blockManager, threadId); if (NULL != ptrBlock) { int iBlockLevel = 0; TCHAR strMsgBuffer[LOG4C_BUFFER_SIZE_MAX] = {0}; if (ptrBlock->GetUseStatus(ptrBlock) == BLOCK_FREE) { ptrBlock->SetUseStatus(ptrBlock, BLOCK_BUSY); ptrBlock->SetThreadId(ptrBlock, threadId); ptrBlock->SetBlockLevel(ptrBlock, 0); } if (ptrBlock->GetThreadId(ptrBlock) != threadId) { ptrBlock->SetThreadId(ptrBlock, threadId); ptrBlock->SetBlockLevel(ptrBlock, 0); } ///ptrBlock->SetThreadId(ptrBlock, threadId); ///ptrBlock->SetBlockLevel(ptrBlock, 0); iBlockLevel = ++(ptrBlock->iBlockLevel) ; _tcsncat(strMsgBuffer, _T("B-Entry\t"), sizeof(strMsgBuffer)); for (i = 0; i < iBlockLevel; i++) { _tcsncat(strMsgBuffer, _T("=="), sizeof(strMsgBuffer)); } _tcsncat(strMsgBuffer, _T("> "), sizeof(strMsgBuffer)); _tcsncat(strMsgBuffer, traceName, sizeof(strMsgBuffer)); ///调用log4c的函数来记录日志 log_msg(fileName, lineNum, _T(""), LOG4C_PRIORITY_TRACE, strMsgBuffer); } } void log4c_block_end(const TCHAR * fileName, int lineNum, const TCHAR * traceName) { TASK_ID threadId = VOS_GetSelfTaskID(); int i = 0; Block *ptrBlock = NULL; PAssert_Return(fileName); PAssert_Return(traceName); ptrBlock = g_blockManager.GetThreadBlock(&g_blockManager, threadId); if (NULL != ptrBlock) { int iBlockLevel = ptrBlock->GetBlockLevel(ptrBlock); TCHAR strMsgBuffer[LOG4C_BUFFER_SIZE_MAX] = {0}; _tcsncat(strMsgBuffer, _T("B-Exit\t"), sizeof(strMsgBuffer)); _tcsncat(strMsgBuffer, _T("<"), sizeof(strMsgBuffer)); for (i = 0; i < iBlockLevel; i++) { _tcsncat(strMsgBuffer, _T("=="), sizeof(strMsgBuffer)); } _tcsncat(strMsgBuffer, _T(" "), sizeof(strMsgBuffer)); _tcsncat(strMsgBuffer, traceName, sizeof(strMsgBuffer)); ///调用log4c的函数来记录日志 log_msg(fileName, lineNum, _T(""), LOG4C_PRIORITY_TRACE, strMsgBuffer); iBlockLevel = --ptrBlock->iBlockLevel ; if (ptrBlock->iBlockLevel == 0) { ptrBlock->SetThreadId(ptrBlock, 0); ptrBlock->SetBlockLevel(ptrBlock, 0); ptrBlock->SetUseStatus(ptrBlock, BLOCK_FREE); } } } /************************************************************************/ /************** End of log.c *******************************************/