mirror of
https://github.com/systemd/systemd.git
synced 2025-03-19 22:50:17 +03:00
Merge 9a0749c82b313d4abd31171beb7cca48bd56f19b into 104587314ff25a5c35390eeb42308f083e1e0488
This commit is contained in:
commit
6927b071c8
@ -8924,6 +8924,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly t RandomizedDelayUSec = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly t RandomizedOffsetUSec = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b FixedRandomDelay = ...;
|
||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||
readonly b Persistent = ...;
|
||||
@ -8953,6 +8955,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
|
||||
|
||||
<!--property RandomizedDelayUSec is not documented!-->
|
||||
|
||||
<!--property RandomizedOffsetUSec is not documented!-->
|
||||
|
||||
<!--property FixedRandomDelay is not documented!-->
|
||||
|
||||
<!--property Persistent is not documented!-->
|
||||
@ -8997,6 +9001,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="RandomizedDelayUSec"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="RandomizedOffsetUSec"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="FixedRandomDelay"/>
|
||||
|
||||
<variablelist class="dbus-property" generated="True" extra-ref="Persistent"/>
|
||||
|
@ -266,13 +266,13 @@
|
||||
|
||||
<listitem><para>Delay the timer by a randomly selected, evenly distributed amount of time between 0
|
||||
and the specified time value. Defaults to 0, indicating that no randomized delay shall be applied.
|
||||
Each timer unit will determine this delay randomly before each iteration, and the delay will simply
|
||||
be added on top of the next determined elapsing time, unless modified with
|
||||
<varname>FixedRandomDelay=</varname>, see below.</para>
|
||||
Each timer unit will determine this delay randomly before each iteration, unless modified with
|
||||
<varname>FixedRandomDelay=</varname>, see below. The delay is added on top of the next determined
|
||||
elapsing time or the service manager's startup time, whichever is later.</para>
|
||||
|
||||
<para>This setting is useful to stretch dispatching of similarly configured timer events over a
|
||||
certain time interval, to prevent them from firing all at the same time, possibly resulting in
|
||||
resource congestion.</para>
|
||||
resource congestion on the local system.</para>
|
||||
|
||||
<para>Note the relation to <varname>AccuracySec=</varname> above: the latter allows the service
|
||||
manager to coalesce timer events within a specified time range in order to minimize wakeups, while
|
||||
@ -292,12 +292,12 @@
|
||||
<varlistentry>
|
||||
<term><varname>FixedRandomDelay=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. When enabled, the randomized offset specified by
|
||||
<varname>RandomizedDelaySec=</varname> is reused for all firings of the same timer. For a given timer
|
||||
unit, the offset depends on the machine ID, user identifier and timer name, which means that it is
|
||||
stable between restarts of the manager. This effectively creates a fixed offset for an individual
|
||||
timer, reducing the jitter in firings of this timer, while still avoiding firing at the same time as
|
||||
other similarly configured timers.</para>
|
||||
<listitem><para>Takes a boolean argument. When enabled, the randomized delay specified by
|
||||
<varname>RandomizedDelaySec=</varname> is chosen deterministically, and remains stable between all
|
||||
firings of the same timer, even if the manager is restarted. The delay is derived from the machine
|
||||
ID, the manager's user identifier, and the timer unit's name. This effectively creates a unique fixed
|
||||
offset for each timer, reducing the jitter in firings of an individual timer while still avoiding
|
||||
firing at the same time as other similarly configured timers.</para>
|
||||
|
||||
<para>This setting has no effect if <varname>RandomizedDelaySec=</varname> is set to 0. Defaults to
|
||||
<option>false</option>.</para>
|
||||
@ -305,6 +305,36 @@
|
||||
<xi:include href="version-info.xml" xpointer="v247"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RandomizedOffsetSec=</varname></term>
|
||||
|
||||
<listitem><para>Offsets the timer by a stable, randomly-selected, and evenly distributed amount of
|
||||
time between 0 and the specified time value. Defaults to 0, indicating that no such offset shall be
|
||||
applied. The offset is chosen deterministically, and is derived the same way as
|
||||
<varname>FixedRandomDelay=</varname>, see above. The offset is added on top of the next determined
|
||||
elapsing time. This setting only has an effect on timers configured with <varname>OnCalendar=</varname>,
|
||||
and it can be combined with <varname>RandomizedDelaySec=</varname>.</para>
|
||||
|
||||
<para>Much like <varname>RandomizedDelaySec=</varname>, this setting is for distributing timer events
|
||||
to prevent them from firing all at once. However, this setting is most useful to prevent resource
|
||||
congestion on a remote service, from a fleet of similarly-configured clients. Unlike
|
||||
<varname>RandomizedDelaySec=</varname>, this setting applies its offset with no regard to manager
|
||||
startup time. This maintains the periodicity of configured <varname>OnCalendar=</varname> events
|
||||
across manager restarts.</para>
|
||||
|
||||
<para>For example, let's say you're running a backup service and have a fleet of laptops that wish
|
||||
to make backups weekly. To distribute load on the backup service, each laptop should randomly pick
|
||||
a weekday to upload its backups. This could be achieved by setting <varname>OnCalendar=</varname> to
|
||||
<literal>weekly</literal>, and then configuring a <varname>RandomizedDelaySec=</varname> of
|
||||
<literal>5 days</literal> with <varname>FixedRandomDelay=</varname> enabled. Let's say that some
|
||||
laptop randomly chooses a delay of 4 days. If this laptop is restarted more often than that, then the
|
||||
timer will never fire: on each fresh boot, the 4 day delay is restarted and will not be finished by
|
||||
the time of the next shutdown. Instead, you should use <varname>RandomizedOffsetSec=</varname>, which
|
||||
will maintain the configured weekly cadence of timer events, even across reboots.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>DeferReactivation=</varname></term>
|
||||
|
||||
|
@ -113,7 +113,8 @@ 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("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_delay_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("RandomizedOffsetUSec", "t", bus_property_get_usec, offsetof(Timer, random_offset_usec), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("FixedRandomDelay", "b", bus_property_get_bool, offsetof(Timer, fixed_random_delay), 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),
|
||||
@ -214,7 +215,10 @@ static int bus_timer_set_transient_property(
|
||||
}
|
||||
|
||||
if (streq(name, "RandomizedDelayUSec"))
|
||||
return bus_set_transient_usec(u, name, &t->random_usec, message, flags, error);
|
||||
return bus_set_transient_usec(u, name, &t->random_delay_usec, message, flags, error);
|
||||
|
||||
if (streq(name, "RandomizedOffsetUSec"))
|
||||
return bus_set_transient_usec(u, name, &t->random_offset_usec, message, flags, error);
|
||||
|
||||
if (streq(name, "FixedRandomDelay"))
|
||||
return bus_set_transient_bool(u, name, &t->fixed_random_delay, message, flags, error);
|
||||
|
@ -578,7 +578,8 @@ Timer.RemainAfterElapse, config_parse_bool,
|
||||
Timer.FixedRandomDelay, config_parse_bool, 0, offsetof(Timer, fixed_random_delay)
|
||||
Timer.DeferReactivation, config_parse_bool, 0, offsetof(Timer, defer_reactivation)
|
||||
Timer.AccuracySec, config_parse_sec, 0, offsetof(Timer, accuracy_usec)
|
||||
Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_usec)
|
||||
Timer.RandomizedDelaySec, config_parse_sec, 0, offsetof(Timer, random_delay_usec)
|
||||
Timer.RandomizedOffsetSec, config_parse_sec, 0, offsetof(Timer, random_offset_usec)
|
||||
Timer.Unit, config_parse_trigger_unit, 0, 0
|
||||
Path.PathExists, config_parse_path_spec, 0, 0
|
||||
Path.PathExistsGlob, config_parse_path_spec, 0, 0
|
||||
|
@ -347,18 +347,18 @@ static void timer_enter_elapsed(Timer *t, bool leave_around) {
|
||||
timer_enter_dead(t, TIMER_SUCCESS);
|
||||
}
|
||||
|
||||
static void add_random(Timer *t, usec_t *v) {
|
||||
static void add_random_delay(Timer *t, usec_t *v) {
|
||||
usec_t add;
|
||||
|
||||
assert(t);
|
||||
assert(v);
|
||||
|
||||
if (t->random_usec == 0)
|
||||
if (t->random_delay_usec == 0)
|
||||
return;
|
||||
if (*v == USEC_INFINITY)
|
||||
return;
|
||||
|
||||
add = (t->fixed_random_delay ? timer_get_fixed_delay_hash(t) : random_u64()) % t->random_usec;
|
||||
add = (t->fixed_random_delay ? timer_get_fixed_delay_hash(t) : random_u64()) % t->random_delay_usec;
|
||||
|
||||
if (*v + add < *v) /* overflow */
|
||||
*v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
|
||||
@ -391,12 +391,19 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
continue;
|
||||
|
||||
if (v->base == TIMER_CALENDAR) {
|
||||
usec_t b, rebased;
|
||||
usec_t b, rebased, random_offset = 0;
|
||||
|
||||
if (t->random_offset_usec != 0)
|
||||
random_offset = timer_get_fixed_delay_hash(t) % t->random_offset_usec;
|
||||
|
||||
/* If DeferReactivation= is enabled, schedule the job based on the last time
|
||||
* the trigger unit entered inactivity. Otherwise, if we know the last time
|
||||
* this was triggered, schedule the job based relative to that. If we don't,
|
||||
* just start from the activation time or realtime. */
|
||||
* just start from the activation time or realtime.
|
||||
*
|
||||
* Unless we have a real last-trigger time, we subtract the random_offset because
|
||||
* any event that elapsed within the last random_offset has actually been delayed
|
||||
* and thus hasn't truly elapsed yet. */
|
||||
|
||||
if (t->defer_reactivation &&
|
||||
dual_timestamp_is_set(&trigger->inactive_enter_timestamp)) {
|
||||
@ -408,14 +415,16 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
} else if (dual_timestamp_is_set(&t->last_trigger))
|
||||
b = t->last_trigger.realtime;
|
||||
else if (dual_timestamp_is_set(&UNIT(t)->inactive_exit_timestamp))
|
||||
b = UNIT(t)->inactive_exit_timestamp.realtime;
|
||||
b = UNIT(t)->inactive_exit_timestamp.realtime - random_offset;
|
||||
else
|
||||
b = ts.realtime;
|
||||
b = ts.realtime - random_offset;
|
||||
|
||||
r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
|
||||
if (r < 0)
|
||||
continue;
|
||||
|
||||
v->next_elapse += random_offset;
|
||||
|
||||
/* To make the delay due to RandomizedDelaySec= work even at boot, if the scheduled
|
||||
* time has already passed, set the time when systemd first started as the scheduled
|
||||
* time. Note that we base this on the monotonic timestamp of the boot, not the
|
||||
@ -505,7 +514,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
if (found_monotonic) {
|
||||
usec_t left;
|
||||
|
||||
add_random(t, &t->next_elapse_monotonic_or_boottime);
|
||||
add_random_delay(t, &t->next_elapse_monotonic_or_boottime);
|
||||
|
||||
left = usec_sub_unsigned(t->next_elapse_monotonic_or_boottime, triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)));
|
||||
log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", FORMAT_TIMESPAN(left, 0));
|
||||
@ -546,7 +555,7 @@ static void timer_enter_waiting(Timer *t, bool time_change) {
|
||||
}
|
||||
|
||||
if (found_realtime) {
|
||||
add_random(t, &t->next_elapse_realtime);
|
||||
add_random_delay(t, &t->next_elapse_realtime);
|
||||
|
||||
log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", FORMAT_TIMESTAMP(t->next_elapse_realtime));
|
||||
|
||||
|
@ -41,7 +41,8 @@ struct Timer {
|
||||
Unit meta;
|
||||
|
||||
usec_t accuracy_usec;
|
||||
usec_t random_usec;
|
||||
usec_t random_delay_usec;
|
||||
usec_t random_offset_usec;
|
||||
|
||||
LIST_HEAD(TimerValue, values);
|
||||
usec_t next_elapse_realtime;
|
||||
|
@ -2044,6 +2044,7 @@ org.freedesktop.systemd1.Timer.OnClockChange
|
||||
org.freedesktop.systemd1.Timer.OnTimezoneChange
|
||||
org.freedesktop.systemd1.Timer.Persistent
|
||||
org.freedesktop.systemd1.Timer.RandomizedDelayUSec
|
||||
org.freedesktop.systemd1.Timer.RandomizedOffsetUSec
|
||||
org.freedesktop.systemd1.Timer.RemainAfterElapse
|
||||
org.freedesktop.systemd1.Timer.Result
|
||||
org.freedesktop.systemd1.Timer.TimersCalendar
|
||||
|
Loading…
x
Reference in New Issue
Block a user