wvdailyevent.cc

00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2004 Net Integration Technologies, Inc.
00004  *
00005  * A simple class that can trigger an event on a timed basis.
00006  *   a) if given an hour, triggers once per day, on that hour.
00007  *   b) if given a number of times per day, triggers that many times per
00008  *      day, evenly, starting at the hour given in (a).  (Needed to get a
00009  *      Microbackup going every 15 minutes.)  
00010  *
00011  * Presently has a one-hour granularity in the first case, but that can be
00012  * extended one day when someone cares.
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     configure(_first_hour, _num_per_day, _skip_first);
00033 }
00034 
00035 
00036 // Compute the next time this stream should select()
00037 bool WvDailyEvent::pre_select(SelectInfo &si)
00038 {
00039     WvTime next(next_event(), 0);
00040     if (next)
00041         si.msec_timeout = msecdiff(next, wvtime());
00042     return WvStream::pre_select(si);
00043 }
00044 
00045 
00046 // Test to see if the timer has gone off
00047 bool WvDailyEvent::post_select(SelectInfo& si)
00048 {
00049     bool timer_rang = false;
00050     WvTime next(next_event(), 0);
00051     if (next < wvtime())
00052     {
00053         timer_rang = true;
00054         prev = next;
00055     }
00056 
00057     return WvStream::post_select(si) || timer_rang;
00058 }
00059 
00060 
00061 void WvDailyEvent::set_num_per_day(int _num_per_day) 
00062 {
00063     num_per_day = _num_per_day;
00064     if (num_per_day < 0)
00065         num_per_day = 1;
00066 
00067     if (num_per_day > NUM_SECS_IN_DAY)
00068         num_per_day = NUM_SECS_IN_DAY;
00069         
00070     time_t max = num_per_day ? NUM_SECS_IN_DAY/num_per_day : 6*60*60;
00071     if (max > 6*60*60)
00072         max = 6*60*60; // unless that's a very long time, 6 hrs
00073 
00074     // don't start until at least one period has gone by
00075     prev = time(NULL);
00076     not_until = prev + max;
00077 }
00078 
00079 
00080 void WvDailyEvent::configure(int _first_hour, int _num_per_day, bool _skip_first)
00081 {
00082     first_hour = _first_hour;
00083     skip_first = _skip_first;
00084 
00085     // Don't let WvDailyEvents occur more than once a minute. -- use an alarm
00086     // instead
00087     if (_num_per_day > NUM_MINS_IN_DAY)
00088         _num_per_day = NUM_MINS_IN_DAY;
00089 
00090     set_num_per_day(_num_per_day);
00091 }
00092 
00093 // the daily event occurs each day at first_hour on the hour, or at
00094 // some multiple of the interval *after* that hour.
00095 time_t WvDailyEvent::next_event() const
00096 {
00097     if (!num_per_day) // disabled
00098         return 0;
00099 
00100     assert(prev);
00101     
00102     time_t interval = NUM_SECS_IN_DAY/num_per_day;
00103     time_t start = prev + interval;
00104    
00105     // find the time to start counting from (up to 24 hours in the past)
00106     struct tm *tm = localtime(&start);
00107     if (tm->tm_hour < first_hour)
00108     {
00109         start = prev - NUM_SECS_IN_DAY + 1; // this time yesterday
00110         tm = localtime(&start);
00111     }
00112     tm->tm_hour = first_hour; // always start at the given hour
00113     tm->tm_min = tm->tm_sec = 0; // right on the hour
00114     start = mktime(tm); // convert back into a time_t
00115 
00116     // find the next event after prev that's a multiple of 'interval'
00117     // since 'start'
00118     time_t next = prev + interval;
00119     if ((next - start)%interval != 0)
00120         next = start + (next - start)/interval * interval;
00121     
00122     assert(next);
00123     assert(next > 100000);
00124 
00125     while (skip_first && next < not_until)
00126         next += interval;
00127 
00128     return next;
00129 }

Generated on Thu May 25 21:51:03 2006 for WvStreams by  doxygen 1.4.6