开源日志库log4c存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;

本文主要是介绍开源日志库log4c存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

开源日志库log4c存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;这样在ARM中应用时,当应用重启了,但是log0还没有达到maxsize,就切换了一个新的文件,会造成空间浪费,网上查了好久,log4c没有提供这样的接口,维护别人的代码,用到了log4c这个库,只能修改log4c的源码了。

源码修改的地方如下:

static int get_file_size(const char *filename)
{
FILE*fp;
if((fp=fopen(filename,"rb"))==NULL)
{
return -1;
}
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
fclose(fp);
return len;
}
/*******************************************************************************/
static int sizewin_rollover(log4c_rollingpolicy_t *this, FILE ** current_fpp ){
int rc = 0;
rollingpolicy_sizewin_udata_t *swup = log4c_rollingpolicy_get_udata(this);
int k = 0;
int i = 0;
sd_debug("sizewin_rollover[");
/* Starting at the last_index work back renaming the files and
leaving space for the .0 file.
If the last index is negative then it means the file doesn't exist
so we create the first file
*/
if ( !swup || !swup->sw_logdir){
sd_error("rollingpolicy '%s' not yet configured (logdir,prefix etc.)",
log4c_rollingpolicy_get_name(this));
} else {
swup->sw_last_index = sizewin_get_last_index(swup);  
k = swup->sw_last_index;
if ( k < 0 ) {
sd_debug("creating first file");
if (sizewin_open_zero_file(swup->sw_filenames[0], current_fpp,1)){
swup->sw_flags |= SW_LAST_FOPEN_FAILED;
sd_error("open zero file failed");
} else{
swup->sw_flags &= !SW_LAST_FOPEN_FAILED;
}
swup->sw_last_index = 0;
} else {
sd_debug("rolling up existing files");
if ( k == swup->sw_conf.swc_file_max_num_files-1) {    
if(unlink(swup->sw_filenames[k])){
sd_error("unlink failed");
rc = 1;
} else {
k = swup->sw_conf.swc_file_max_num_files-2;
}
} else {
/* not yet reached the max num of files
* so there's still room to rotate the list up */    
}
/* If there's a current open fp, close it.*/
if ( !(swup->sw_flags & SW_LAST_FOPEN_FAILED) && *current_fpp) {
if(fclose(*current_fpp)){
sd_error("failed to close current log file");
rc = 1;
}
} else {
if( (swup->sw_flags & SW_LAST_FOPEN_FAILED)){
sd_debug("Not closing log file...last open failed");
} else if (*current_fpp == 0) {
sd_debug("No log file currentlty open...so not closing it");
}else {
sd_debug("Not closing current log file...not sure why");
}
}
/* Now, rotate the list up if all seems ok, otherwise 
* don't mess with teh files if something seems to have gone wrong
*/
int new_file_flag=0;
if ( !rc){
sd_debug("rotate up , last index is %d", k);
int len= get_file_size(swup->sw_filenames[0]);
int max_len=swup->sw_conf.swc_file_maxsize/100000*100000;
if(len>max_len ||len==-1)
{
i = k;
while ( i >= 0 ) {
sd_debug("Renaming %s to %s",
swup->sw_filenames[i], swup->sw_filenames[i+1]);
if(rename( swup->sw_filenames[i], swup->sw_filenames[i+1])){
sd_error("rename failed"); 
rc = 1;
// break;
}
i--;
}
if ( !rc){
swup->sw_last_index = k + 1;
}
new_file_flag=1;
}
} else {
sd_debug("not rotating up--some file access error");
}
/* Now open up the 0'th file for writing */
if (sizewin_open_zero_file(swup->sw_filenames[0], current_fpp,new_file_flag)){
swup->sw_flags |= SW_LAST_FOPEN_FAILED;
sd_error("open zero file failed");
rc = 1;
} else{
swup->sw_flags &= !SW_LAST_FOPEN_FAILED;
rc = 0;
}
}
sd_debug("current file descriptor '%d'", fileno(*current_fpp));
}
sd_debug("]");
return(rc);
}


 

