add class for weekly scheduling, intervals still missing
authorGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 28 Jan 2009 00:06:36 +0000 (01:06 +0100)
committerGerd v. Egidy <gerd.von.egidy@intra2net.com>
Wed, 28 Jan 2009 00:06:36 +0000 (01:06 +0100)
src/Makefile.am
src/cron.cpp [new file with mode: 0644]
src/cron.hpp [new file with mode: 0644]
src/timefunc.cpp
src/timefunc.hxx
test/Makefile.am
test/test_cron.cpp [new file with mode: 0644]

index a5a6b2f..b0aaecf 100644 (file)
@@ -4,15 +4,15 @@ INCLUDES = -I$(top_srcdir)/src @LIBGETTEXT_CFLAGS@ @LIBICONV_CFLAGS@ $(all_inclu
 
 # the library search path.
 lib_LTLIBRARIES = libi2ncommon.la
-include_HEADERS = containerfunc.hpp daemonfunc.hpp filefunc.hxx \
+include_HEADERS = containerfunc.hpp cron.hpp daemonfunc.hpp filefunc.hxx \
        i2n_configdata.hpp i2n_configfile.hpp insocketstream.hxx ip_type.hxx ipfunc.hxx \
        log_macros.hpp logfunc.hpp logread.hxx oftmpstream.hxx pidfile.hpp pipestream.hxx \
        pointer_func.hpp signalfunc.hpp source_track_basics.hpp stringfunc.hxx timefunc.hxx \
        tracefunc.hpp userfunc.hpp
-libi2ncommon_la_SOURCES = containerfunc.cpp daemonfunc.cpp filefunc.cpp \
-       i2n_configfile.cpp ipfunc.cpp logfunc.cpp logread.cpp oftmpstream.cpp pidfile.cpp \
-       pointer_func.cpp signalfunc.cpp source_track_basics.cpp stringfunc.cpp timefunc.cpp \
-       tracefunc.cpp userfunc.cpp
+libi2ncommon_la_SOURCES = containerfunc.cpp cron.cpp daemonfunc.cpp \
+       filefunc.cpp i2n_configfile.cpp ipfunc.cpp logfunc.cpp logread.cpp oftmpstream.cpp \
+       pidfile.cpp pointer_func.cpp signalfunc.cpp source_track_basics.cpp stringfunc.cpp \
+       timefunc.cpp tracefunc.cpp userfunc.cpp
 
 # Note:  If you specify a:b:c as the version in the next line,
 #  the library that is made has version (a-c).c.b.  In this
diff --git a/src/cron.cpp b/src/cron.cpp
new file mode 100644 (file)
index 0000000..f3103bf
--- /dev/null
@@ -0,0 +1,83 @@
+
+/** @file
+ * @brief repeating time-points and intervals 
+ *
+ * @copyright Copyright &copy; 2009 by Intra2net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ *
+ */
+#include <time.h>
+
+#include <stdexcept>
+
+#include <cron.hpp>
+
+bool WeekCron::is_sane()
+{
+    if (begin < 0 || begin > 86399)
+        return false;
+
+    if (every != -1)
+    {
+        if (end < 0 || end > 86399 ||
+            every < 0 || every > 86399 ||
+            begin > end)
+            return false;
+    }
+
+    return true;
+}
+
+time_t WeekCron::get_next_run(time_t calc_from)
+{
+    if (!calc_from)
+        calc_from=time(NULL);
+
+    if (!is_sane())
+        throw std::runtime_error("illegal cron value");
+
+    if (calc_from <= 86400)
+        throw std::runtime_error("WeekCron doesn't work for times near 0");
+
+    if (week.none_set())
+        return 0;
+
+    if (every == -1)
+    {
+        // point in time
+        return get_next_point(calc_from);
+    }
+    else
+    {
+        // interval
+
+        // TODO
+    }
+}
+
+time_t WeekCron::get_next_point(time_t calc_from)
+{
+    struct tm ft;
+    localtime_r(&calc_from,&ft);
+
+    // take care of the weekday
+    ft.tm_mday+=week.days_till_set(static_cast<WEEK::WEEKDAY>(ft.tm_wday));
+
+    ft.tm_hour=0;
+    ft.tm_min=0;
+    ft.tm_sec=begin;
+
+    time_t target=mktime(&ft);
+
+    // todays schedule could already been through
+    if (target < calc_from)
+    {
+        ft.tm_mday++;
+        target=mktime(&ft);
+    }
+
+    return target;
+}
+
+
diff --git a/src/cron.hpp b/src/cron.hpp
new file mode 100644 (file)
index 0000000..26e67f4
--- /dev/null
@@ -0,0 +1,52 @@
+/** @file
+ * @brief repeating time-points and intervals 
+ *
+ * @copyright Copyright &copy; 2009 by Intra2net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ *
+ */
+
+#ifndef __CRON_HPP
+#define __CRON_HPP
+
+#include <time.h>
+
+#include <timefunc.hxx>
+
+/**
+    @brief time-points and intervals repeating each week
+    @note begin and end are given in seconds since start of the day
+*/
+class WeekCron
+{
+    private:
+
+        int begin;
+        int end;
+        int every;
+        WEEK week;
+
+        time_t get_next_point(time_t calc_from=0);
+
+    public:
+
+        WeekCron(void)
+            : begin(0), end(0), every(-1), week()
+            { }
+
+        WeekCron(const std::string& daystring, int _begin)
+            : begin(_begin), end(0), every(-1), week(daystring)
+            { }
+
+        WeekCron(const std::string& daystring, int _begin, int _end, int _every)
+            : begin(_begin), end(_end), every(_every), week(daystring)
+            { }
+
+        bool is_sane();
+
+        time_t get_next_run(time_t calc_from=0);
+
+};
+
+#endif
index a9bc8df..f66e61b 100644 (file)
@@ -183,6 +183,31 @@ void WEEK::set(const std::string& daystring)
     }
 }
 
