OSDN Git Service

Fixed chkconfig option
[ultramonkey-l7/ultramonkey-l7-v2.git] / logger / strict_time_based_rolling_policy.cpp
1 /*
2  * @file  strict_time_based_rolling_policy.cpp
3  * @brief log4cxx's rolling policy class. (time)
4  *
5  * L7VSD: Linux Virtual Server for Layer7 Load Balancing
6  * Copyright (C) 2008  NTT COMWARE Corporation.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *      
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  **********************************************************************/
24
25 #include <log4cxx/logstring.h>
26 #include <log4cxx/rolling/filerenameaction.h>
27 #include <log4cxx/helpers/loglog.h>
28 #include <log4cxx/helpers/exception.h>
29 #include <log4cxx/helpers/stringhelper.h>
30 #include <log4cxx/helpers/optionconverter.h>
31 #include <time.h>
32 #include "strict_time_based_rolling_policy.h"
33 #include "lexical_cast.h"
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37
38 using namespace log4cxx;
39 using namespace log4cxx::rolling;
40 using namespace log4cxx::helpers;
41 using namespace log4cxx::pattern;
42
43 #define TIME_BUF_LEN (256)
44 #define LOG_DATE_FORMAT "%Y%m%d%H%M"
45 #define LOG_DATE_FORMAT_WEEK "%Y%m%d%w%H%M"
46
47 IMPLEMENT_LOG4CXX_OBJECT(StrictTimeBasedRollingPolicy)
48
49 /*!
50  * default constructor.
51  * initialize member valiables
52  * @param   void
53  * @return  void
54  */
55 StrictTimeBasedRollingPolicy::StrictTimeBasedRollingPolicy() :
56         nextCheck(0), rotationTiming(LOG_TIM_YEAR), rotationTimingValue("")
57 {
58 }
59
60 /*!
61  * increase reffernce count
62  * @param   void
63  * @return  void
64  */
65 void StrictTimeBasedRollingPolicy::addRef() const
66 {
67         TriggeringPolicy::addRef();
68 }
69
70 /*!
71  * decrease reffernce count
72  * @param   void
73  * @return  void
74  */
75 void StrictTimeBasedRollingPolicy::releaseRef() const
76 {
77         TriggeringPolicy::releaseRef();
78 }
79
80 /*!
81  * evaluate and activate options
82  * @param   memory pool
83  * @return  void
84  */
85 void StrictTimeBasedRollingPolicy::activateOptions(log4cxx::helpers::Pool& pool)
86 {
87         // check for rotationTimingValue
88         if (0 >= rotationTimingValue.length()) {
89                 LogLog::warn(
90                 LOG4CXX_STR("The RotationTimingValue option must be set before using StrictTimeBasedRollingPolicy. "));
91                 throw IllegalStateException();
92         }
93
94         // call super class's activateOptions
95         FixedWindowRollingPolicy::activateOptions(pool);
96 }
97
98 /*!
99  * rotationTimingValue getter
100  * @param   void
101  * @return  rotationTimingValue
102  */
103 std::string StrictTimeBasedRollingPolicy::getRotationTimingValue()
104 {
105         return rotationTimingValue;
106 }
107  
108 /*!
109  * rotationTimingValue setter
110  * @param   rotationTimingValue
111  * @return  void
112  */
113 void StrictTimeBasedRollingPolicy::setRotationTimingValue(const std::string& val)
114 {
115         rotationTimingValue = val;
116 }
117
118 /*!
119  * rotationTiming getter
120  * @param   void
121  * @return  rotationTiming
122  */
123 LOG_ROTATION_TIMING_TAG StrictTimeBasedRollingPolicy::getRotationTiming()
124 {
125         return rotationTiming;
126 }
127  
128 /*!
129  * rotationTiming setter
130  * @param   rotationTiming
131  * @return  void
132  */
133 void StrictTimeBasedRollingPolicy::setRotationTiming(const LOG_ROTATION_TIMING_TAG val)
134 {
135         rotationTiming = val;
136 }
137
138 /*!
139  * option setter
140  * @param   option name
141  * @param   value
142  * @return  void
143  */
144 void StrictTimeBasedRollingPolicy::setOption(const LogString& option, const LogString& value)
145 {
146         if (StringHelper::equalsIgnoreCase(option,
147                 LOG4CXX_STR("ROTATIONTIMINGVALUE"),
148                 LOG4CXX_STR("rotationtimingvalue"))) {
149                 rotationTimingValue = value;
150         }
151         else if (StringHelper::equalsIgnoreCase(option,
152                 LOG4CXX_STR("ROTATIONTIMING"),
153                 LOG4CXX_STR("rotationtiming"))) {
154                 rotationTiming = (LOG_ROTATION_TIMING_TAG)OptionConverter::toInt(value, 0);
155         }
156         else {
157                 FixedWindowRollingPolicy::setOption(option, value);
158         }
159 }
160
161 /*!
162  * rolling policy initialize
163  * @param   filename of current use
164  * @param   append or overWrite
165  * @param   memory pool
166  * @return  Rollover information
167  */
168 RolloverDescriptionPtr StrictTimeBasedRollingPolicy::initialize(
169         const LogString& currentActiveFile,
170         const bool append,
171         Pool& pool) 
172 {
173         // get current time
174         time_t now_time;
175         time_t ret_time = time(&now_time);
176         if (-1 == ret_time) {
177                 LogLog::warn(LOG4CXX_STR("Fail to get CurrentTime. "));
178                 RolloverDescriptionPtr desc;
179                 return desc;
180         }
181
182         // get next rotation timing
183         nextCheck = getNextCheck(now_time);
184         if (-1 == nextCheck) {
185                 LogLog::warn(LOG4CXX_STR("Fail to get nextCheck. "));
186                 RolloverDescriptionPtr desc;
187                 return desc;
188         }       
189
190         // call super class's initialize
191         return FixedWindowRollingPolicy::initialize(currentActiveFile, append, pool);
192 }
193
194 /*!
195  * calculate next rollover timing
196  * @param   now time
197  * @return  next rollover time
198  */
199 time_t StrictTimeBasedRollingPolicy::getNextCheck(time_t now_time)
200 {
201         struct tm now_tm;
202         struct tm *ret_tm;
203         ret_tm = localtime_r(&now_time, &now_tm);
204         if (0 == ret_tm) {
205                 return -1;
206         }
207         
208         char buf[TIME_BUF_LEN];
209         size_t ret_sz = 0;
210         if (LOG_TIM_WEEK == rotationTiming) {
211                 ret_sz = strftime(buf, sizeof(buf), LOG_DATE_FORMAT_WEEK, &now_tm);
212         }
213         else {
214                 ret_sz = strftime(buf, sizeof(buf), LOG_DATE_FORMAT, &now_tm);
215         }
216         if (0 == ret_sz) {
217                 return -1;
218         }
219         std::string now(buf);
220
221         int dates[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 
222         unsigned long long numNowDate = 0;;
223         unsigned long long numTimingDate = 0;
224
225         int numYear = 0;
226         int numMonth = 0;
227         int numDate = 0;
228         int numNowWeek = 0;
229         int numTimingWeek = 0;
230         int numHour = 0;
231         int numMinute = 0;
232
233         struct tm t;
234         memset(&t, 0, sizeof(struct tm));
235
236         time_t next = 0;
237
238         try {
239                 switch (rotationTiming) {
240                 case LOG_TIM_YEAR:
241                         numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(4));
242                         numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
243         
244                         numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
245                         numMonth = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 2));
246                         numDate = l7vs::lexical_cast<int>(rotationTimingValue.substr(2, 2));
247                         numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(4, 2));
248                         numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(6));
249         
250                         if (numTimingDate > numNowDate) {
251                                 t.tm_year = numYear - 1900;
252                         }
253                         else {
254 #if defined(LOGGER_PROCESS_ADM)
255                                 t.tm_year = numYear - 1900;
256 #else   //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
257                                 t.tm_year = numYear + 1 - 1900;
258 #endif
259                         }
260                         t.tm_mon = numMonth - 1;
261                         t.tm_mday = numDate;
262                         t.tm_hour = numHour;
263                         t.tm_min = numMinute;
264         
265                         next = mktime(&t);
266                         if (-1 == next) {
267                                 return -1;
268                         }
269                         break;
270         
271                 case LOG_TIM_MONTH:
272                         numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(6));
273                         numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
274         
275                         numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
276                         numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
277                         numDate = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 2));
278                         numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(2, 2));
279                         numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(4));
280         
281                         if (numTimingDate > numNowDate) {
282                                 t.tm_year = numYear - 1900;
283                                 t.tm_mon = numMonth - 1;
284                         }
285                         else {
286 #if defined(LOGGER_PROCESS_ADM)
287                                 t.tm_year = numYear - 1900;
288                                 t.tm_mon = numMonth - 1;
289 #else   //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
290                                 if (12 == numMonth) {
291                                         t.tm_year = numYear + 1 - 1900;
292                                         t.tm_mon = 0;
293                                 }
294                                 else {
295                                         t.tm_year = numYear - 1900;
296                                         t.tm_mon = numMonth + 1 - 1;
297                                 }
298 #endif
299                         }
300         
301                         if (numDate > dates[t.tm_mon]) {
302                                 t.tm_mday = dates[t.tm_mon];
303                         }
304                         else {
305                                 t.tm_mday = numDate;
306                         }
307
308                         t.tm_hour = numHour;
309                         t.tm_min = numMinute;
310         
311                         next = mktime(&t);
312                         if (-1 == next) {
313                                 return -1;
314                         }
315         
316                         break;
317                 case LOG_TIM_WEEK:
318                         numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(8));
319                         numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
320         
321                         numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
322                         numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
323                         numDate = l7vs::lexical_cast<int>(now.substr(6, 2));
324                         numNowWeek = l7vs::lexical_cast<int>(now.substr(8, 1));
325                         numTimingWeek = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 1));
326                         numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(1, 2));
327                         numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(3));
328         
329                         t.tm_year = numYear - 1900;
330                         t.tm_mon = numMonth - 1;
331                         if (numTimingDate > numNowDate) {       
332                                 t.tm_mday = numDate + (numTimingWeek - numNowWeek); 
333                         }
334                         else {
335 #if defined(LOGGER_PROCESS_ADM)
336                                 t.tm_mday = numDate + (numTimingWeek - numNowWeek); 
337 #else   //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
338                                 t.tm_mday = numDate + (7 - (numNowWeek - numTimingWeek));
339 #endif
340                         }
341                         t.tm_hour = numHour;
342                         t.tm_min = numMinute;
343         
344                         next = mktime(&t);
345                         if (-1 == next) {
346                                 return -1;
347                         }
348         
349                         break;
350         
351                 case LOG_TIM_DATE:
352                         numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(8));
353                         numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
354         
355                         numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
356                         numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
357                         numDate = l7vs::lexical_cast<int>(now.substr(6, 2));
358                         numHour = l7vs::lexical_cast<int>(rotationTimingValue.substr(0, 2));
359                         numMinute = l7vs::lexical_cast<int>(rotationTimingValue.substr(2));
360         
361                         t.tm_year = numYear - 1900;
362                         t.tm_mon = numMonth - 1;
363                         if (numTimingDate > numNowDate) {       
364                                 t.tm_mday = numDate;
365                         }
366                         else {
367 #if defined(LOGGER_PROCESS_ADM)
368                                 t.tm_mday = numDate; 
369 #else   //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
370                                 t.tm_mday = numDate + 1; 
371 #endif
372                         }
373                         t.tm_hour = numHour;
374                         t.tm_min = numMinute;
375         
376                         next = mktime(&t);
377                         if (-1 == next) {
378                                 return -1;
379                         }
380                         break;
381         
382                 default:        //HOUR
383                         numNowDate = l7vs::lexical_cast<unsigned long long>(now.substr(10));
384                         numTimingDate = l7vs::lexical_cast<unsigned long long>(rotationTimingValue);
385         
386                         numYear = l7vs::lexical_cast<int>(now.substr(0, 4));
387                         numMonth = l7vs::lexical_cast<int>(now.substr(4, 2));
388                         numDate = l7vs::lexical_cast<int>(now.substr(6, 2));
389                         numHour = l7vs::lexical_cast<int>(now.substr(8, 2));
390                         numMinute = l7vs::lexical_cast<int>(rotationTimingValue);
391         
392                         t.tm_year = numYear - 1900;
393                         t.tm_mon = numMonth - 1;
394                         t.tm_mday = numDate;
395                         if (numTimingDate > numNowDate) {
396                                 t.tm_hour = numHour;
397                         }
398                         else {
399 #if defined(LOGGER_PROCESS_ADM)
400                                 t.tm_hour = numHour;
401 #else   //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
402                                 t.tm_hour = numHour + 1;
403 #endif
404                         }
405                         t.tm_min = numMinute;
406         
407                         next = mktime(&t);
408                         if (-1 == next) {
409                                 return -1;
410                         }
411                 }
412         }
413         catch (const std::exception& ex) {
414                 return -1;
415         }
416         return next;
417
418 }
419
420 /*!
421  * log file rollover opration
422  * @param   name of current log file
423  * @param   memory pool
424  * @return  Rollover infomation
425  */
426 RolloverDescriptionPtr StrictTimeBasedRollingPolicy::rollover(
427         const LogString& currentActiveFile,
428         Pool& pool) 
429 {
430         // get current time
431         time_t now_time;
432         time_t ret_time = time(&now_time);
433         if (-1 == ret_time) {
434                 LogLog::warn(LOG4CXX_STR("Fail to get CurrentTime. "));
435                 RolloverDescriptionPtr desc;
436                 return desc;
437         }
438
439         // get next rotation timing
440         nextCheck = getNextCheck(now_time);
441         if (-1 == nextCheck) {
442                 LogLog::warn(LOG4CXX_STR("Fail to get nextCheck. "));
443                 RolloverDescriptionPtr desc;
444                 return desc;
445         }       
446
447         // call super class's rollover
448         return FixedWindowRollingPolicy::rollover(currentActiveFile, pool);
449
450 }
451
452 /*!
453  * returns do rollover or not
454  * @param   appender (not use)
455  * @param   event (not use)
456  * @param   filename
457  * @param   fileLength (not use)
458  * @retval  true do rollover
459  * @retval  false not rollover yet
460  */
461 bool StrictTimeBasedRollingPolicy::isTriggeringEvent(
462         Appender* /* appender */,
463         const log4cxx::spi::LoggingEventPtr& /* event */,
464         const LogString& filename,
465         size_t /* fileLength */)  
466 {
467         time_t now_time;
468         time_t ret_time = time(&now_time);
469         if (-1 == ret_time) {
470                 LogLog::warn(LOG4CXX_STR("Fail to get time. "));
471                 return false;
472         }
473 #if defined(LOGGER_PROCESS_ADM)
474         struct stat sb;
475
476         if (-1 == stat(filename.c_str(), &sb)) {
477                 LogLog::warn(LOG4CXX_STR("Fail to get logfile update time. "));
478                 return false;
479         }
480         if (now_time > nextCheck && nextCheck > sb.st_mtime) {
481                 // Do rollover.
482                 return true;
483         } else {
484                 // Do not rollover.
485                 return false;
486         }
487 #else   //LOGGER_PROCESS_VSD or LOGGER_PROCESS_SNM
488         return now_time > nextCheck;
489 #endif
490 }