00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "wvdailyevent.h"
00016 #include "wvstream.h"
00017 #include "wvtimeutils.h"
00018
00019 #include <time.h>
00020
00021 #ifndef _WIN32
00022 #include <sys/time.h>
00023 #include <unistd.h>
00024 #endif
00025
00026 #define NUM_MINS_IN_DAY (24*60)
00027 #define NUM_SECS_IN_DAY (60*NUM_MINS_IN_DAY)
00028
00029 WvDailyEvent::WvDailyEvent(int _first_hour, int _num_per_day, bool _skip_first)
00030 : prev(time(NULL))
00031 {
00032 need_reset = false;
00033 prev = wvstime().tv_sec;
00034 configure(_first_hour, _num_per_day, _skip_first);
00035 }
00036
00037
00038
00039 void WvDailyEvent::pre_select(SelectInfo &si)
00040 {
00041 WvStream::pre_select(si);
00042
00043 if (num_per_day)
00044 {
00045 time_t now = wvstime().tv_sec;
00046 time_t next = next_event();
00047
00048 assert(prev);
00049 assert(next);
00050 assert(prev > 100000);
00051 assert(next > 100000);
00052
00053
00054 if (now < next)
00055 si.msec_timeout = msecdiff(now, next);
00056 else if (!need_reset)
00057 {
00058 need_reset = true;
00059 prev = next;
00060 }
00061 }
00062 if (need_reset)
00063 si.msec_timeout = 0;
00064
00065 }
00066
00067
00068
00069 bool WvDailyEvent::post_select(SelectInfo& si)
00070 {
00071 bool timer_rang = false;
00072 WvTime next(next_event(), 0);
00073 if (next < wvtime())
00074 {
00075 timer_rang = true;
00076 prev = next;
00077 }
00078
00079 return WvStream::post_select(si) || need_reset || timer_rang;
00080 }
00081
00082
00083 void WvDailyEvent::set_num_per_day(int _num_per_day)
00084 {
00085 num_per_day = _num_per_day;
00086 if (num_per_day < 0)
00087 num_per_day = 1;
00088
00089 if (num_per_day > NUM_SECS_IN_DAY)
00090 num_per_day = NUM_SECS_IN_DAY;
00091
00092 time_t max = num_per_day ? NUM_SECS_IN_DAY/num_per_day : 6*60*60;
00093 if (max > 6*60*60)
00094 max = 6*60*60;
00095
00096
00097 prev = wvstime().tv_sec;
00098 not_until = prev + max;
00099 }
00100
00101
00102 void WvDailyEvent::configure(int _first_hour, int _num_per_day, bool _skip_first)
00103 {
00104 first_hour = _first_hour;
00105 skip_first = _skip_first;
00106
00107
00108
00109 if (_num_per_day > NUM_MINS_IN_DAY)
00110 _num_per_day = NUM_MINS_IN_DAY;
00111
00112 set_num_per_day(_num_per_day);
00113 }
00114
00115
00116
00117 time_t WvDailyEvent::next_event() const
00118 {
00119 if (!num_per_day)
00120 return 0;
00121
00122 assert(prev);
00123
00124 time_t interval = NUM_SECS_IN_DAY/num_per_day;
00125 time_t start = prev + interval;
00126
00127
00128 struct tm *tm = localtime(&start);
00129 if (tm->tm_hour < first_hour)
00130 {
00131 start = prev - NUM_SECS_IN_DAY + 1;
00132 tm = localtime(&start);
00133 }
00134 tm->tm_hour = first_hour;
00135 tm->tm_min = tm->tm_sec = 0;
00136 start = mktime(tm);
00137
00138
00139
00140 time_t next = prev + interval;
00141 if ((next - start)%interval != 0)
00142 next = start + (next - start)/interval * interval;
00143
00144 assert(next);
00145 assert(next > 100000);
00146
00147 while (skip_first && next < not_until)
00148 next += interval;
00149
00150 return next;
00151 }