+/**
+    @brief returns the number of days till the next weekday which is set
+    @param start weekday to start checking
+    @note returns 0 if the start-day is set
+*/
+int WEEK::days_till_set(WEEKDAY start)
+{
+    if (none_set())
+        return -1;
+
+    for (unsigned int days=0; days < 8; days++)
+    {
+        unsigned int check=start+days;
+        if (check > 6)
+            check-=7;
+        if (is_set(static_cast<WEEKDAY>(check)))
+            return days;
+    }
+
+    throw logic_error("can't find next weekday");
+
+    // fake
+    return -1;
+}
+
 std::string WEEK::get_daystring() const
 {
     ostringstream out;
index 9ceb753..8467af6 100644 (file)
@@ -75,6 +75,8 @@ class WEEK
         bool none_set() const
             { return days.none(); }
 
+        int days_till_set(WEEKDAY day);
+
         std::string get_daystring() const;
         std::string get_displaystring() const;
         std::string get_netfilterstring() const;
index 0cc3379..31d151d 100644 (file)
@@ -2,8 +2,8 @@ INCLUDES = -I$(top_srcdir)/configlib -I$(top_srcdir)/src @CPPUNIT_CFLAGS@
 METASOURCES = AUTO
 check_PROGRAMS =  test
 test_SOURCES = ip_range.cpp stringfunc.cpp test.cpp test_containerfunc.cpp \
-       test_filefunc.cpp test_global_config.cpp test_logging.cpp test_pidfile.cpp \
-       test_timefunc.cpp
+       test_cron.cpp test_filefunc.cpp test_global_config.cpp test_logging.cpp \
+       test_pidfile.cpp test_timefunc.cpp
 test_LDADD = $(top_builddir)/src/libi2ncommon.la \
        $(top_builddir)/configlib/libi2ncommon_config.la @CPPUNIT_LIBS@
 
diff --git a/test/test_cron.cpp b/test/test_cron.cpp
new file mode 100644 (file)
index 0000000..ca83ba0
--- /dev/null
@@ -0,0 +1,70 @@
+/** @file
+ * @brief unit test for cron functions.
+ *
+ * @copyright Copyright &copy; 2009 by Intra2net AG
+ * @license commercial
+ * @contact info@intra2net.com
+ *
+ */
+
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/ui/text/TestRunner.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <time.h>
+#include <stdlib.h>
+
+#include <cron.hpp>
+
+using namespace std;
+using namespace CppUnit;
+
+class TestCronFunc : public TestFixture
+{
+    CPPUNIT_TEST_SUITE(TestCronFunc);
+
+    CPPUNIT_TEST(NotYetToday);
+    CPPUNIT_TEST(LaterToday);
+    CPPUNIT_TEST(Tomorrow);
+    CPPUNIT_TEST(NextWeek);
+
+    CPPUNIT_TEST_SUITE_END();
+
+public:
+
+    void setUp()
+    {
+        // our check-values are set for Germany
+        setenv("TZ",":Europe/Berlin",1);
+    }
+
+    void tearDown()
+    { }
+
+    void NotYetToday()
+    {
+        WeekCron cron("2345",3600);
+        CPPUNIT_ASSERT_EQUAL( 1233100800, static_cast<int>(cron.get_next_run(1233099657)));
+    }
+
+    void LaterToday()
+    {
+        WeekCron cron("2345",3600);
+        CPPUNIT_ASSERT_EQUAL( 1233187200, static_cast<int>(cron.get_next_run(1233100801)));
+    }
+
+    void Tomorrow()
+    {
+        WeekCron cron("45",3600);
+        CPPUNIT_ASSERT_EQUAL( 1233187200, static_cast<int>(cron.get_next_run(1233099657)));
+    }
+
+    void NextWeek()
+    {
+        WeekCron cron("1",3600);
+        CPPUNIT_ASSERT_EQUAL( 1233532800, static_cast<int>(cron.get_next_run(1233099657)));
+    }
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TestCronFunc);