OSDN Git Service

Initial commit from 2.1.2-1
[ultramonkey-l7/ultramonkey-l7-v2.git] / logger / strict_time_based_rolling_policy.cpp
diff --git a/logger/strict_time_based_rolling_policy.cpp b/logger/strict_time_based_rolling_policy.cpp
new file mode 100644 (file)
index 0000000..82f823d
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * @file  strict_time_based_rolling_policy.cpp
+ * @brief log4cxx's rolling policy class. (time)
+ *
+ * L7VSD: Linux Virtual Server for Layer7 Load Balancing
+ * Copyright (C) 2008  NTT COMWARE Corporation.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *      
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ **********************************************************************/
+
+#include <log4cxx/logstring.h>
+#include <log4cxx/rolling/filerenameaction.h>
+#include <log4cxx/helpers/loglog.h>
+#include <log4cxx/helpers/exception.h>
+#include <log4cxx/helpers/stringhelper.h>
+#include <log4cxx/helpers/optionconverter.h>
+#include <time.h>
+#include "strict_time_based_rolling_policy.h"
+#include "lexical_cast.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+using namespace log4cxx;
+using namespace log4cxx::rolling;
+using namespace log4cxx::helpers;
+using namespace log4cxx::pattern;
+
+#define TIME_BUF_LEN (256)
+#define LOG_DATE_FORMAT "%Y%m%d%H%M"
+#define LOG_DATE_FORMAT_WEEK "%Y%m%d%w%H%M"
+
+IMPLEMENT_LOG4CXX_OBJECT(StrictTimeBasedRollingPolicy)
+
+/*!
+ * default constructor.
+ * initialize member valiables
+ * @param   void
+ * @return  void
+ */
+StrictTimeBasedRollingPolicy::StrictTimeBasedRollingPolicy() :
+       nextCheck(0), rotationTiming(LOG_TIM_YEAR), rotationTimingValue("")
+{
+}
+
+/*!
+ * increase reffernce count
+ * @param   void
+ * @return  void
+ */
+void StrictTimeBasedRollingPolicy::addRef() const
+{
+       TriggeringPolicy::addRef();
+}
+
+/*!
+ * decrease reffernce count
+ * @param   void
+ * @return  void
+ */
+void StrictTimeBasedRollingPolicy::releaseRef() const
+{
+       TriggeringPolicy::releaseRef();
+}
+
+/*!
+ * evaluate and activate options
+ * @param   memory pool
+ * @return  void
+ */
+void StrictTimeBasedRollingPolicy::activateOptions(log4cxx::helpers::Pool& pool)
+{
+       // check for rotationTimingValue
+       if (0 >= rotationTimingValue.length()) {
+               LogLog::warn(
+               LOG4CXX_STR("The RotationTimingValue option must be set before using StrictTimeBasedRollingPolicy. "));
+               throw IllegalStateException();
+       }
+
+       // call super class's activateOptions
+       FixedWindowRollingPolicy::activateOptions(pool);
+}
+
+/*!
+ * rotationTimingValue getter
+ * @param   void
+ * @return  rotationTimingValue
+ */
+std::string StrictTimeBasedRollingPolicy::getRotationTimingValue()
+{
+       return rotationTimingValue;
+}
+/*!
+ * rotationTimingValue setter
+ * @param   rotationTimingValue
+ * @return  void
+ */
+void StrictTimeBasedRollingPolicy::setRotationTimingValue(const std::string& val)
+{
+       rotationTimingValue = val;
+}
+
+/*!
+ * rotationTiming getter
+ * @param   void
+ * @return  rotationTiming
+ */
+LOG_ROTATION_TIMING_TAG StrictTimeBasedRollingPolicy::getRotationTiming()
+{
+       return rotationTiming;
+}
+/*!
+ * rotationTiming setter
+ * @param   rotationTiming
+ * @return  void
+ */
+void StrictTimeBasedRollingPolicy::setRotationTiming(const LOG_ROTATION_TIMING_TAG val)
+{
+       rotationTiming = val;
+}
+
+/*!
+ * option setter
+ * @param   option name
+ * @param   value
+ * @return  void
+ */
+void StrictTimeBasedRollingPolicy::setOption(const LogString& option, const LogString& value)
+{
+       if (StringHelper::equalsIgnoreCase(option,
+               LOG4CXX_STR("ROTATIONTIMINGVALUE"),
+               LOG4CXX_STR("rotationtimingvalue"))) {
+               rotationTimingValue = value;
+       }
+       else if (StringHelper::equalsIgnoreCase(option,
+               LOG4CXX_STR("ROTATIONTIMING"),
+               LOG4CXX_STR("rotationtiming"))) {
+               rotationTiming = (LOG_ROTATION_TIMING_TAG)OptionConverter::toInt(value, 0);
+       }
+       else {
+               FixedWindowRollingPolicy::setOption(option, value);
+       }
+}
+
+/*!
+ * rolling policy initialize
+ * @param   filename of current use
+ * @param   append or overWrite
+ * @param   memory pool
+ * @return  Rollover information
+ */
+RolloverDescriptionPtr StrictTimeBasedRollingPolicy::initialize(
+       const LogString& currentActiveFile,
+       const bool append,
+       Pool& pool) 
+{
+       // get current time
+       time_t now_time;
+       time_t ret_time = time(&now_time);
+       if (-1 == ret_time) {
+               LogLog::warn(LOG4CXX_STR("Fail to get CurrentTime. "));
+               RolloverDescriptionPtr desc;
+               return desc;
+       }
+
+       // get next rotation timing
+       nextCheck = getNextCheck(now_time);
+       if (-1 == nextCheck) {
+               LogLog::warn(LOG4CXX_STR("Fail to get nextCheck. "));
+               RolloverDescriptionPtr desc;
+               return desc;
+       }       
+
+       // call super class's initialize
+       return FixedWindowRollingPolicy::initialize(currentActiveFile, append, pool);
+}
+
+/*!
+ * calculate next rollover timing
+ * @param   now time
+ * @return  next rollover time
+ */
+time_t StrictTimeBasedRollingPolicy::getNextCheck(time_t now_time)
+{
+       struct tm now_tm;
+       struct tm *ret_tm;
+       ret_tm = localtime_r(&now_time, &now_tm);
+       if (0 == ret_tm) {
+               return -1;
+       }
+       
+       char buf[TIME_BUF_LEN];
+       size_t ret_sz = 0;
+       if (LOG_TIM_WEEK == rotationTiming) {
+               ret_sz = strftime(buf, sizeof(buf), LOG_DATE_FORMAT_WEEK, &now_tm);
+       }
+       else {
+               ret_sz = strftime(buf, sizeof(buf), LOG_DATE_FORMAT, &now_tm);
+       }
+       if (0 == ret_sz) {
+               return -1;
+       }
+       std::string now(buf);
+
+       int dates[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
+       unsigned long long numNowDate = 0;;
+       unsigned long long numTimingDate = 0;
+
+       int numYear = 0;
+       int numMonth = 0;
+       int numDate = 0;
+       int numNowWeek = 0;
+       int numTimingWeek = 0;
+       int numHour = 0;
+       int numMinute = 0;
+
+       struct tm t;
+       memset(&t, 0, sizeof(struct tm));
+
+       time_t next = 0;
+
+       try {
+               switch (rotationTiming) {
+               case LOG_TIM_YEAR:
+                       numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(4));
+                       numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
+       
+                       numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
+                       numMonth = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 2));
+                       numDate = l7vs::lexical_cast<int>(rotationTimingValue.substr(2, 2));
+                       numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(4, 2));
+                       numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(6));
+       
+                       if (numTimingDate > numNowDate) {
+                               t.tm_year = numYear - 1900;
+                       }
+                       else {
+#if defined(LOGGER_PROCESS_ADM)
+                               t.tm_year = numYear - 1900;
+#else  //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
+                               t.tm_year = numYear + 1 - 1900;
+#endif
+                       }
+                       t.tm_mon = numMonth - 1;
+                       t.tm_mday = numDate;
+                       t.tm_hour = numHour;
+                       t.tm_min = numMinute;
+       
+                       next = mktime(&t);
+                       if (-1 == next) {
+                               return -1;
+                       }
+                       break;
+       
+               case LOG_TIM_MONTH:
+                       numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(6));
+                       numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
+       
+                       numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
+                       numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
+                       numDate = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 2));
+                       numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(2, 2));
+                       numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(4));
+       
+                       if (numTimingDate > numNowDate) {
+                               t.tm_year = numYear - 1900;
+                               t.tm_mon = numMonth - 1;
+                       }
+                       else {
+#if defined(LOGGER_PROCESS_ADM)
+                               t.tm_year = numYear - 1900;
+                               t.tm_mon = numMonth - 1;
+#else  //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
+                               if (12 == numMonth) {
+                                       t.tm_year = numYear + 1 - 1900;
+                                       t.tm_mon = 0;
+                               }
+                               else {
+                                       t.tm_year = numYear - 1900;
+                                       t.tm_mon = numMonth + 1 - 1;
+                               }
+#endif
+                       }
+       
+                       if (numDate > dates[t.tm_mon]) {
+                               t.tm_mday = dates[t.tm_mon];
+                       }
+                       else {
+                               t.tm_mday = numDate;
+                       }
+
+                       t.tm_hour = numHour;
+                       t.tm_min = numMinute;
+       
+                       next = mktime(&t);
+                       if (-1 == next) {
+                               return -1;
+                       }
+       
+                       break;
+               case LOG_TIM_WEEK:
+                       numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(8));
+                       numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
+       
+                       numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
+                       numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
+                       numDate = l7vs::lexical_cast<int>(now.substr(6, 2));
+                       numNowWeek = l7vs::lexical_cast<int>(now.substr(8, 1));
+                       numTimingWeek = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 1));
+                       numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(1, 2));
+                       numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(3));
+       
+                       t.tm_year = numYear - 1900;
+                       t.tm_mon = numMonth - 1;
+                       if (numTimingDate > numNowDate) {       
+                               t.tm_mday = numDate + (numTimingWeek - numNowWeek); 
+                       }
+                       else {
+#if defined(LOGGER_PROCESS_ADM)
+                               t.tm_mday = numDate + (numTimingWeek - numNowWeek); 
+#else  //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
+                               t.tm_mday = numDate + (7 - (numNowWeek - numTimingWeek));
+#endif
+                       }
+                       t.tm_hour = numHour;
+                       t.tm_min = numMinute;
+       
+                       next = mktime(&t);
+                       if (-1 == next) {
+                               return -1;
+                       }
+       
+                       break;
+       
+               case LOG_TIM_DATE:
+                       numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(8));
+                       numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
+       
+                       numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
+                       numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
+                       numDate = l7vs::lexical_cast<int>(now.substr(6, 2));
+                       numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 2));
+                       numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(2));
+       
+                       t.tm_year = numYear - 1900;
+                       t.tm_mon = numMonth - 1;
+                       if (numTimingDate > numNowDate) {       
+                               t.tm_mday = numDate;
+                       }
+                       else {
+#if defined(LOGGER_PROCESS_ADM)
+                               t.tm_mday = numDate; 
+#else  //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
+                               t.tm_mday = numDate + 1; 
+#endif
+                       }
+                       t.tm_hour = numHour;
+                       t.tm_min = numMinute;
+       
+                       next = mktime(&t);
+                       if (-1 == next) {
+                               return -1;
+                       }
+                       break;
+       
+               default:        //HOUR
+                       numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(10));
+                       numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
+       
+                       numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
+                       numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
+                       numDate = l7vs::lexical_cast<int>(now.substr(6, 2));
+                       numHour = l7vs::lexical_cast<int>(now.substr(8, 2));
+                       numMinute = l7vs::lexical_cast<int>(rotationTimingValue);
+       
+                       t.tm_year = numYear - 1900;
+                       t.tm_mon = numMonth - 1;
+                       t.tm_mday = numDate;
+                       if (numTimingDate > numNowDate) {
+                               t.tm_hour = numHour;
+                       }
+                       else {
+#if defined(LOGGER_PROCESS_ADM)
+                               t.tm_hour = numHour;
+#else  //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
+                               t.tm_hour = numHour + 1;
+#endif
+                       }
+                       t.tm_min = numMinute;
+       
+                       next = mktime(&t);
+                       if (-1 == next) {
+                               return -1;
+                       }
+               }
+       }
+       catch (const std::exception& ex) {
+               return -1;
+       }
+       return next;
+
+}
+
+/*!
+ * log file rollover opration
+ * @param   name of current log file
+ * @param   memory pool
+ * @return  Rollover infomation
+ */
+RolloverDescriptionPtr StrictTimeBasedRollingPolicy::rollover(
+       const LogString& currentActiveFile,
+       Pool& pool) 
+{
+       // get current time
+       time_t now_time;
+       time_t ret_time = time(&now_time);
+       if (-1 == ret_time) {
+               LogLog::warn(LOG4CXX_STR("Fail to get CurrentTime. "));
+               RolloverDescriptionPtr desc;
+               return desc;
+       }
+
+       // get next rotation timing
+       nextCheck = getNextCheck(now_time);
+       if (-1 == nextCheck) {
+               LogLog::warn(LOG4CXX_STR("Fail to get nextCheck. "));
+               RolloverDescriptionPtr desc;
+               return desc;
+       }       
+
+       // call super class's rollover
+       return FixedWindowRollingPolicy::rollover(currentActiveFile, pool);
+
+}
+
+/*!
+ * returns do rollover or not
+ * @param   appender (not use)
+ * @param   event (not use)
+ * @param   filename
+ * @param   fileLength (not use)
+ * @retval  true do rollover
+ * @retval  false not rollover yet
+ */
+bool StrictTimeBasedRollingPolicy::isTriggeringEvent(
+       Appender* /* appender */,
+       const log4cxx::spi::LoggingEventPtr& /* event */,
+       const LogString& filename,
+       size_t /* fileLength */)  
+{
+       time_t now_time;
+       time_t ret_time = time(&now_time);
+       if (-1 == ret_time) {
+               LogLog::warn(LOG4CXX_STR("Fail to get time. "));
+               return false;
+       }
+#if defined(LOGGER_PROCESS_ADM)
+       struct stat sb;
+
+       if (-1 == stat(filename.c_str(), &sb)) {
+               LogLog::warn(LOG4CXX_STR("Fail to get logfile update time. "));
+               return false;
+       }
+       if (now_time > nextCheck && nextCheck > sb.st_mtime) {
+               // Do rollover.
+               return true;
+       } else {
+               // Do not rollover.
+               return false;
+       }
+#else  //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
+       return now_time > nextCheck;
+#endif
+}