chiark / gitweb /
dbus: properly serialize calendar timer data
authorLennart Poettering <lennart@poettering.net>
Wed, 9 Jan 2013 23:54:46 +0000 (00:54 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 9 Jan 2013 23:56:32 +0000 (00:56 +0100)
As it turns out the bus properties for timer units wre really broken,
so let's clean this up for good and properly add calendar timer
serialization. We really should get that right before finalizing the
bus API documentation in the wiki...

src/core/dbus-timer.c
src/core/timer.c
src/core/timer.h
src/shared/time-util.c

index b22fcb59341953333f83ec3a906190c230bfc440..75add815196168c00da42399873dd5a4e311bf51 100644 (file)
 #define BUS_TIMER_INTERFACE                                             \
         " <interface name=\"org.freedesktop.systemd1.Timer\">\n"        \
         "  <property name=\"Unit\" type=\"s\" access=\"read\"/>\n"      \
-        "  <property name=\"Timers\" type=\"a(stt)\" access=\"read\"/>\n" \
-        "  <property name=\"NextElapseUSec\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"TimersMonotonic\" type=\"a(stt)\" access=\"read\"/>\n" \
+        "  <property name=\"TimersCalendar\" type=\"a(sst)\" access=\"read\"/>\n" \
+        "  <property name=\"NextElapseUSecRealtime\" type=\"t\" access=\"read\"/>\n" \
+        "  <property name=\"NextElapseUSecMonotonic\" type=\"t\" access=\"read\"/>\n" \
         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
         " </interface>\n"
 
 const char bus_timer_interface[] _introspect_("Timer") = BUS_TIMER_INTERFACE;
 
 const char bus_timer_invalidating_properties[] =
-        "Timers\0"
-        "NextElapseUSec\0"
+        "TimersMonotonic\0"
+        "TimersRealtime\0"
+        "NextElapseUSecRealtime\0"
+        "NextElapseUSecMonotonic\0"
         "Result\0";
 
-static int bus_timer_append_timers(DBusMessageIter *i, const char *property, void *data) {
+static int bus_timer_append_monotonic_timers(DBusMessageIter *i, const char *property, void *data) {
         Timer *p = data;
         DBusMessageIter sub, sub2;
         TimerValue *k;
@@ -74,23 +78,20 @@ static int bus_timer_append_timers(DBusMessageIter *i, const char *property, voi
                 size_t l;
                 bool b;
 
-                t = timer_base_to_string(k->base);
+                if (k->base == TIMER_CALENDAR)
+                        continue;
 
-                if (endswith(t, "Sec")) {
+                t = timer_base_to_string(k->base);
+                assert(endswith(t, "Sec"));
 
-                        /* s/Sec/USec/ */
-                        l = strlen(t);
-                        buf = new(char, l+2);
-                        if (!buf)
-                                return -ENOMEM;
+                /* s/Sec/USec/ */
+                l = strlen(t);
+                buf = new(char, l+2);
+                if (!buf)
+                        return -ENOMEM;
 
-                        memcpy(buf, t, l-3);
-                        memcpy(buf+l-3, "USec", 5);
-                } else {
-                        buf = strdup(t);
-                        if (!buf)
-                                return -ENOMEM;
-                }
+                memcpy(buf, t, l-3);
+                memcpy(buf+l-3, "USec", 5);
 
                 b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
                         dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
@@ -108,6 +109,48 @@ static int bus_timer_append_timers(DBusMessageIter *i, const char *property, voi
         return 0;
 }
 
+static int bus_timer_append_calendar_timers(DBusMessageIter *i, const char *property, void *data) {
+        Timer *p = data;
+        DBusMessageIter sub, sub2;
+        TimerValue *k;
+
+        assert(i);
+        assert(property);
+        assert(p);
+
+        if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sst)", &sub))
+                return -ENOMEM;
+
+        LIST_FOREACH(value, k, p->values) {
+                _cleanup_free_ char *buf = NULL;
+                const char *t;
+                bool b;
+                int j;
+
+                if (k->base != TIMER_CALENDAR)
+                        continue;
+
+                t = timer_base_to_string(k->base);
+                j = calendar_spec_to_string(k->calendar_spec, &buf);
+                if (j < 0)
+                        return j;
+
+                b = dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) &&
+                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &t) &&
+                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &buf) &&
+                        dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &k->next_elapse) &&
+                        dbus_message_iter_close_container(&sub, &sub2);
+
+                if (!b)
+                        return -ENOMEM;
+        }
+
+        if (!dbus_message_iter_close_container(i, &sub))
+                return -ENOMEM;
+
+        return 0;
+}
+
 static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void *data) {
         Unit *u = data;
         Timer *timer = TIMER(u);
@@ -125,11 +168,12 @@ static int bus_timer_append_unit(DBusMessageIter *i, const char *property, void
 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_timer_append_timer_result, timer_result, TimerResult);
 
 static const BusProperty bus_timer_properties[] = {
-        { "Unit",           bus_timer_append_unit,        "s", 0 },
-        { "Timers",         bus_timer_append_timers, "a(stt)", 0 },
-        { "NextElapseUSec", bus_property_append_usec,     "t", offsetof(Timer, next_elapse_monotonic) },
-        { "NextElapseUSecRealtime", bus_property_append_usec, "t", offsetof(Timer, next_elapse_realtime) },
-        { "Result",         bus_timer_append_timer_result,"s", offsetof(Timer, result)      },
+        { "Unit",                    bus_timer_append_unit,             "s",      0 },
+        { "TimersMonotonic",         bus_timer_append_monotonic_timers, "a(stt)", 0 },
+        { "TimersCalendar",          bus_timer_append_calendar_timers,  "a(sst)", 0 },
+        { "NextElapseUSecMonotonic", bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_monotonic) },
+        { "NextElapseUSecRealtime",  bus_property_append_usec,          "t",      offsetof(Timer, next_elapse_realtime) },
+        { "Result",                  bus_timer_append_timer_result,     "s",      offsetof(Timer, result) },
         { NULL, }
 };
 
