/************** 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 #include #include #include #include #include #include #include #include #include #include #include "log4c/vos.h" #include "log4c/log.h" #include "GlobalMacro.h" ////////////////////////////////////////////////////////////////////////// ///下面括起来代码和log_check拷贝自init.c typedef struct log_c_rcfile { char name[256]; time_t ctime; int exists; } log_c_rcfile_t; static log_c_rcfile_t log_c_rcfiles[] = { #if 1 { "$LOG4C_RCPATH/log4crc" }, { "$HOME/.log4crc" }, #endif { "./log4crc" } }; 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; ////////////////////////////////////////////////////////////////////////// /** 日志模块初始化 @return int:return 0 for success 作者:jesse 日期:2008-2-3 */ 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()); } /** 日志模块初始化,指定配置文件名称 @return int:return 0 for success 作者:jesse 日期:2008-9-5 */ int log_init_with_cfg_file(const char *strCfgFileName) { log_check_with_cfg_file(strCfgFileName); return(log4c_init_with_cfg_file(strCfgFileName)); } extern void ReleaseModuleUsage(); /** 日志模块清理 @return int:return 0 for success 作者:jesse 日期:2008-2-3 */ int log_fini() { int iResult = log4c_fini(); // 解决资源泄漏 [4/18/2009 jesse] VOS_DELETE_SEM(gs_semphore); ReleaseModuleUsage(); return iResult; } /**检测配置文件是否存在 @return const int : iPriority. 作者:jesse 日期:2008-2-18 */ const int log_check(void) { int iReturn = 0; BOOL bCfgFileExist = FALSE; int i = 0; printf("check configuration files...\n"); /* check configuration files */ printf("looking for conf files...\n"); #if 1 snprintf(log_c_rcfiles[0].name, sizeof(log_c_rcfiles[0].name) - 1, "%s/log4crc", getenv("LOG4C_RCPATH") ? getenv("LOG4C_RCPATH") : LOG4C_RCPATH); snprintf(log_c_rcfiles[1].name, sizeof(log_c_rcfiles[1].name) - 1, "%s/.log4crc", getenv("HOME") ? getenv("HOME") : ""); #endif for (i = 0; i < log_c_nrcfiles; i++) { printf("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("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) { printf("find configuration file\n"); } else { printf("can't find configuration file,\nplease put you conf file in the same dir of execute file.\n"); } return iReturn; } /**检测配置文件是否存在,只检测传入的配置文件名 @return const int : iPriority. 作者:jesse 日期:2008-9-4 */ const int log_check_with_cfg_file(const char *strCfgFileName) { int iReturn = 0; BOOL bCfgFileExist = FALSE; int i = 0; printf("check configuration files...\n"); /* check configuration files */ printf("looking for conf files...\n"); #if 1 snprintf(log_c_rcfiles[0].name, sizeof(log_c_rcfiles[0].name) - 1, "%s/log4crc", getenv("LOG4C_RCPATH") ? getenv("LOG4C_RCPATH") : LOG4C_RCPATH); snprintf(log_c_rcfiles[1].name, sizeof(log_c_rcfiles[1].name) - 1, "%s/.log4crc", getenv("HOME") ? getenv("HOME") : ""); #endif if(NULL == strCfgFileName) { iReturn = -1; } else { printf("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("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) { printf("find configuration file\n"); } else { printf("can't find configuration file,\nplease put you conf file in the same dir of execute file.\n"); } return iReturn; } /** 日志记录 日志记录为一个字符串指针指向的内容 @return void 作者:jesse 日期:2008-2-3 */ void log_msg( const char *strFile, ///文件名 const int iLineNum, ///行号 const char *strCatName, ///category名 const int iPriority, ///日志记录级别 const char *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 char * strFilePath = strFile; const char * strFileName = strrchr(strFilePath, '/'); char 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 = strrchr(strFilePath, '\\'); if (strFileName != NULL) { strFileName++; } else { strFileName = strFilePath; } } snprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, "%-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); } } /** 日志记录 日志记录为一个字符串指针指向的内容 @return void 作者:jesse 日期:2008-2-3 */ void log_msg_func( const char *strFile, ///文件名 const char *strFuncName,///函数名 const int iLineNum, ///行号 const char *strCatName, ///category名 const int iPriority, ///日志记录级别 const char *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 char * strFilePath = strFile; const char * strFileName = strrchr(strFilePath, '/'); char 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 = strrchr(strFilePath, '\\'); if (strFileName != NULL) { strFileName++; } else { strFileName = strFilePath; } } snprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, "%-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 char *strCatName, ///category名 const int iPriority, ///日志记录级别 const char *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; char 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); snprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, "%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 char *strCatName, ///category名 const int iPriority, ///日志记录级别 const char *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; char 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); snprintf(strMsgBuffer, sizeof(strMsgBuffer)-1, "%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 char *strCatName, ///category名 const char *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 char *strCatName, ///category名 const int iPriority, ///日志记录级别 const char* 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 char* strFormat, ///日志内容格式 ... ///日志内容 ) { LOG_PARAM log_param; va_list va; va_start(va, strFormat); { #if 1 vsnprintf(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 char* strFormat, ///日志内容格式 ... ///日志内容 ) { LOG_PARAM log_param; va_list va; va_start(va, strFormat); { #if 1 vsnprintf(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 char* strHexBuf, ///缓冲区首地址 const int iHexBufLen, ///缓冲区长度 ... ///日志内容 ) { char *strBuffer = (char *)malloc(LOG4C_BUFFER_SIZE_MAX); memset(strBuffer, 0, LOG4C_BUFFER_SIZE_MAX); log4c_sprintf_data((char*)(strHexBuf), (iHexBufLen), strBuffer); log_msg_no_file_num( DEFAULT_LOG_CATEGORY_NAME, iPriority, strBuffer ); } const LOG_PARAM log_vsnprintf_wrapper_msg( const char* strFormat, ///日志内容格式 ... ///日志内容 ) { LOG_PARAM log_param; va_list va; va_start(va, strFormat); { #if 1 vsnprintf(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 char *strFileName,///文件名 const int iLineNum, ///行号 const char *strCatName, ///category名 const int iPriority, ///日志记录级别 const char *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 char* log_get_format_wrapper( const int iPriority, ///日志记录级别 const char* 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 char* strFormat, ///日志内容格式 ... ///日志内容 ) { return iPriority; } /** 将大小为count的缓冲区中内容按字节以16进制字符串打印出来, 返回值即为指向相应的字符串, 该返回指向的存储区域要调用本函数的用户显示的进行删除 */ void log4c_sprintf_data(char *buff, int count, char *dest_buffer) { int i,j,c; int printnext=1; char 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) { snprintf(str, sizeof(str), "%c",buff[j]&0xff); strncat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); } else { snprintf(str, sizeof(str), "."); strncat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); } } else { snprintf(str, sizeof(str), " "); strncat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); ///ostr << str; } } snprintf(str, sizeof(str), "\n"); strncat(dest_buffer, str, LOG4C_BUFFER_SIZE_MAX); printnext=1; } } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// static char gs_strFileContent_InC[] = "\n" "\n" "\n" "\n" " \n" " 0\n" " \n" " 0\n" " 1\n" " \n" "\n" " \n" "\n" " \n" " \n" "\n" " \n" " \n" " \n" "\n"; static char gs_strDefualtFileName[] = "log4crc"; int log_init_with_string( const char *strFileContent, const char *strFileName ) { int iResult = FAILURE; const char * strLocalFileContent = NULL; const char * strLocalFileName = NULL; PAssertNotNull_ReturnWithValue(strFileContent, FAILURE); PAssertNotNull_ReturnWithValue(strFileName, FAILURE); strLocalFileContent = (strlen(strFileContent) > 0 ? strFileContent:gs_strFileContent_InC); strLocalFileName = (strlen(strFileName) > 0 ? strFileName:gs_strDefualtFileName); /** 若文件已存在则不重新生成配置文件了 否则生成新的配置文件 */ if (OK != SD_ACCESS_READ(strLocalFileName)) { ///文件不存在新建 FILE *file = fopen(strLocalFileName, "wb"); if (NULL != file) { fwrite(strLocalFileContent, 1, strlen(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 char * strConfigFile) { int iResult = FAILURE; PAssertNotNull_ReturnWithValue(strConfigFile, FAILURE); ///调用log4c的函数来初始化日志 if (strlen(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 { char m_strLogCfgFileName[MAX_FILE_NAME_LEN]; char m_strLogFileName[MAX_FILE_NAME_LEN]; int m_iLogFileSize; char m_strLogLevel[128]; int m_iLogFileNum; BOOL m_bReReadLogCfgFile; }; typedef struct ST_LogProperty LogProperty; static LogProperty gs_st_LogProperty = { "log4crc", "log", 1048576, "notice", 15, TRUE }; static char gs_strFileContentFormat[] = "\n" "\n" "\n" "\n" " \n" " 0\n" " \n" " 0\n" " %d\n" " \n" "\n" " \n" "\n" " \n" " \n" "\n" " \n" " \n" " \n" "\n"; static char gs_strFileContentBuffer[4096] = {0}; void log_set_log_cfg_file_name(const char *strFileName) { PAssertNotNull_Return(strFileName); strncpy(gs_st_LogProperty.m_strLogCfgFileName, strFileName, sizeof(gs_st_LogProperty.m_strLogCfgFileName)); } void log_set_log_file_name(const char *strFileName) { PAssertNotNull_Return(strFileName); strncpy(gs_st_LogProperty.m_strLogFileName, strFileName, sizeof(gs_st_LogProperty.m_strLogFileName)); } void log_set_log_level(const char *strLogLevel) { strncpy(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() { snprintf(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() { char strLogCfgFileName[MAX_FILE_NAME_LEN] = {0}; char strLogFileName[MAX_FILE_NAME_LEN] = {0}; char 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); snprintf(strLogModuleUsageNum, sizeof(strLogModuleUsageNum), "%d", g_lLogModuleUsage); strcat(gs_st_LogProperty.m_strLogCfgFileName, strLogModuleUsageNum); strcat(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 char * fileName, int lineNum, const char * 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; char 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) ; strncat(strMsgBuffer, "B-Entry\t", sizeof(strMsgBuffer)); for (i = 0; i < iBlockLevel; i++) { strncat(strMsgBuffer, "==", sizeof(strMsgBuffer)); } strncat(strMsgBuffer, "> ", sizeof(strMsgBuffer)); strncat(strMsgBuffer, traceName, sizeof(strMsgBuffer)); ///调用log4c的函数来记录日志 log_msg(fileName, lineNum, "", LOG4C_PRIORITY_TRACE, strMsgBuffer); } } void log4c_block_end(const char * fileName, int lineNum, const char * 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); char strMsgBuffer[LOG4C_BUFFER_SIZE_MAX] = {0}; strncat(strMsgBuffer, "B-Exit\t", sizeof(strMsgBuffer)); strncat(strMsgBuffer, "<", sizeof(strMsgBuffer)); for (i = 0; i < iBlockLevel; i++) { strncat(strMsgBuffer, "==", sizeof(strMsgBuffer)); } strncat(strMsgBuffer, " ", sizeof(strMsgBuffer)); strncat(strMsgBuffer, traceName, sizeof(strMsgBuffer)); ///调用log4c的函数来记录日志 log_msg(fileName, lineNum, "", 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 *******************************************/