開源日誌庫log4c存在的一個bug,程式重啟後,每次都重新寫新的檔案,不是接在在原來的檔案中寫;

smilestone322發表於2015-09-30

開源日誌庫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

相關文章