Log4c学习笔记
来源:互联网 发布:mac safari无法退出 编辑:程序博客网 时间:2024/04/27 13:42
1.Log工具简单比较
Log4cpp & Log4CPlus:C++的日志库,可移植移性相对差些
Log4c:C的日志库,基本上都是一些纯c的东西,移植性较好
2.Log4c的基本概念
Log4c中有三个重要的概念, Category, Appender, Layout。
Category用于区分不同的日志,在一个程序中我们可以通过Category来指定很多的日志。
Appdender用于描述输出流,通过为Category来指定一个Appdender,可以决定将log信息来输出到什么地方去,比如stdout, stderr, rollingfile等等。
Layout用于指定日志信息的格式,通过为Appender来指定一个Layout,可以决定log信息以何种格式来输出,比如是否有带有时间戳, 是否包含文件位置信息等,以及他们在一条log信息中的输出格式的等。
Category, Appender, Layout三者之间的关系,一个Category需要为其指定一个appender, 一个appender亦要为其指定一个layout。
另外,对于文件类型输出还有一个rollingpolicy。rollingpolicy用于描述文件输出的配置策略。
3.关于配置
配置文件示例如下:
<!DOCTYPE log4c SYSTEM "">
<log4c version="1.2.0">
<config>
<bufsize>0</bufsize>
<debug level="0"/>
<nocleanup>0</nocleanup>
</config>
<layout name="dated" type="dated_l"/>
<!-- appenders ===================================== -->
<appender name="LoadBusinessLog" type="rollingfile" logdir="../etc/log"
prefix="LoadBusiness-" layout="dated_l" rollingpolicy="Policy1" />
<appender name="CataRollingFileAppender" type="rollingfile" logdir="../etc/log/"
prefix="testLog" layout="dated" rollingpolicy="RollingPolicy" />
<!-- category ========================================= -->
<category name="root" priority="notice"/>
<category name="framework" priority="info" appender="FrameLog" />
<category name="test.log" priority="trace" appender="CataRollingFileAppender" />
<!-- policy ======================================= -->
<rollingpolicy name="Policy1" type="timewin" timetype="1" maxnum="10" />
<rollingpolicy name="RollingPolicy" type="sizewin" maxsize="102400" maxnum="10" />
</log4c>
3.1 category
name:日志的名称
priority:日志的优先级,共有fatal、alert、crit、error、warn、notice、info、debug、trace、notset和unknown11个级别,其级别逐步递增,记录在日志中的数据为小于等于指定级别的数据。
appender:输出流类型名称,为appender节点的name属性的值。
3.2 appender
name:输出流名称
type:输出流类型,共有stream、syslog、rollingfile三大类
layout:输出日志的格式的名称,为layout节点的name属性的值。
rollingpolicy:输出日志文件配置策略名称,为rollingpolicy节点的name属性的值。
rollingpolicy的timewin类型的日志输出为自定义类型
3.3 layout
name:输出日志的格式名称
type:输出日志格式的类型,共有base 、dated、dated_l等格式类型,对于自定义类型也有配置在这里,否则不能够加载。
base:%P %c - %m/n
"%P" 日志信息的优先级
"%c" 日志的名称
"%m" 日志信息内容
dated:%d %P %c - %m/n
"%d" 日志信息产生的时间,UTC格式yyyymmdd hh:mm:ss.mis
"%P" 日志信息的优先级
"%c" 日志的名称
"%m" 日志信息内容
dated_l:%d %P %c - %m/n (源代码里面没有,自己增加的)
"%d" 日志信息产生的时间,本地时间格式yyyymmdd hh:mm:ss
"%P" 日志信息的优先级
"%c" 日志的名称
"%m"日志信息内容
3.4 rollingpolicy
name:日志文件输出的配置策略名称。
type:日志文件输出的配置策略的类型,有sizewin一种类型。
maxsize:输出日志文件的最大值。默认值为20KB
maxnum:保存的历史日志文件总数。默认值为5
3.5 配置文件的路径:
${ LOG4C_RCPATH }/log4crc //环境变量中设置的配置文件夹下log4crc
${HOME}/.log4crc //HOME文件夹下log4crc
./log4crc //当前可执行文件夹下log4crc
4、Log4c的基本使用
头文件(直接引用log4c.h程序编译出错,因此只引用需要的头文件)
extern "C" {
#include <log4c/init.h>
#include <log4c/category.h>
}
cpp文件
//初始化
log4c_init();
//获取一个已有的category
log4c_category_t* mycat = log4c_category_get("cata.log ");
//用该category进行日志输出,优先级为DEBUG,输出信息为 "Hello World!"
log4c_category_log(mycat, LOG4C_PRIORITY_DEBUG, "Hello World!");
//析构
log4c_fini();
//在日志输出过程中可以进行格式化输出:
log4c_category_log(mycat, LOG4C_PRIORITY_ERROR, "Error code = %d", 12345);
//对于格式化输出也可以有如下写法:
void CLog::Trace(const char * format, ... )
{
if (log4c_category_is_priority_enabled(mycat, LOG4C_PRIORITY_TRACE))
{
a_list argptr;
va_start(argptr, format);
log4c_category_vlog(mycat, LOG4C_PRIORITY_TRACE, format, argptr);
va_end(argptr);
}
}
5.自定义Logout
5.1 添加在Log4c源代码中的流程
在log4c-1.2.0/src/文件夹添加相应的头文件和实现文件,如examplelayout.h和examplelayout.c文件
编辑log4c-1.2.0/src/log4c/Makefile.in
在am__liblog4c_la_SOURCES_DIST中添加examplelayout.c
在am_liblog4c_la_OBJECTS中添加examplelayout. lo
在liblog4c_la_SOURCES 中添加examplelayout.c
在pkginclude_HEADERS中添加 examplelayout.h
添加@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ examplelayout.Plo@am__quote@
编辑log4c-1.2.0/src/log4c/Makefile.am
在liblog4c_la_SOURCES中添加examplelayout.c
在pkginclude_HEADERS中添加examplelayout.h
编辑log4c-1.2.0/src/init.c
添加#include <examplelayout.h>
在static const log4c_layout_type_t * const layout_types[]数组中添加新添加的layout_type函数指针
5.2在工程中添加自定义日志格式
实现自定义格式的主要函数:
static const char* cat_format(
const log4c_layout_t* a_layout,
const log4c_logging_event_t*a_event)
{
static char buffer[4096];
/*
* For this formatter we put the category up front in the log message
*/
sprintf(buffer, "[%s][LINE:%d][FILE:%s] %s", a_event->evt_category,
a_event->evt_loc->loc_line, a_event->evt_loc->loc_file, a_event->evt_msg);
return buffer;
}
const log4c_layout_type_t log4c_layout_type_cat = {
"test_cat", //格式名称,用于配置文件的设置
cat_format, //格式定义函数
5.3将自定义格式添加到Log4c的配置中:
int init_example_formatters()
{
log4c_layout_type_set(&log4c_layout_type_cat);//自定义格式类型函数指针
}
5.4自定义格式的使用
//执行自定义格式初始化
init_example_formatters();
//执行Log4c的初始化
log4c_init();
……
#ff00806.自定义Appender
6.1实现自定义输出流的主要函数:
static int test_file_append(log4c_appender_t* a_appender,
const log4c_logging_event_t* a_event)
{
FILE* fp = log4c_appender_get_udata(a_appender);
/*
return fprintf(fp, "[%s] [%s] [%d] [%d] [%s] [%s] [%d]/n%s",
log4c_appender_get_name(this),
a_event->evt_category,
a_event->evt_priority,
a_event->evt_timestamp.tv_sec*1000000 + a_event->evt_timestamp.tv_usec,
a_event->evt_msg,
a_event->evt_loc->loc_file,
a_event->evt_loc->loc_line,
a_event->evt_rendered_msg);
*/
return fprintf(fp, "%s/n", a_event->evt_rendered_msg);
}
static int test_open(log4c_appender_t* a_appender)
{
FILE* fp = log4c_appender_get_udata(a_appender);
if (fp)
return 0;
if ( (fp = fopen(log4c_appender_get_name(a_appender), "a+")) == NULL)
fp = stderr;
/* unbuffered mode */
setbuf(fp, NULL);
log4c_appender_set_udata(a_appender, fp);
return 0;
}
static int test_close(log4c_appender_t* a_appender)
{
FILE* fp = log4c_appender_get_udata(a_appender);
return (fp ? fclose(fp) : 0);
}
const log4c_appender_type_t log4c_appender_type_test_file = {
"test_file", //输出流的名称,用于配置文件设置
test_open, //打开输出流的函数
test_file_append, //给输出流追加日志信息的函数
test_close, //关闭输出流的函数
};
6.2将自定义输出流添加到Log4c的配置中:
int init_example_appenders()
{
log4c_appender_type_set (&log4c_appender_type_test_file);//自定义输出流类型的函数指针
}
6.3自定义输出流的使用
//执行自定义格式初始化
init_example_appenders();
//执行Log4c的初始化
log4c_init();
……
7.自定义rollingpolicy
源代码中有一个sizewin的rollingpolicy,是根据文件大小进行生成日志控制的。
在这里添加一个根据时间的控制日志输出的策略,实现代码如下:
7.1 rollingpolicy_type_timewin.h
#ifndef log4c_policy_type_timewin_h
#define log4c_policy_type_timewin_h
#include <log4c/defs.h>
#include <log4c/rollingpolicy.h>
__LOG4C_BEGIN_DECLS
LOG4C_API const log4c_rollingpolicy_type_t log4c_rollingpolicy_type_timewin;
typedef struct __timewin_udata rollingpolicy_timewin_udata_t;
#define TIME_TYPE_HOUR 0
#define TIME_TYPE_DAY 1
#define TIME_TYPE_MONTH 2
#define TIME_TYPE_YEAR 3
#define ROLLINGPOLICY_TIME_DEFAULT_MAX_NUM_FILES 100
#define ROLLINGPOLICY_TIME_DEFAULT_FILE_TYPE TIME_TYPE_DAY
LOG4C_API rollingpolicy_timewin_udata_t *timewin_make_udata(void);
LOG4C_API int timewin_udata_set_file_time_type(
rollingpolicy_timewin_udata_t * swup,
long time_type);
LOG4C_API int timewin_udata_set_max_num_files(
rollingpolicy_timewin_udata_t * swup,
long max_num);
LOG4C_API int timewin_udata_set_appender(
rollingpolicy_timewin_udata_t * swup,
log4c_appender_t* app);
__LOG4C_END_DECLS
#endif
7.2 rollingpolicy_type_timewin.c
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
#include <log4c/appender.h>
#include <log4c/rollingpolicy.h>
#include <log4c/rollingpolicy_type_timewin.h>
#include "appender_type_rollingfile.h"
#include <sd/malloc.h>
#include <sd/error.h>
#include <sd/sd_xplatform.h>
#include <sd/sprintf.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Internal structs that defines the conf and the state info
* for an instance of the appender_type_rollingfile type.
*/
struct __timewin_conf {
long swc_file_time_type;
long swc_file_max_num_files;
};
struct __timewin_udata {
struct __timewin_conf sw_conf;
rollingfile_udata_t *sw_rfudata;
const char *sw_logdir;
const char *sw_files_prefix;
char *sw_curfileflag;
char *sw_prefileflag;
int sw_flags;
};
/***************************************************************************/
static int timewin_init(log4c_rollingpolicy_t *this, rollingfile_udata_t* rfup);
static int timewin_rollover(log4c_rollingpolicy_t *this, FILE **current_fpp );
static int timewin_is_triggering_event(
log4c_rollingpolicy_t *this,
const log4c_logging_event_t* a_event,
long current_file_size);
static int timewin_fini(log4c_rollingpolicy_t *this);
static char* timewin_get_filename(rollingpolicy_timewin_udata_t * swup);
static int timewin_check_update_fileflag(rollingpolicy_timewin_udata_t * swup);
static int timewin_open_file(char *filename, FILE **fpp );
static int timewin_copy_string(char** szDest, const char* src);
/*******************************************************************************
Policy interface: init, is_triggering_event, rollover
*******************************************************************************/
static int timewin_is_triggering_event(
log4c_rollingpolicy_t *this,
const log4c_logging_event_t* a_event,
long current_file_size){
int decision = 0;
rollingpolicy_timewin_udata_t *swup = log4c_rollingpolicy_get_udata(this);
sd_debug("timewin_is_triggering_event[");
decision = timewin_check_update_fileflag(swup);
if (decision)
{
sd_debug("triggering event");
}
else
{
sd_debug("not triggering event");
}
sd_debug("]");
return(decision);
}
/*******************************************************************************/
static int timewin_rollover(log4c_rollingpolicy_t *this, FILE ** current_fpp ){
int rc = 0;
rollingpolicy_timewin_udata_t *swup = log4c_rollingpolicy_get_udata(this);
int k = 0;
char * szFileName = NULL;
sd_debug("timewin_rollover[");
if ( !swup || !swup->sw_logdir){
sd_error("rollingpolicy '%s' not yet configured (logdir,prefix etc.)",
log4c_rollingpolicy_get_name(this));
}
else
{
k = swup->sw_flags;
if (k > 0 || *current_fpp == NULL)
{
szFileName = timewin_get_filename(swup);
if (*current_fpp)
{
if(fclose(*current_fpp)){
sd_error("failed to close current log file");
rc = 1;
}
}
if (!rc && timewin_open_file(szFileName, current_fpp)){
sd_error("open zero file failed");
}
free(szFileName);
}
}
sd_debug("]");
return(rc);
}
/*******************************************************************************/
static int timewin_init(log4c_rollingpolicy_t *this, rollingfile_udata_t *rfup){
rollingpolicy_timewin_udata_t *swup = NULL;
sd_debug("timewin_init[");
if (!this){
goto timewin_init_exit;
}
swup = log4c_rollingpolicy_get_udata(this);
if ( swup == NULL ){
swup = timewin_make_udata();
log4c_rollingpolicy_set_udata(this, swup);
}
swup->sw_logdir = rollingfile_udata_get_logdir(rfup);
swup->sw_files_prefix = rollingfile_udata_get_files_prefix(rfup);
timewin_check_update_fileflag(swup);
timewin_init_exit:
sd_debug("]");
return(0);
}
/*******************************************************************************/
static int timewin_fini(log4c_rollingpolicy_t *this){
rollingpolicy_timewin_udata_t *swup = NULL;
int rc = 0;
sd_debug("timewin_fini[ ");
if (!this){
goto timewin_fini_exit;
}
swup = log4c_rollingpolicy_get_udata(this);
if (!swup){
goto timewin_fini_exit;
}
if (swup->sw_curfileflag)
{
free(swup->sw_curfileflag);
}
if (swup->sw_prefileflag)
{
free(swup->sw_prefileflag);
}
swup->sw_flags = 0;
/* logdir and files_prefix are just pointers into the rollingfile udata
* so they are not ours to free--that will be done by the free call to
* the rollingfile appender
*/
sd_debug("freeing timewin udata from rollingpolicy instance");
free(swup);
log4c_rollingpolicy_set_udata(this,NULL);
timewin_fini_exit:
sd_debug("]");
return(rc);
}
/*******************************************************************************
timewin specific conf functions
*******************************************************************************/
LOG4C_API rollingpolicy_timewin_udata_t *timewin_make_udata(void)
{
rollingpolicy_timewin_udata_t *swup = NULL;
swup = (rollingpolicy_timewin_udata_t *)sd_calloc(1,
sizeof(rollingpolicy_timewin_udata_t));
timewin_udata_set_file_time_type(swup,
ROLLINGPOLICY_TIME_DEFAULT_FILE_TYPE);
timewin_udata_set_max_num_files(swup,
ROLLINGPOLICY_TIME_DEFAULT_MAX_NUM_FILES);
swup->sw_curfileflag = 0;
swup->sw_prefileflag = 0;
swup->sw_flags = 0;
return(swup);
}
/*******************************************************************************/
LOG4C_API int timewin_udata_set_file_time_type(rollingpolicy_timewin_udata_t * swup,
long time_type){
swup->sw_conf.swc_file_time_type = time_type;
return(0);
}
/****************************************************************************/
LOG4C_API int timewin_udata_set_max_num_files(rollingpolicy_timewin_udata_t *swup,
long max_num){
swup->sw_conf.swc_file_max_num_files = max_num;
return(0);
}
/****************************************************************************/
LOG4C_API int timewin_udata_set_rfudata(rollingpolicy_timewin_udata_t *swup,
rollingfile_udata_t *rfup ){
swup->sw_rfudata = rfup;
return(0);
}
/*****************************************************************************
private functions
*****************************************************************************/
/****************************************************************************/
static char* timewin_get_filename(rollingpolicy_timewin_udata_t* swup){
long filename_len = 0;
char *s = NULL;
filename_len = strlen(swup->sw_logdir) + 1 +
strlen(swup->sw_files_prefix) + 1 + 15; // a margin /
s = (char *)malloc(filename_len);
sprintf( s, "%s%s%s%s%s", swup->sw_logdir,
FILE_SEP, swup->sw_files_prefix, swup->sw_curfileflag, ".log");
return(s);
}
/********************************************************************************/
static int timewin_check_update_fileflag(rollingpolicy_timewin_udata_t * swup)
{
struct tm tm;
time_t timep;
time(&timep);
char buf[11];
memset(buf, 0, 11);
#ifndef _WIN32
#ifndef __HP_cc
#warning gmtime() routine should be defined in sd_xplatform
#endif
localtime_r(&timep, &tm);
#else
/* xxx Need a CreateMutex/ReleaseMutex or something here
*/
{
struct tm *tmp = NULL;
tmp = localtime(&timep);
tm = *tmp; /* struct copy */
}
#endif
swup->sw_flags = 0;
switch (swup->sw_conf.swc_file_time_type)
{
case TIME_TYPE_YEAR:
sprintf(buf, "%04d", tm.tm_year + 1900);
break;
case TIME_TYPE_MONTH:
sprintf(buf, "%04d%02d", tm.tm_year + 1900, tm.tm_mon + 1);
break;
case TIME_TYPE_DAY:
sprintf(buf, "%04d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
break;
case TIME_TYPE_HOUR:
sprintf(buf, "%04d%02d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour);
break;
default:
sprintf(buf, "%04d%02d%02d%02d", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour);
break;
}
if (swup->sw_curfileflag == NULL)
{
timewin_copy_string(&swup->sw_curfileflag, buf);
swup->sw_flags = 1;
}
else if (strcmp(swup->sw_curfileflag, buf) != 0)
{
timewin_copy_string(&swup->sw_prefileflag, swup->sw_curfileflag);
timewin_copy_string(&swup->sw_curfileflag, buf);
swup->sw_flags = 1;
}
return swup->sw_flags;
}
/******************************************************************************/
static int timewin_copy_string(char** szDest, const char* src)
{
int len = 0;
if (src == 0)
{
return -1;
}
len = strlen(src) + 1;
if (*szDest == NULL)
{
* szDest = (char *)malloc(len);
}
else if (strlen(*szDest) < len)
{
free(*szDest);
* szDest = (char *)malloc(len);
memset(*szDest, 0, len);
}
memcpy(* szDest, src, len);
return 0;
}
/*******************************************************************************/
static int timewin_open_file(char *filename, FILE **fpp ){
int rc = 0;
sd_debug("timewin_open_file['%s'", filename);
if ( (*fpp = fopen(filename, "a+")) == NULL){
sd_error("failed to open file '%s'--defaulting to stderr--error='%s'",
filename, strerror(errno));
*fpp = stderr;
rc = 1;
}
/* unbuffered mode at the filesystem level
xxx make this configurable from the outside ?
*/
setbuf(*fpp, NULL);
sd_debug("]");
return(rc);
}
/****************************************************************************/
const log4c_rollingpolicy_type_t log4c_rollingpolicy_type_timewin = {
"timewin",
timewin_init,
timewin_is_triggering_event,
timewin_rollover,
timewin_fini
};
7.3 init.c
#ifdef WITH_ROLLINGFILE
static const log4c_rollingpolicy_type_t * const rollingpolicy_types[] = {
&log4c_rollingpolicy_type_sizewin,
&log4c_rollingpolicy_type_timewin
};
static size_t nrollingpolicy_types =
sizeof(rollingpolicy_types) / sizeof(rollingpolicy_types[0]);
#endif
rc.c
#ifdef WITH_ROLLINGFILE
/******************************************************************************/
static int rollingpolicy_load(log4c_rc_t* this, sd_domnode_t* anode)
{
sd_domnode_t* name = sd_domnode_attrs_get(anode, "name");
sd_domnode_t* type = sd_domnode_attrs_get(anode, "type");
log4c_rollingpolicy_t* rpolicyp = NULL;
sd_debug("rollingpolicy_load[");
if (!name) {
sd_error("attribute /"name/" is missing");
return -1;
}
rpolicyp = log4c_rollingpolicy_get(name->value);
if (type){
log4c_rollingpolicy_set_type(rpolicyp,
log4c_rollingpolicy_type_get(type->value));
if (!strcasecmp(type->value, "sizewin")){
sd_domnode_t* maxsize = sd_domnode_attrs_get(anode, "maxsize");
sd_domnode_t* maxnum = sd_domnode_attrs_get(anode, "maxnum");
rollingpolicy_sizewin_udata_t *sizewin_udatap = NULL;
sd_debug("type='sizewin', maxsize='%s', maxnum='%s', "
"rpolicyname='%s'",
(maxsize && maxsize->value ? maxsize->value :"(not set)"),
(maxnum && maxnum->value ? maxnum->value :"(not set)"),
(name && name->value ? name->value :"(not set)"));
/*
* Get a new sizewin policy type and configure it.
* Then attach it to the policy object.
* Check to see if this policy already has a
sw udata object. If so, leave as is except update
the params
*/
if ( !(sizewin_udatap = log4c_rollingpolicy_get_udata(rpolicyp))){
sd_debug("creating new sizewin udata for this policy");
sizewin_udatap = sizewin_make_udata();
log4c_rollingpolicy_set_udata(rpolicyp,sizewin_udatap);
sizewin_udata_set_file_maxsize(sizewin_udatap, atoi(maxsize->value));
sizewin_udata_set_max_num_files(sizewin_udatap, atoi(maxnum->value));
}else{
sd_debug("policy already has a sizewin udata--just updating params");
sizewin_udata_set_file_maxsize(sizewin_udatap, atoi(maxsize->value));
sizewin_udata_set_max_num_files(sizewin_udatap, atoi(maxnum->value));
/* allow the policy to initialize itself */
log4c_rollingpolicy_init(rpolicyp,
log4c_rollingpolicy_get_rfudata(rpolicyp));
}
}
else if (!strcasecmp(type->value, "timewin")){
sd_domnode_t* timetype = sd_domnode_attrs_get(anode, "timetype");
sd_domnode_t* maxnum = sd_domnode_attrs_get(anode, "maxnum");
rollingpolicy_timewin_udata_t *timewin_udatap = NULL;
sd_debug("type='timewin', timetype='%s', maxnum='%s', "
"rpolicyname='%s'",
(timetype && timetype->value ? timetype->value :"(not set)"),
(maxnum && maxnum->value ? maxnum->value :"(not set)"),
(name && name->value ? name->value :"(not set)"));
/*
* Get a new sizewin policy type and configure it.
* Then attach it to the policy object.
* Check to see if this policy already has a
sw udata object. If so, leave as is except update
the params
*/
if ( !(timewin_udatap = log4c_rollingpolicy_get_udata(rpolicyp))){
sd_debug("creating new sizewin udata for this policy");
timewin_udatap = timewin_make_udata();
log4c_rollingpolicy_set_udata(rpolicyp,timewin_udatap);
timewin_udata_set_file_time_type(timewin_udatap, atoi(timetype->value));
timewin_udata_set_max_num_files(timewin_udatap, atoi(maxnum->value));
}else{
sd_debug("policy already has a sizewin udata--just updating params");
timewin_udata_set_file_time_type(timewin_udatap, atoi(timetype->value));
timewin_udata_set_max_num_files(timewin_udatap, atoi(maxnum->value));
/* allow the policy to initialize itself */
log4c_rollingpolicy_init(rpolicyp,
log4c_rollingpolicy_get_rfudata(rpolicyp));
}
}
}
sd_debug("]");
return 0;
}
#endif
- Log4c学习笔记
- Log4c学习笔记
- Log4c学习笔记
- Log4c学习笔记
- log4c 学习笔记
- log4c 的学习
- Log4C++
- log4c version
- log4c/log4cxx
- Log4c使用
- Log4c 使用
- log4c 总结
- Log4c使用
- A example of Log4c
- log4c-embed日志
- log4c的使用
- log4c面向对象设计
- log4c 使用例程
- WM 模拟器常见问题如何联网、打电话、发送短信、连接GPRS、硬起等
- C# lambda
- ThinkPad键盘拆解与清理(附图详解)
- 网站怎样留住浏览用户
- 17条网站的隐患,影响你的收录排名
- Log4c学习笔记
- editPlus3.2 注册码
- KillTimer
- 装饰模式Decorator
- Visual Studio 中各种文件后缀名是什么意思
- Video Game Internationalization Issues
- slope one
- 数据库复杂语句
- 我又回来了。。。