index 31ef176e7e3d750c8867bc94d96d32063494262c..4453aa0781f5ef64bf14e9609959c7a091688d7a 100644 (file)
@@ -323,7 +323,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
                 log_debug_unit(UNIT(t)->id,
                                "%s: Monotonic timer elapses in %s the next time.",
                                UNIT(t)->id,
-                               format_timespan(buf, sizeof(buf), t->next_elapse_monotonic - ts.monotonic));
+                               format_timespan(buf, sizeof(buf), t->next_elapse_monotonic > ts.monotonic ? t->next_elapse_monotonic - ts.monotonic : 0));
 
                 r = unit_watch_timer(UNIT(t), CLOCK_MONOTONIC, false, t->next_elapse_monotonic, &t->monotonic_watch);
                 if (r < 0)
index 57a514a68c5f7a7dd824afdf018b830949039607..10d3ce11164628a237e11fa845b8785f41cf2c44 100644 (file)
@@ -52,8 +52,8 @@ typedef struct TimerValue {
         bool disabled;
         clockid_t clock_id;
 
-        usec_t value;
-        CalendarSpec *calendar_spec;
+        usec_t value; /* only for monotonic events */
+        CalendarSpec *calendar_spec; /* only for calendar events */
         usec_t next_elapse;
 
         LIST_FIELDS(struct TimerValue, value);
index 4fd8f08984d3c0df608348868a20a17dfbc62cb0..e192d5ef58d712302231575fce57808f7176ef5e 100644 (file)
@@ -230,6 +230,8 @@ char *format_timespan(char *buf, size_t l, usec_t t) {
                 const char *suffix;
                 usec_t usec;
         } table[] = {
+                { "y", USEC_PER_YEAR },
+                { "month", USEC_PER_MONTH },
                 { "w", USEC_PER_WEEK },
                 { "d", USEC_PER_DAY },
                 { "h", USEC_PER_HOUR },