static int sizewin_open_zero_file(char *filename, FILE **fpp,int flag ){
int rc = 0;
sd_debug("sizewin_open_zero_file['%s'", filename);
if(flag)
{
*fpp = fopen(filename, "w+");
}else
{
*fpp = fopen(filename, "a+");
}
if ( (*fpp) == NULL){
sd_error("failed to open zero 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);
}


 

 

以下内容转自互联网,版权归原作者所有:

http://xueqi.iteye.com/blog/1570013

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存在的一个bug,程序重启后,每次都重新写新的文件,不是接在在原来的文件中写;的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/599732

相关文章

java中判断json key是否存在的几种方法

《java中判断jsonkey是否存在的几种方法》在使用Java处理JSON数据时,如何判断某一个key是否存在?本文就来介绍三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的... 目http://www.chinasem.cn录第一种方法是使用 jsONObject 的 has 方法

java程序远程debug原理与配置全过程

《java程序远程debug原理与配置全过程》文章介绍了Java远程调试的JPDA体系,包含JVMTI监控JVM、JDWP传输调试命令、JDI提供调试接口,通过-Xdebug、-Xrunjdwp参数配... 目录背景组成模块间联系IBM对三个模块的详细介绍编程使用总结背景日常工作中,每个程序员都会遇到bu

uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)

《uni-app小程序项目中实现前端图片压缩实现方式(附详细代码)》在uni-app开发中,文件上传和图片处理是很常见的需求,但也经常会遇到各种问题,下面:本文主要介绍uni-app小程序项目中实... 目录方式一:使用<canvas>实现图片压缩(推荐,兼容性好)示例代码(小程序平台):方式二:使用uni

Java 日志中 Marker 的使用示例详解

《Java日志中Marker的使用示例详解》Marker是SLF4J(以及Logback、Log4j2)提供的一个接口,它本质上是一个命名对象,你可以把它想象成一个可以附加到日志语句上的标签或戳... 目录什么是Marker?为什么使用Markejavascriptr?1. 精细化的过滤2. 触发特定操作3

Oracle数据库在windows系统上重启步骤

《Oracle数据库在windows系统上重启步骤》有时候在服务中重启了oracle之后,数据库并不能正常访问,下面:本文主要介绍Oracle数据库在windows系统上重启的相关资料,文中通过代... oracle数据库在Windows上重启的方法我这里是使用oracle自带的sqlplus工具实现的方

linux查找java项目日志查找报错信息方式

《linux查找java项目日志查找报错信息方式》日志查找定位步骤:进入项目,用tail-f实时跟踪日志,tail-n1000查看末尾1000行,grep搜索关键词或时间,vim内精准查找并高亮定位,... 目录日志查找定位在当前文件里找到报错消息总结日志查找定位1.cd 进入项目2.正常日志 和错误日

MySQL使用EXISTS检查记录是否存在的详细过程

《MySQL使用EXISTS检查记录是否存在的详细过程》EXISTS是SQL中用于检查子查询是否返回至少一条记录的运算符,它通常用于测试是否存在满足特定条件的记录,从而在主查询中进行相应操作,本文给大... 目录基本语法示例数据库和表结构1. 使用 EXISTS 在 SELECT 语句中2. 使用 EXIS

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

SpringBoot日志级别与日志分组详解

《SpringBoot日志级别与日志分组详解》文章介绍了日志级别(ALL至OFF)及其作用,说明SpringBoot默认日志级别为INFO,可通过application.properties调整全局或... 目录日志级别1、级别内容2、调整日志级别调整默认日志级别调整指定类的日志级别项目开发过程中,利用日志

深度剖析SpringBoot日志性能提升的原因与解决

《深度剖析SpringBoot日志性能提升的原因与解决》日志记录本该是辅助工具,却为何成了性能瓶颈,SpringBoot如何用代码彻底破解日志导致的高延迟问题,感兴趣的小伙伴可以跟随小编一起学习一下... 目录前言第一章:日志性能陷阱的底层原理1.1 日志级别的“双刃剑”效应1.2 同步日志的“吞吐量杀手”