From 744c7693751830149ae78fdaf95c6c6f99d59f07 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 18 Nov 2015 13:37:30 +0100 Subject: core: add new RandomSec= setting for time units This allows configuration of a random time on top of the elapse events, in order to spread time events in a network evenly across a range. --- src/core/dbus-timer.c | 17 +++++++++++++++++ src/core/load-fragment-gperf.gperf.m4 | 1 + src/core/timer.c | 28 ++++++++++++++++++++++++++++ src/core/timer.h | 1 + 4 files changed, 47 insertions(+) (limited to 'src/core') diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c index 2e6c479c3a..4bee82df07 100644 --- a/src/core/dbus-timer.c +++ b/src/core/dbus-timer.c @@ -180,6 +180,7 @@ const sd_bus_vtable bus_timer_vtable[] = { BUS_PROPERTY_DUAL_TIMESTAMP("LastTriggerUSec", offsetof(Timer, last_trigger), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("RandomUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST), @@ -283,6 +284,22 @@ static int bus_timer_set_transient_property( return 1; + } else if (streq(name, "RandomUSec")) { + usec_t u = 0; + + r = sd_bus_message_read(message, "t", &u); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + char time[FORMAT_TIMESPAN_MAX]; + + t->random_usec = u; + unit_write_drop_in_private_format(UNIT(t), mode, name, "RandomSec=%s\n", format_timespan(time, sizeof(time), u, USEC_PER_MSEC)); + } + + return 1; + } else if (streq(name, "WakeSystem")) { int b; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 0dbe38d7e5..c64850802e 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -347,6 +347,7 @@ Timer.Persistent, config_parse_bool, 0, Timer.WakeSystem, config_parse_bool, 0, offsetof(Timer, wake_system) Timer.RemainAfterElapse, config_parse_bool, 0, offsetof(Timer, remain_after_elapse) Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec) +Timer.RandomSec, config_parse_sec, 0, offsetof(Timer, random_usec) Timer.Unit, config_parse_trigger_unit, 0, 0 m4_dnl Path.PathExists, config_parse_path_spec, 0, 0 diff --git a/src/core/timer.c b/src/core/timer.c index 0587452cfb..6b0f8e8616 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -27,6 +27,7 @@ #include "dbus-timer.h" #include "fs-util.h" #include "parse-util.h" +#include "random-util.h" #include "special.h" #include "string-table.h" #include "string-util.h" @@ -330,6 +331,28 @@ static usec_t monotonic_to_boottime(usec_t t) { return 0; } +static void add_random(Timer *t, usec_t *v) { + char s[FORMAT_TIMESPAN_MAX]; + usec_t add; + + assert(t); + assert(*v); + + if (t->random_usec == 0) + return; + if (*v == USEC_INFINITY) + return; + + add = random_u64() % t->random_usec; + + if (*v + add < *v) /* overflow */ + *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */ + else + *v += add; + + log_unit_info(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); +} + static void timer_enter_waiting(Timer *t, bool initial) { bool found_monotonic = false, found_realtime = false; usec_t ts_realtime, ts_monotonic; @@ -452,6 +475,8 @@ static void timer_enter_waiting(Timer *t, bool initial) { char buf[FORMAT_TIMESPAN_MAX]; usec_t left; + add_random(t, &t->next_elapse_monotonic_or_boottime); + left = t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0; log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0)); @@ -486,6 +511,9 @@ static void timer_enter_waiting(Timer *t, bool initial) { if (found_realtime) { char buf[FORMAT_TIMESTAMP_MAX]; + + add_random(t, &t->next_elapse_realtime); + log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime)); if (t->realtime_event_source) { diff --git a/src/core/timer.h b/src/core/timer.h index 6bc9fbed3d..0599f07818 100644 --- a/src/core/timer.h +++ b/src/core/timer.h @@ -58,6 +58,7 @@ struct Timer { Unit meta; usec_t accuracy_usec; + usec_t random_usec; LIST_HEAD(TimerValue, values); usec_t next_elapse_realtime; -- cgit v1.2.3-54-g00ecf