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_t) -1;
50 t->next_elapse_realtime = (usec_t) -1;
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) {
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/stamp-", 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"
209 prefix, timer_state_to_string(t->state),
210 prefix, timer_result_to_string(t->result),
211 prefix, trigger ? trigger->id : "n/a",
212 prefix, yes_no(t->persistent),
213 prefix, yes_no(t->wake_system),
214 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1));
216 LIST_FOREACH(value, v, t->values) {
218 if (v->base == TIMER_CALENDAR) {
219 _cleanup_free_ char *p = NULL;
221 calendar_spec_to_string(v->calendar_spec, &p);
226 timer_base_to_string(v->base),
229 char timespan1[FORMAT_TIMESPAN_MAX];
234 timer_base_to_string(v->base),
235 strna(format_timespan(timespan1, sizeof(timespan1), v->value, 0)));
240 static void timer_set_state(Timer *t, TimerState state) {
241 TimerState old_state;
244 old_state = t->state;
247 if (state != TIMER_WAITING) {
248 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
249 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
252 if (state != old_state)
253 log_debug_unit(UNIT(t)->id,
254 "%s changed %s -> %s", UNIT(t)->id,
255 timer_state_to_string(old_state),
256 timer_state_to_string(state));
258 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
261 static void timer_enter_waiting(Timer *t, bool initial);
263 static int timer_coldplug(Unit *u) {
267 assert(t->state == TIMER_DEAD);
269 if (t->deserialized_state != t->state) {
271 if (t->deserialized_state == TIMER_WAITING)
272 timer_enter_waiting(t, false);
274 timer_set_state(t, t->deserialized_state);
280 static void timer_enter_dead(Timer *t, TimerResult f) {
283 if (f != TIMER_SUCCESS)
286 timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
289 static usec_t monotonic_to_boottime(usec_t t) {
295 a = now(CLOCK_BOOTTIME);
296 b = now(CLOCK_MONOTONIC);
304 static void timer_enter_waiting(Timer *t, bool initial) {
305 bool found_monotonic = false, found_realtime = false;
306 usec_t ts_realtime, ts_monotonic;
311 /* If we shall wake the system we use the boottime clock
312 * rather than the monotonic clock. */
314 ts_realtime = now(CLOCK_REALTIME);
315 ts_monotonic = now(t->wake_system ? CLOCK_BOOTTIME : CLOCK_MONOTONIC);
316 t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
318 LIST_FOREACH(value, v, t->values) {
323 if (v->base == TIMER_CALENDAR) {
326 /* If we know the last time this was
327 * triggered, schedule the job based relative
328 * to that. If we don't just start from
331 b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts_realtime;
333 r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
338 t->next_elapse_realtime = v->next_elapse;
340 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
342 found_realtime = true;
348 if (state_translation_table[t->state] == UNIT_ACTIVE)
349 base = UNIT(t)->inactive_exit_timestamp.monotonic;
355 /* CLOCK_MONOTONIC equals the uptime on Linux */
360 base = UNIT(t)->manager->userspace_timestamp.monotonic;
363 case TIMER_UNIT_ACTIVE:
365 base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
368 base = t->last_trigger.monotonic;
375 case TIMER_UNIT_INACTIVE:
377 base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
380 base = t->last_trigger.monotonic;
388 assert_not_reached("Unknown timer base");
392 base = monotonic_to_boottime(base);
394 v->next_elapse = base + v->value;
396 if (!initial && v->next_elapse < ts_monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
397 /* This is a one time trigger, disable it now */
402 if (!found_monotonic)
403 t->next_elapse_monotonic_or_boottime = v->next_elapse;
405 t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse);
407 found_monotonic = true;
411 if (!found_monotonic && !found_realtime) {
412 log_debug_unit(UNIT(t)->id, "%s: Timer is elapsed.", UNIT(t)->id);
413 timer_set_state(t, TIMER_ELAPSED);
417 if (found_monotonic) {
418 char buf[FORMAT_TIMESPAN_MAX];
420 log_debug_unit(UNIT(t)->id, "%s: Monotonic timer elapses in %s.",
422 format_timespan(buf, sizeof(buf), t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0, 0));
424 if (t->monotonic_event_source) {
425 r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
429 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
431 r = sd_event_add_time(
432 UNIT(t)->manager->event,
433 &t->monotonic_event_source,
434 t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC,
435 t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
440 } else if (t->monotonic_event_source) {
442 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
447 if (found_realtime) {
448 char buf[FORMAT_TIMESTAMP_MAX];
449 log_debug_unit(UNIT(t)->id, "%s: Realtime timer elapses at %s.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
451 if (t->realtime_event_source) {
452 r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
456 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
458 r = sd_event_add_time(
459 UNIT(t)->manager->event,
460 &t->realtime_event_source,
461 t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME,
462 t->next_elapse_realtime, t->accuracy_usec,
467 } else if (t->realtime_event_source) {
469 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
474 timer_set_state(t, TIMER_WAITING);
478 log_warning_unit(UNIT(t)->id, "%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
479 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
482 static void timer_enter_running(Timer *t) {
483 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
488 /* Don't start job if we are supposed to go down */
489 if (unit_stop_pending(UNIT(t)))
492 r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
493 JOB_REPLACE, true, &error, NULL);
497 dual_timestamp_get(&t->last_trigger);
500 touch_file(t->stamp_path, true, t->last_trigger.realtime, (uid_t) -1, (gid_t) -1, 0);
502 timer_set_state(t, TIMER_RUNNING);
506 log_warning_unit(UNIT(t)->id,
507 "%s failed to queue unit startup job: %s",
508 UNIT(t)->id, bus_error_message(&error, r));
509 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
512 static int timer_start(Unit *u) {
516 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
518 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
521 t->last_trigger = DUAL_TIMESTAMP_NULL;
526 if (stat(t->stamp_path, &st) >= 0)
527 t->last_trigger.realtime = timespec_load(&st.st_atim);
528 else if (errno == ENOENT)
529 /* The timer has never run before,
530 * make sure a stamp file exists.
532 touch_file(t->stamp_path, true, (usec_t) -1, (uid_t) -1, (gid_t) -1, 0);
535 t->result = TIMER_SUCCESS;
536 timer_enter_waiting(t, true);
540 static int timer_stop(Unit *u) {
544 assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
546 timer_enter_dead(t, TIMER_SUCCESS);
550 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
557 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
558 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
560 if (t->last_trigger.realtime > 0)
561 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
563 if (t->last_trigger.monotonic > 0)
564 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
569 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
578 if (streq(key, "state")) {
581 state = timer_state_from_string(value);
583 log_debug_unit(u->id, "Failed to parse state value %s", value);
585 t->deserialized_state = state;
586 } else if (streq(key, "result")) {
589 f = timer_result_from_string(value);
591 log_debug_unit(u->id, "Failed to parse result value %s", value);
592 else if (f != TIMER_SUCCESS)
594 } else if (streq(key, "last-trigger-realtime")) {
596 r = safe_atou64(value, &t->last_trigger.realtime);
598 log_debug_unit(u->id, "Failed to parse last-trigger-realtime value %s", value);
600 } else if (streq(key, "last-trigger-monotonic")) {
602 r = safe_atou64(value, &t->last_trigger.monotonic);
604 log_debug_unit(u->id, "Failed to parse last-trigger-monotonic value %s", value);
607 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
612 _pure_ static UnitActiveState timer_active_state(Unit *u) {
615 return state_translation_table[TIMER(u)->state];
618 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
621 return timer_state_to_string(TIMER(u)->state);
624 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
625 Timer *t = TIMER(userdata);
629 if (t->state != TIMER_WAITING)
632 log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
633 timer_enter_running(t);
637 static void timer_trigger_notify(Unit *u, Unit *other) {
644 if (other->load_state != UNIT_LOADED)
647 /* Reenable all timers that depend on unit state */
648 LIST_FOREACH(value, v, t->values)
649 if (v->base == TIMER_UNIT_ACTIVE ||
650 v->base == TIMER_UNIT_INACTIVE)
658 /* Recalculate sleep time */
659 timer_enter_waiting(t, false);
664 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
665 log_debug_unit(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
666 timer_enter_waiting(t, false);
675 assert_not_reached("Unknown timer state");
679 static void timer_reset_failed(Unit *u) {
684 if (t->state == TIMER_FAILED)
685 timer_set_state(t, TIMER_DEAD);
687 t->result = TIMER_SUCCESS;
690 static void timer_time_change(Unit *u) {
695 if (t->state != TIMER_WAITING)
698 log_debug_unit(u->id, "%s: time change, recalculating next elapse.", u->id);
699 timer_enter_waiting(t, false);
702 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
703 [TIMER_DEAD] = "dead",
704 [TIMER_WAITING] = "waiting",
705 [TIMER_RUNNING] = "running",
706 [TIMER_ELAPSED] = "elapsed",
707 [TIMER_FAILED] = "failed"
710 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
712 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
713 [TIMER_ACTIVE] = "OnActiveSec",
714 [TIMER_BOOT] = "OnBootSec",
715 [TIMER_STARTUP] = "OnStartupSec",
716 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
717 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
718 [TIMER_CALENDAR] = "OnCalendar"
721 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
723 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
724 [TIMER_SUCCESS] = "success",
725 [TIMER_FAILURE_RESOURCES] = "resources"
728 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
730 const UnitVTable timer_vtable = {
731 .object_size = sizeof(Timer),
742 .coldplug = timer_coldplug,
746 .start = timer_start,
749 .serialize = timer_serialize,
750 .deserialize_item = timer_deserialize_item,
752 .active_state = timer_active_state,
753 .sub_state_to_string = timer_sub_state_to_string,
755 .trigger_notify = timer_trigger_notify,
757 .reset_failed = timer_reset_failed,
758 .time_change = timer_time_change,
760 .bus_interface = "org.freedesktop.systemd1.Timer",
761 .bus_vtable = bus_timer_vtable,