mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-24 21:34:08 +03:00
core: add RemainAfterElapse= setting to timer units
Previously, after a timer unit elapsed we'd leave it around for good, which has the nice benefit that starting a timer that shall trigger at a specific point in time multiple times will only result in one trigger instead of possibly many. With this change a new option RemainAfterElapse= is added. It defaults to "true", to mimic the old behaviour. If set to "false" timer units will be unloaded after they elapsed. This is specifically useful for transient timer units.
This commit is contained in:
parent
df446f9603
commit
3e0c30ac56
@ -243,6 +243,15 @@
|
||||
again after any work that is to be done is finished. Defaults
|
||||
to <varname>false</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>RemainAfterExit=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument. If true, an elapsed
|
||||
timer will stay loaded, and its state remains
|
||||
queriable. Defaults to
|
||||
<varname>yes</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
@ -182,6 +182,7 @@ const sd_bus_vtable bus_timer_vtable[] = {
|
||||
SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_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),
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
@ -283,7 +284,6 @@ static int bus_timer_set_transient_property(
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "WakeSystem")) {
|
||||
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
@ -292,11 +292,24 @@ static int bus_timer_set_transient_property(
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
t->wake_system = b;
|
||||
unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(t->wake_system));
|
||||
unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(b));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "RemainAfterElapse")) {
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (mode != UNIT_CHECK) {
|
||||
t->remain_after_elapse = b;
|
||||
unit_write_drop_in_private_format(UNIT(t), mode, name, "%s=%s\n", name, yes_no(b));
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -344,6 +344,7 @@ Timer.OnUnitActiveSec, config_parse_timer, 0,
|
||||
Timer.OnUnitInactiveSec, config_parse_timer, 0, 0
|
||||
Timer.Persistent, config_parse_bool, 0, offsetof(Timer, persistent)
|
||||
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.Unit, config_parse_trigger_unit, 0, 0
|
||||
m4_dnl
|
||||
|
@ -55,6 +55,7 @@ static void timer_init(Unit *u) {
|
||||
t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
|
||||
t->next_elapse_realtime = USEC_INFINITY;
|
||||
t->accuracy_usec = u->manager->default_timer_accuracy_usec;
|
||||
t->remain_after_elapse = true;
|
||||
}
|
||||
|
||||
void timer_free_values(Timer *t) {
|
||||
@ -217,13 +218,15 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
"%sUnit: %s\n"
|
||||
"%sPersistent: %s\n"
|
||||
"%sWakeSystem: %s\n"
|
||||
"%sAccuracy: %s\n",
|
||||
"%sAccuracy: %s\n"
|
||||
"%sRemainAfterElapse: %s\n",
|
||||
prefix, timer_state_to_string(t->state),
|
||||
prefix, timer_result_to_string(t->result),
|
||||
prefix, trigger ? trigger->id : "n/a",
|
||||
prefix, yes_no(t->persistent),
|
||||
prefix, yes_no(t->wake_system),
|
||||
prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1));
|
||||
prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1),
|
||||
prefix, yes_no(t->remain_after_elapse));
|
||||
|
||||
LIST_FOREACH(value, v, t->values) {
|
||||
|
||||
@ -275,13 +278,13 @@ static int timer_coldplug(Unit *u) {
|
||||
assert(t);
|
||||
assert(t->state == TIMER_DEAD);
|
||||
|
||||
if (t->deserialized_state != t->state) {
|
||||
if (t->deserialized_state == t->state)
|
||||
return 0;
|
||||
|
||||
if (t->deserialized_state == TIMER_WAITING)
|
||||
timer_enter_waiting(t, false);
|
||||
else
|
||||
timer_set_state(t, t->deserialized_state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -295,6 +298,23 @@ static void timer_enter_dead(Timer *t, TimerResult f) {
|
||||
timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
|
||||
}
|
||||
|
||||
static void timer_enter_elapsed(Timer *t, bool leave_around) {
|
||||
assert(t);
|
||||
|
||||
/* If a unit is marked with RemainAfterElapse=yes we leave it
|
||||
* around even after it elapsed once, so that starting it
|
||||
* later again does not necessarily mean immediate
|
||||
* retriggering. We unconditionally leave units with
|
||||
* TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around,
|
||||
* since they might be restarted automatically at any time
|
||||
* later on. */
|
||||
|
||||
if (t->remain_after_elapse || leave_around)
|
||||
timer_set_state(t, TIMER_ELAPSED);
|
||||
else
|
||||
timer_enter_dead(t, TIMER_SUCCESS);
|
||||
}
|
||||
|
||||
static usec_t monotonic_to_boottime(usec_t t) {
|
||||
usec_t a, b;
|
||||
|
||||
@ -314,6 +334,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
|
||||
bool found_monotonic = false, found_realtime = false;
|
||||
usec_t ts_realtime, ts_monotonic;
|
||||
usec_t base = 0;
|
||||
bool leave_around = false;
|
||||
TimerValue *v;
|
||||
int r;
|
||||
|
||||
@ -374,7 +395,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
|
||||
break;
|
||||
|
||||
case TIMER_UNIT_ACTIVE:
|
||||
|
||||
leave_around = true;
|
||||
base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
|
||||
|
||||
if (base <= 0)
|
||||
@ -386,7 +407,7 @@ static void timer_enter_waiting(Timer *t, bool initial) {
|
||||
break;
|
||||
|
||||
case TIMER_UNIT_INACTIVE:
|
||||
|
||||
leave_around = true;
|
||||
base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
|
||||
|
||||
if (base <= 0)
|
||||
@ -423,14 +444,16 @@ static void timer_enter_waiting(Timer *t, bool initial) {
|
||||
|
||||
if (!found_monotonic && !found_realtime) {
|
||||
log_unit_debug(UNIT(t), "Timer is elapsed.");
|
||||
timer_set_state(t, TIMER_ELAPSED);
|
||||
timer_enter_elapsed(t, leave_around);
|
||||
return;
|
||||
}
|
||||
|
||||
if (found_monotonic) {
|
||||
char buf[FORMAT_TIMESPAN_MAX];
|
||||
usec_t left;
|
||||
|
||||
log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0, 0));
|
||||
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));
|
||||
|
||||
if (t->monotonic_event_source) {
|
||||
r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
|
||||
|
@ -73,6 +73,7 @@ struct Timer {
|
||||
|
||||
bool persistent;
|
||||
bool wake_system;
|
||||
bool remain_after_elapse;
|
||||
|
||||
char *stamp_path;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user