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_or_boottime = USEC_INFINITY;
50 t->next_elapse_realtime = USEC_INFINITY;
51 t->accuracy_usec = u->manager->default_timer_accuracy_usec;
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) {
102 r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, NULL, true);
106 if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) {
107 r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
111 LIST_FOREACH(value, v, t->values) {
112 if (v->base == TIMER_CALENDAR) {
113 r = unit_add_dependency_by_name(UNIT(t), UNIT_AFTER, SPECIAL_TIME_SYNC_TARGET, NULL, true);
121 return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
124 static int timer_setup_persistent(Timer *t) {
132 if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) {
134 r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers");
138 t->stamp_path = strappend("/var/lib/systemd/timers/stamp-", UNIT(t)->id);
142 e = getenv("XDG_DATA_HOME");
144 t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id, NULL);
147 _cleanup_free_ char *h = NULL;
149 r = get_home_dir(&h);
151 log_error("Failed to determine home directory: %s", strerror(-r));
155 t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id, NULL);
165 static int timer_load(Unit *u) {
170 assert(u->load_state == UNIT_STUB);
172 r = unit_load_fragment_and_dropin(u);
176 if (u->load_state == UNIT_LOADED) {
178 if (set_isempty(u->dependencies[UNIT_TRIGGERS])) {
181 r = unit_load_related_unit(u, ".service", &x);
185 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
190 r = timer_setup_persistent(t);
194 if (u->default_dependencies) {
195 r = timer_add_default_dependencies(t);
201 return timer_verify(t);
204 static void timer_dump(Unit *u, FILE *f, const char *prefix) {
205 char buf[FORMAT_TIMESPAN_MAX];
210 trigger = UNIT_TRIGGER(u);
213 "%sTimer State: %s\n"
219 prefix, timer_state_to_string(t->state),
220 prefix, timer_result_to_string(t->result),
221 prefix, trigger ? trigger->id : "n/a",
222 prefix, yes_no(t->persistent),
223 prefix, yes_no(t->wake_system),
224 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1));
226 LIST_FOREACH(value, v, t->values) {
228 if (v->base == TIMER_CALENDAR) {
229 _cleanup_free_ char *p = NULL;
231 calendar_spec_to_string(v->calendar_spec, &p);
236 timer_base_to_string(v->base),
239 char timespan1[FORMAT_TIMESPAN_MAX];
244 timer_base_to_string(v->base),
245 format_timespan(timespan1, sizeof(timespan1), v->value, 0));
250 static void timer_set_state(Timer *t, TimerState state) {
251 TimerState old_state;
254 old_state = t->state;
257 if (state != TIMER_WAITING) {
258 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
259 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
262 if (state != old_state)
263 log_debug_unit(UNIT(t)->id,
264 "%s changed %s -> %s", UNIT(t)->id,
265 timer_state_to_string(old_state),
266 timer_state_to_string(state));
268 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
271 static void timer_enter_waiting(Timer *t, bool initial);
273 static int timer_coldplug(Unit *u) {
277 assert(t->state == TIMER_DEAD);
279 if (t->deserialized_state != t->state) {
281 if (t->deserialized_state == TIMER_WAITING)
282 timer_enter_waiting(t, false);
284 timer_set_state(t, t->deserialized_state);
290 static void timer_enter_dead(Timer *t, TimerResult f) {
293 if (f != TIMER_SUCCESS)
296 timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
299 static usec_t monotonic_to_boottime(usec_t t) {
305 a = now(CLOCK_BOOTTIME);
306 b = now(CLOCK_MONOTONIC);
314 static void timer_enter_waiting(Timer *t, bool initial) {
315 bool found_monotonic = false, found_realtime = false;
316 usec_t ts_realtime, ts_monotonic;
321 /* If we shall wake the system we use the boottime clock
322 * rather than the monotonic clock. */
324 ts_realtime = now(CLOCK_REALTIME);
325 ts_monotonic = now(t->wake_system ? CLOCK_BOOTTIME : CLOCK_MONOTONIC);
326 t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
328 LIST_FOREACH(value, v, t->values) {
333 if (v->base == TIMER_CALENDAR) {
336 /* If we know the last time this was
337 * triggered, schedule the job based relative
338 * to that. If we don't just start from
341 b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts_realtime;
343 r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
348 t->next_elapse_realtime = v->next_elapse;
350 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
352 found_realtime = true;
358 if (state_translation_table[t->state] == UNIT_ACTIVE)
359 base = UNIT(t)->inactive_exit_timestamp.monotonic;
365 /* CLOCK_MONOTONIC equals the uptime on Linux */
370 base = UNIT(t)->manager->userspace_timestamp.monotonic;
373 case TIMER_UNIT_ACTIVE:
375 base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
378 base = t->last_trigger.monotonic;
385 case TIMER_UNIT_INACTIVE:
387 base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
390 base = t->last_trigger.monotonic;
398 assert_not_reached("Unknown timer base");
402 base = monotonic_to_boottime(base);
404 v->next_elapse = base + v->value;
406 if (!initial && v->next_elapse < ts_monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
407 /* This is a one time trigger, disable it now */
412 if (!found_monotonic)
413 t->next_elapse_monotonic_or_boottime = v->next_elapse;
415 t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse);
417 found_monotonic = true;
421 if (!found_monotonic && !found_realtime) {
422 log_debug_unit(UNIT(t)->id, "%s: Timer is elapsed.", UNIT(t)->id);
423 timer_set_state(t, TIMER_ELAPSED);
427 if (found_monotonic) {
428 char buf[FORMAT_TIMESPAN_MAX];
430 log_debug_unit(UNIT(t)->id, "%s: Monotonic timer elapses in %s.",
432 format_timespan(buf, sizeof(buf), t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0, 0));
434 if (t->monotonic_event_source) {
435 r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
439 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
441 r = sd_event_add_time(
442 UNIT(t)->manager->event,
443 &t->monotonic_event_source,
444 t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC,
445 t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
450 } else if (t->monotonic_event_source) {
452 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
457 if (found_realtime) {
458 char buf[FORMAT_TIMESTAMP_MAX];
459 log_debug_unit(UNIT(t)->id, "%s: Realtime timer elapses at %s.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
461 if (t->realtime_event_source) {
462 r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
466 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
468 r = sd_event_add_time(
469 UNIT(t)->manager->event,
470 &t->realtime_event_source,
471 t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME,
472 t->next_elapse_realtime, t->accuracy_usec,
477 } else if (t->realtime_event_source) {
479 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
484 timer_set_state(t, TIMER_WAITING);
488 log_warning_unit(UNIT(t)->id, "%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
489 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
492 static void timer_enter_running(Timer *t) {
493 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
498 /* Don't start job if we are supposed to go down */
499 if (unit_stop_pending(UNIT(t)))
502 r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
503 JOB_REPLACE, true, &error, NULL);
507 dual_timestamp_get(&t->last_trigger);
510 touch_file(t->stamp_path, true, t->last_trigger.realtime, (uid_t) -1, (gid_t) -1, 0);
512 timer_set_state(t, TIMER_RUNNING);
516 log_warning_unit(UNIT(t)->id,
517 "%s failed to queue unit startup job: %s",
518 UNIT(t)->id, bus_error_message(&error, r));
519 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
522 static int timer_start(Unit *u) {
527 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
529 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
532 t->last_trigger = DUAL_TIMESTAMP_NULL;
534 /* Reenable all timers that depend on unit activation time */
535 LIST_FOREACH(value, v, t->values)
536 if (v->base == TIMER_ACTIVE)
542 if (stat(t->stamp_path, &st) >= 0)
543 t->last_trigger.realtime = timespec_load(&st.st_atim);
544 else if (errno == ENOENT)
545 /* The timer has never run before,
546 * make sure a stamp file exists.
548 touch_file(t->stamp_path, true, (usec_t) -1, (uid_t) -1, (gid_t) -1, 0);
551 t->result = TIMER_SUCCESS;
552 timer_enter_waiting(t, true);
556 static int timer_stop(Unit *u) {
560 assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
562 timer_enter_dead(t, TIMER_SUCCESS);
566 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
573 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
574 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
576 if (t->last_trigger.realtime > 0)
577 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
579 if (t->last_trigger.monotonic > 0)
580 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
585 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
594 if (streq(key, "state")) {
597 state = timer_state_from_string(value);
599 log_debug_unit(u->id, "Failed to parse state value %s", value);
601 t->deserialized_state = state;
602 } else if (streq(key, "result")) {
605 f = timer_result_from_string(value);
607 log_debug_unit(u->id, "Failed to parse result value %s", value);
608 else if (f != TIMER_SUCCESS)
610 } else if (streq(key, "last-trigger-realtime")) {
612 r = safe_atou64(value, &t->last_trigger.realtime);
614 log_debug_unit(u->id, "Failed to parse last-trigger-realtime value %s", value);
616 } else if (streq(key, "last-trigger-monotonic")) {
618 r = safe_atou64(value, &t->last_trigger.monotonic);
620 log_debug_unit(u->id, "Failed to parse last-trigger-monotonic value %s", value);
623 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
628 _pure_ static UnitActiveState timer_active_state(Unit *u) {
631 return state_translation_table[TIMER(u)->state];
634 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
637 return timer_state_to_string(TIMER(u)->state);
640 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
641 Timer *t = TIMER(userdata);
645 if (t->state != TIMER_WAITING)
648 log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
649 timer_enter_running(t);
653 static void timer_trigger_notify(Unit *u, Unit *other) {
660 if (other->load_state != UNIT_LOADED)
663 /* Reenable all timers that depend on unit state */
664 LIST_FOREACH(value, v, t->values)
665 if (v->base == TIMER_UNIT_ACTIVE ||
666 v->base == TIMER_UNIT_INACTIVE)
674 /* Recalculate sleep time */
675 timer_enter_waiting(t, false);
680 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
681 log_debug_unit(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
682 timer_enter_waiting(t, false);
691 assert_not_reached("Unknown timer state");
695 static void timer_reset_failed(Unit *u) {
700 if (t->state == TIMER_FAILED)
701 timer_set_state(t, TIMER_DEAD);
703 t->result = TIMER_SUCCESS;
706 static void timer_time_change(Unit *u) {
711 if (t->state != TIMER_WAITING)
714 log_debug_unit(u->id, "%s: time change, recalculating next elapse.", u->id);
715 timer_enter_waiting(t, false);
718 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
719 [TIMER_DEAD] = "dead",
720 [TIMER_WAITING] = "waiting",
721 [TIMER_RUNNING] = "running",
722 [TIMER_ELAPSED] = "elapsed",
723 [TIMER_FAILED] = "failed"
726 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
728 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
729 [TIMER_ACTIVE] = "OnActiveSec",
730 [TIMER_BOOT] = "OnBootSec",
731 [TIMER_STARTUP] = "OnStartupSec",
732 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
733 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
734 [TIMER_CALENDAR] = "OnCalendar"
737 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
739 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
740 [TIMER_SUCCESS] = "success",
741 [TIMER_FAILURE_RESOURCES] = "resources"
744 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
746 const UnitVTable timer_vtable = {
747 .object_size = sizeof(Timer),
758 .coldplug = timer_coldplug,
762 .start = timer_start,
765 .serialize = timer_serialize,
766 .deserialize_item = timer_deserialize_item,
768 .active_state = timer_active_state,
769 .sub_state_to_string = timer_sub_state_to_string,
771 .trigger_notify = timer_trigger_notify,
773 .reset_failed = timer_reset_failed,
774 .time_change = timer_time_change,
776 .bus_interface = "org.freedesktop.systemd1.Timer",
777 .bus_vtable = bus_timer_vtable,