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 bool WvDailyEvent::pre_select(SelectInfo &si)
00040 {
00041 if (num_per_day)
00042 {
00043 time_t now = wvstime().tv_sec;
00044 time_t next = next_event();
00045
00046 assert(prev);
00047 assert(next);
00048 assert(prev > 100000);
00049 assert(next > 100000);
00050
00051
00052 if (now < next)
00053 si.msec_timeout = msecdiff(now, next);
00054 else if (!need_reset)
00055 {
00056 need_reset = true;
00057 prev = next;
00058 }
00059 }
00060 bool ret = WvStream::pre_select(si) || need_reset;
00061
00062 return ret;
00063 }
00064
00065
00066
00067 bool WvDailyEvent::post_select(SelectInfo& si)
00068 {
00069 bool timer_rang = false;
00070 WvTime next(next_event(), 0);
00071 if (next < wvtime())
00072 {
00073 timer_rang = true;
00074 prev = next;
00075 }
00076
00077 return WvStream::post_select(si) || timer_rang;
00078 }
00079
00080
00081 void WvDailyEvent::set_num_per_day(int _num_per_day)
00082 {
00083 num_per_day = _num_per_day;
00084 if (num_per_day < 0)
00085 num_per_day = 1;
00086
00087 if (num_per_day > NUM_SECS_IN_DAY)
00088 num_per_day = NUM_SECS_IN_DAY;
00089
00090 time_t max = num_per_day ? NUM_SECS_IN_DAY/num_per_day : 6*60*60;
00091 if (max > 6*60*60)
00092 max = 6*60*60;
00093
00094
00095 prev = wvstime().tv_sec;
00096 not_until = prev + max;
00097 }
00098
00099
00100 void WvDailyEvent::configure(int _first_hour, int _num_per_day, bool _skip_first)
00101 {
00102 first_hour = _first_hour;
00103 skip_first = _skip_first;
00104
00105
00106
00107 if (_num_per_day > NUM_MINS_IN_DAY)
00108 _num_per_day = NUM_MINS_IN_DAY;
00109
00110 set_num_per_day(_num_per_day);
00111 }
00112
00113
00114
00115 time_t WvDailyEvent::next_event() const
00116 {
00117 if (!num_per_day)
00118 return 0;
00119
00120 assert(prev);
00121
00122 time_t interval = NUM_SECS_IN_DAY/num_per_day;
00123 time_t start = prev + interval;
00124
00125
00126 struct tm *tm = localtime(&start);
00127 if (tm->tm_hour < first_hour)
00128 {
00129 start = prev - NUM_SECS_IN_DAY + 1;
00130 tm = localtime(&start);
00131 }
00132 tm->tm_hour = first_hour;
00133 tm->tm_min = tm->tm_sec = 0;
00134 start = mktime(tm);
00135
00136
00137
00138 time_t next = prev + interval;
00139 if ((next - start)%interval != 0)
00140 next = start + (next - start)/interval * interval;
00141
00142 assert(next);
00143 assert(next > 100000);
00144
00145 while (skip_first && next < not_until)
00146 next += interval;
00147
00148 return next;
00149 }