1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "unit-name.h"
27 #include "dbus-timer.h"
30 #include "bus-error.h"
33 static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
34 [TIMER_DEAD] = UNIT_INACTIVE,
35 [TIMER_WAITING] = UNIT_ACTIVE,
36 [TIMER_RUNNING] = UNIT_ACTIVE,
37 [TIMER_ELAPSED] = UNIT_ACTIVE,
38 [TIMER_FAILED] = UNIT_FAILED
41 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
43 static void timer_init(Unit *u) {
47 assert(u->load_state == UNIT_STUB);
49 t->next_elapse_monotonic = (usec_t) -1;
50 t->next_elapse_realtime = (usec_t) -1;
51 t->accuracy_usec = USEC_PER_MINUTE;
54 void timer_free_values(Timer *t) {
59 while ((v = t->values)) {
60 LIST_REMOVE(value, t->values, v);
63 calendar_spec_free(v->calendar_spec);
69 static void timer_done(Unit *u) {
76 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
77 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
82 static int timer_verify(Timer *t) {
85 if (UNIT(t)->load_state != UNIT_LOADED)
89 log_error_unit(UNIT(t)->id, "%s lacks value setting. Refusing.", UNIT(t)->id);
96 static int timer_add_default_dependencies(Timer *t) {
101 r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, NULL, true);
105 if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) {
106 r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
111 return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
114 static int timer_setup_persistent(Timer *t) {
122 if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) {
124 r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers");
128 t->stamp_path = strappend("/var/lib/systemd/timers/stamp-", UNIT(t)->id);
132 e = getenv("XDG_DATA_HOME");
134 t->stamp_path = strjoin(e, "/systemd/timers/", UNIT(t)->id, NULL);
137 _cleanup_free_ char *h = NULL;
139 r = get_home_dir(&h);
141 log_error("Failed to determine home directory: %s", strerror(-r));
145 t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id, NULL);
155 static int timer_load(Unit *u) {
160 assert(u->load_state == UNIT_STUB);
162 r = unit_load_fragment_and_dropin(u);
166 if (u->load_state == UNIT_LOADED) {
168 if (set_isempty(u->dependencies[UNIT_TRIGGERS])) {
171 r = unit_load_related_unit(u, ".service", &x);
175 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
180 r = timer_setup_persistent(t);
184 if (u->default_dependencies) {
185 r = timer_add_default_dependencies(t);
191 return timer_verify(t);
194 static void timer_dump(Unit *u, FILE *f, const char *prefix) {
195 char buf[FORMAT_TIMESPAN_MAX];
200 trigger = UNIT_TRIGGER(u);
203 "%sTimer State: %s\n"
207 prefix, timer_state_to_string(t->state),
208 prefix, timer_result_to_string(t->result),
209 prefix, trigger ? trigger->id : "n/a",
210 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1));
212 LIST_FOREACH(value, v, t->values) {
214 if (v->base == TIMER_CALENDAR) {
215 _cleanup_free_ char *p = NULL;
217 calendar_spec_to_string(v->calendar_spec, &p);
222 timer_base_to_string(v->base),
225 char timespan1[FORMAT_TIMESPAN_MAX];
230 timer_base_to_string(v->base),
231 strna(format_timespan(timespan1, sizeof(timespan1), v->value, 0)));
236 static void timer_set_state(Timer *t, TimerState state) {
237 TimerState old_state;
240 old_state = t->state;
243 if (state != TIMER_WAITING) {
244 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
245 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
248 if (state != old_state)
249 log_debug_unit(UNIT(t)->id,
250 "%s changed %s -> %s", UNIT(t)->id,
251 timer_state_to_string(old_state),
252 timer_state_to_string(state));
254 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
257 static void timer_enter_waiting(Timer *t, bool initial);
259 static int timer_coldplug(Unit *u) {
263 assert(t->state == TIMER_DEAD);
265 if (t->deserialized_state != t->state) {
267 if (t->deserialized_state == TIMER_WAITING)
268 timer_enter_waiting(t, false);
270 timer_set_state(t, t->deserialized_state);
276 static void timer_enter_dead(Timer *t, TimerResult f) {
279 if (f != TIMER_SUCCESS)
282 timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
285 static void timer_enter_waiting(Timer *t, bool initial) {
289 bool found_monotonic = false, found_realtime = false;
292 dual_timestamp_get(&ts);
293 t->next_elapse_monotonic = t->next_elapse_realtime = 0;
295 LIST_FOREACH(value, v, t->values) {
300 if (v->base == TIMER_CALENDAR) {
303 /* If we know the last time this was
304 * triggered, schedule the job based relative
305 * to that. If we don't just start from
308 b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts.realtime;
310 r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
315 t->next_elapse_realtime = v->next_elapse;
317 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
319 found_realtime = true;
325 if (state_translation_table[t->state] == UNIT_ACTIVE)
326 base = UNIT(t)->inactive_exit_timestamp.monotonic;
332 /* CLOCK_MONOTONIC equals the uptime on Linux */
337 base = UNIT(t)->manager->userspace_timestamp.monotonic;
340 case TIMER_UNIT_ACTIVE:
342 base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
345 base = t->last_trigger.monotonic;
352 case TIMER_UNIT_INACTIVE:
354 base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
357 base = t->last_trigger.monotonic;
365 assert_not_reached("Unknown timer base");
368 v->next_elapse = base + v->value;
370 if (!initial && v->next_elapse < ts.monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
371 /* This is a one time trigger, disable it now */
376 if (!found_monotonic)
377 t->next_elapse_monotonic = v->next_elapse;
379 t->next_elapse_monotonic = MIN(t->next_elapse_monotonic, v->next_elapse);
381 found_monotonic = true;
385 if (!found_monotonic && !found_realtime) {
386 log_debug_unit(UNIT(t)->id, "%s: Timer is elapsed.", UNIT(t)->id);
387 timer_set_state(t, TIMER_ELAPSED);
391 if (found_monotonic) {
392 char buf[FORMAT_TIMESPAN_MAX];
393 log_debug_unit(UNIT(t)->id, "%s: Monotonic timer elapses in %s.", UNIT(t)->id, format_timespan(buf, sizeof(buf), t->next_elapse_monotonic > ts.monotonic ? t->next_elapse_monotonic - ts.monotonic : 0, 0));
395 if (t->monotonic_event_source) {
396 r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic);
400 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
402 r = sd_event_add_monotonic(UNIT(t)->manager->event, &t->monotonic_event_source, t->next_elapse_monotonic, t->accuracy_usec, timer_dispatch, t);
406 } else if (t->monotonic_event_source) {
408 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
413 if (found_realtime) {
414 char buf[FORMAT_TIMESTAMP_MAX];
415 log_debug_unit(UNIT(t)->id, "%s: Realtime timer elapses at %s.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
417 if (t->realtime_event_source) {
418 r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
422 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
424 r = sd_event_add_realtime(UNIT(t)->manager->event, &t->realtime_event_source, t->next_elapse_realtime, t->accuracy_usec, timer_dispatch, t);
428 } else if (t->realtime_event_source) {
430 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
435 timer_set_state(t, TIMER_WAITING);
439 log_warning_unit(UNIT(t)->id, "%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
440 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
443 static void timer_enter_running(Timer *t) {
444 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
449 /* Don't start job if we are supposed to go down */
450 if (unit_stop_pending(UNIT(t)))
453 r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
454 JOB_REPLACE, true, &error, NULL);
458 dual_timestamp_get(&t->last_trigger);
461 _cleanup_close_ int fd = -1;
463 mkdir_parents_label(t->stamp_path, 0755);
465 /* Update the file atime + mtime, if we can */
466 fd = open(t->stamp_path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
468 struct timespec ts[2];
470 timespec_store(&ts[0], t->last_trigger.realtime);
477 timer_set_state(t, TIMER_RUNNING);
481 log_warning_unit(UNIT(t)->id,
482 "%s failed to queue unit startup job: %s",
483 UNIT(t)->id, bus_error_message(&error, r));
484 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
487 static int timer_start(Unit *u) {
491 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
493 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
496 t->last_trigger = DUAL_TIMESTAMP_NULL;
501 if (stat(t->stamp_path, &st) >= 0)
502 t->last_trigger.realtime = timespec_load(&st.st_atim);
505 t->result = TIMER_SUCCESS;
506 timer_enter_waiting(t, true);
510 static int timer_stop(Unit *u) {
514 assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
516 timer_enter_dead(t, TIMER_SUCCESS);
520 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
527 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
528 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
530 if (t->last_trigger.realtime > 0)
531 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
533 if (t->last_trigger.monotonic > 0)
534 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
539 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
548 if (streq(key, "state")) {
551 state = timer_state_from_string(value);
553 log_debug_unit(u->id, "Failed to parse state value %s", value);
555 t->deserialized_state = state;
556 } else if (streq(key, "result")) {
559 f = timer_result_from_string(value);
561 log_debug_unit(u->id, "Failed to parse result value %s", value);
562 else if (f != TIMER_SUCCESS)
564 } else if (streq(key, "last-trigger-realtime")) {
566 r = safe_atou64(value, &t->last_trigger.realtime);
568 log_debug_unit(u->id, "Failed to parse last-trigger-realtime value %s", value);
570 } else if (streq(key, "last-trigger-monotonic")) {
572 r = safe_atou64(value, &t->last_trigger.monotonic);
574 log_debug_unit(u->id, "Failed to parse last-trigger-monotonic value %s", value);
577 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
582 _pure_ static UnitActiveState timer_active_state(Unit *u) {
585 return state_translation_table[TIMER(u)->state];
588 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
591 return timer_state_to_string(TIMER(u)->state);
594 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
595 Timer *t = TIMER(userdata);
599 if (t->state != TIMER_WAITING)
602 log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
603 timer_enter_running(t);
607 static void timer_trigger_notify(Unit *u, Unit *other) {
614 if (other->load_state != UNIT_LOADED)
617 /* Reenable all timers that depend on unit state */
618 LIST_FOREACH(value, v, t->values)
619 if (v->base == TIMER_UNIT_ACTIVE ||
620 v->base == TIMER_UNIT_INACTIVE)
628 /* Recalculate sleep time */
629 timer_enter_waiting(t, false);
634 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
635 log_debug_unit(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
636 timer_enter_waiting(t, false);
645 assert_not_reached("Unknown timer state");
649 static void timer_reset_failed(Unit *u) {
654 if (t->state == TIMER_FAILED)
655 timer_set_state(t, TIMER_DEAD);
657 t->result = TIMER_SUCCESS;
660 static void timer_time_change(Unit *u) {
665 if (t->state != TIMER_WAITING)
668 log_debug_unit(u->id, "%s: time change, recalculating next elapse.", u->id);
669 timer_enter_waiting(t, false);
672 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
673 [TIMER_DEAD] = "dead",
674 [TIMER_WAITING] = "waiting",
675 [TIMER_RUNNING] = "running",
676 [TIMER_ELAPSED] = "elapsed",
677 [TIMER_FAILED] = "failed"
680 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
682 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
683 [TIMER_ACTIVE] = "OnActiveSec",
684 [TIMER_BOOT] = "OnBootSec",
685 [TIMER_STARTUP] = "OnStartupSec",
686 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
687 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
688 [TIMER_CALENDAR] = "OnCalendar"
691 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
693 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
694 [TIMER_SUCCESS] = "success",
695 [TIMER_FAILURE_RESOURCES] = "resources"
698 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
700 const UnitVTable timer_vtable = {
701 .object_size = sizeof(Timer),
712 .coldplug = timer_coldplug,
716 .start = timer_start,
719 .serialize = timer_serialize,
720 .deserialize_item = timer_deserialize_item,
722 .active_state = timer_active_state,
723 .sub_state_to_string = timer_sub_state_to_string,
725 .trigger_notify = timer_trigger_notify,
727 .reset_failed = timer_reset_failed,
728 .time_change = timer_time_change,
730 .bus_interface = "org.freedesktop.systemd1.Timer",
731 .bus_vtable = bus_timer_vtable,