WvStreams
wvdailyevent.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2004 Net Integration Technologies, Inc.
4 *
5 * A simple class that can trigger an event on a timed basis.
6 * a) if given an hour, triggers once per day, on that hour.
7 * b) if given a number of times per day, triggers that many times per
8 * day, evenly, starting at the hour given in (a). (Needed to get a
9 * Microbackup going every 15 minutes.)
10 *
11 * Presently has a one-hour granularity in the first case, but that can be
12 * extended one day when someone cares.
13 *
14 */
15#include "wvdailyevent.h"
16#include "wvstream.h"
17#include "wvtimeutils.h"
18
19#include <time.h>
20
21#ifndef _WIN32
22#include <sys/time.h>
23#include <unistd.h>
24#endif
25
26#define NUM_MINS_IN_DAY (24*60)
27#define NUM_SECS_IN_DAY (60*NUM_MINS_IN_DAY)
28
29WvDailyEvent::WvDailyEvent(int _first_hour, int _num_per_day, bool _skip_first)
30 : prev(time(NULL))
31{
32 need_reset = false;
33 prev = wvstime().tv_sec;
34 configure(_first_hour, _num_per_day, _skip_first);
35}
36
37
38// Compute the next time this stream should select()
40{
42
43 if (num_per_day)
44 {
45 time_t now = wvstime().tv_sec;
46 time_t next = next_event();
47
48 assert(prev);
49 assert(next);
50 assert(prev > 100000);
51 assert(next > 100000);
52
53 //printf("%d %d %d\n", now, next, msecdiff(now, next));
54 if (now < next)
55 si.msec_timeout = msecdiff(now, next);
56 else if (!need_reset)
57 {
58 need_reset = true;
59 prev = next;
60 }
61 }
62 if (need_reset)
63 si.msec_timeout = 0;
64 //printf("%p msd=%d\n", this, ret, si.msec_timeout);
65}
66
67
68// Test to see if the timer has gone off
70{
71 bool timer_rang = false;
72 WvTime next(next_event(), 0);
73 if (next < wvtime())
74 {
75 timer_rang = true;
76 prev = next;
77 }
78
79 return WvStream::post_select(si) || need_reset || timer_rang;
80}
81
82
83void WvDailyEvent::set_num_per_day(int _num_per_day)
84{
85 num_per_day = _num_per_day;
86 if (num_per_day < 0)
87 num_per_day = 1;
88
89 if (num_per_day > NUM_SECS_IN_DAY)
90 num_per_day = NUM_SECS_IN_DAY;
91
92 time_t max = num_per_day ? NUM_SECS_IN_DAY/num_per_day : 6*60*60;
93 if (max > 6*60*60)
94 max = 6*60*60; // unless that's a very long time, 6 hrs
95
96 // don't start until at least one period has gone by
97 prev = wvstime().tv_sec;
98 not_until = prev + max;
99}
100
101
102void WvDailyEvent::configure(int _first_hour, int _num_per_day, bool _skip_first)
103{
104 first_hour = _first_hour;
105 skip_first = _skip_first;
106
107 // Don't let WvDailyEvents occur more than once a minute. -- use an alarm
108 // instead
109 if (_num_per_day > NUM_MINS_IN_DAY)
110 _num_per_day = NUM_MINS_IN_DAY;
111
112 set_num_per_day(_num_per_day);
113}
114
115// the daily event occurs each day at first_hour on the hour, or at
116// some multiple of the interval *after* that hour.
118{
119 if (!num_per_day) // disabled
120 return 0;
121
122 assert(prev);
123
124 time_t interval = NUM_SECS_IN_DAY/num_per_day;
125 time_t start = prev + interval;
126
127 // find the time to start counting from (up to 24 hours in the past)
128 struct tm *tm = localtime(&start);
129 if (tm->tm_hour < first_hour)
130 {
131 start = prev - NUM_SECS_IN_DAY + 1; // this time yesterday
132 tm = localtime(&start);
133 }
134 tm->tm_hour = first_hour; // always start at the given hour
135 tm->tm_min = tm->tm_sec = 0; // right on the hour
136 start = mktime(tm); // convert back into a time_t
137
138 // find the next event after prev that's a multiple of 'interval'
139 // since 'start'
140 time_t next = prev + interval;
141 if ((next - start)%interval != 0)
142 next = start + (next - start)/interval * interval;
143
144 assert(next);
145 assert(next > 100000);
146
147 while (skip_first && next < not_until)
148 next += interval;
149
150 return next;
151}
void set_num_per_day(int _num_per_day)
Set number of times per day the event should occur - ONLY FOR TESTING!
virtual void pre_select(SelectInfo &si)
Munges SelectInfo such that the stream will select when the time is right for the event to occur.
void configure(int _first_hour, int _num_per_day=0, bool _skip_first=true)
Modifies the first hour in which the event should occur and the number of times the event should occu...
virtual bool post_select(SelectInfo &si)
post_select() is called after select(), and returns true if this object is now ready.
time_t next_event() const
return the time when the next event will occur
WvDailyEvent(int _first_hour, int _num_per_day=0, bool _skip_first=true)
Constructs WvDailyEvent.
virtual bool post_select(SelectInfo &si)
post_select() is called after select(), and returns true if this object is now ready.
Definition wvstream.cc:875
virtual void pre_select(SelectInfo &si)
pre_select() sets up for eventually calling select().
Definition wvstream.cc:844
Based on (and interchangeable with) struct timeval.
the data structure used by pre_select()/post_select() and internally by select().