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_unit_error(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 return log_error_errno(r, "Failed to determine home directory: %m");
153 t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id, NULL);
163 static int timer_load(Unit *u) {
168 assert(u->load_state == UNIT_STUB);
170 r = unit_load_fragment_and_dropin(u);
174 if (u->load_state == UNIT_LOADED) {
176 if (set_isempty(u->dependencies[UNIT_TRIGGERS])) {
179 r = unit_load_related_unit(u, ".service", &x);
183 r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
188 r = timer_setup_persistent(t);
192 if (u->default_dependencies) {
193 r = timer_add_default_dependencies(t);
199 return timer_verify(t);
202 static void timer_dump(Unit *u, FILE *f, const char *prefix) {
203 char buf[FORMAT_TIMESPAN_MAX];
208 trigger = UNIT_TRIGGER(u);
211 "%sTimer State: %s\n"
217 prefix, timer_state_to_string(t->state),
218 prefix, timer_result_to_string(t->result),
219 prefix, trigger ? trigger->id : "n/a",
220 prefix, yes_no(t->persistent),
221 prefix, yes_no(t->wake_system),
222 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1));
224 LIST_FOREACH(value, v, t->values) {
226 if (v->base == TIMER_CALENDAR) {
227 _cleanup_free_ char *p = NULL;
229 calendar_spec_to_string(v->calendar_spec, &p);
234 timer_base_to_string(v->base),
237 char timespan1[FORMAT_TIMESPAN_MAX];
242 timer_base_to_string(v->base),
243 format_timespan(timespan1, sizeof(timespan1), v->value, 0));
248 static void timer_set_state(Timer *t, TimerState state) {
249 TimerState old_state;
252 old_state = t->state;
255 if (state != TIMER_WAITING) {
256 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
257 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
260 if (state != old_state)
261 log_unit_debug(UNIT(t)->id,
262 "%s changed %s -> %s", UNIT(t)->id,
263 timer_state_to_string(old_state),
264 timer_state_to_string(state));
266 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
269 static void timer_enter_waiting(Timer *t, bool initial);
271 static int timer_coldplug(Unit *u) {
275 assert(t->state == TIMER_DEAD);
277 if (t->deserialized_state != t->state) {
279 if (t->deserialized_state == TIMER_WAITING)
280 timer_enter_waiting(t, false);
282 timer_set_state(t, t->deserialized_state);
288 static void timer_enter_dead(Timer *t, TimerResult f) {
291 if (f != TIMER_SUCCESS)
294 timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
297 static usec_t monotonic_to_boottime(usec_t t) {
303 a = now(CLOCK_BOOTTIME);
304 b = now(CLOCK_MONOTONIC);
312 static void timer_enter_waiting(Timer *t, bool initial) {
313 bool found_monotonic = false, found_realtime = false;
314 usec_t ts_realtime, ts_monotonic;
319 /* If we shall wake the system we use the boottime clock
320 * rather than the monotonic clock. */
322 ts_realtime = now(CLOCK_REALTIME);
323 ts_monotonic = now(t->wake_system ? CLOCK_BOOTTIME : CLOCK_MONOTONIC);
324 t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
326 LIST_FOREACH(value, v, t->values) {
331 if (v->base == TIMER_CALENDAR) {
334 /* If we know the last time this was
335 * triggered, schedule the job based relative
336 * to that. If we don't just start from
339 b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts_realtime;
341 r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
346 t->next_elapse_realtime = v->next_elapse;
348 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
350 found_realtime = true;
356 if (state_translation_table[t->state] == UNIT_ACTIVE)
357 base = UNIT(t)->inactive_exit_timestamp.monotonic;
363 /* CLOCK_MONOTONIC equals the uptime on Linux */
368 base = UNIT(t)->manager->userspace_timestamp.monotonic;
371 case TIMER_UNIT_ACTIVE:
373 base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
376 base = t->last_trigger.monotonic;
383 case TIMER_UNIT_INACTIVE:
385 base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
388 base = t->last_trigger.monotonic;
396 assert_not_reached("Unknown timer base");
400 base = monotonic_to_boottime(base);
402 v->next_elapse = base + v->value;
404 if (!initial && v->next_elapse < ts_monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
405 /* This is a one time trigger, disable it now */
410 if (!found_monotonic)
411 t->next_elapse_monotonic_or_boottime = v->next_elapse;
413 t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse);
415 found_monotonic = true;
419 if (!found_monotonic && !found_realtime) {
420 log_unit_debug(UNIT(t)->id, "%s: Timer is elapsed.", UNIT(t)->id);
421 timer_set_state(t, TIMER_ELAPSED);
425 if (found_monotonic) {
426 char buf[FORMAT_TIMESPAN_MAX];
428 log_unit_debug(UNIT(t)->id, "%s: Monotonic timer elapses in %s.",
430 format_timespan(buf, sizeof(buf), t->next_elapse_monotonic_or_boottime > ts_monotonic ? t->next_elapse_monotonic_or_boottime - ts_monotonic : 0, 0));
432 if (t->monotonic_event_source) {
433 r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
437 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
439 r = sd_event_add_time(
440 UNIT(t)->manager->event,
441 &t->monotonic_event_source,
442 t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC,
443 t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
448 } else if (t->monotonic_event_source) {
450 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
455 if (found_realtime) {
456 char buf[FORMAT_TIMESTAMP_MAX];
457 log_unit_debug(UNIT(t)->id, "%s: Realtime timer elapses at %s.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
459 if (t->realtime_event_source) {
460 r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
464 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
466 r = sd_event_add_time(
467 UNIT(t)->manager->event,
468 &t->realtime_event_source,
469 t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME,
470 t->next_elapse_realtime, t->accuracy_usec,
475 } else if (t->realtime_event_source) {
477 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
482 timer_set_state(t, TIMER_WAITING);
486 log_unit_warning_errno(UNIT(t)->id, r, "%s failed to enter waiting state: %m", UNIT(t)->id);
487 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
490 static void timer_enter_running(Timer *t) {
491 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
496 /* Don't start job if we are supposed to go down */
497 if (unit_stop_pending(UNIT(t)))
500 r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
501 JOB_REPLACE, true, &error, NULL);
505 dual_timestamp_get(&t->last_trigger);
508 touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, 0);
510 timer_set_state(t, TIMER_RUNNING);
514 log_unit_warning(UNIT(t)->id,
515 "%s failed to queue unit startup job: %s",
516 UNIT(t)->id, bus_error_message(&error, r));
517 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
520 static int timer_start(Unit *u) {
525 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
527 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
530 t->last_trigger = DUAL_TIMESTAMP_NULL;
532 /* Reenable all timers that depend on unit activation time */
533 LIST_FOREACH(value, v, t->values)
534 if (v->base == TIMER_ACTIVE)
540 if (stat(t->stamp_path, &st) >= 0)
541 t->last_trigger.realtime = timespec_load(&st.st_atim);
542 else if (errno == ENOENT)
543 /* The timer has never run before,
544 * make sure a stamp file exists.
546 touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, 0);
549 t->result = TIMER_SUCCESS;
550 timer_enter_waiting(t, true);
554 static int timer_stop(Unit *u) {
558 assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
560 timer_enter_dead(t, TIMER_SUCCESS);
564 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
571 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
572 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
574 if (t->last_trigger.realtime > 0)
575 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
577 if (t->last_trigger.monotonic > 0)
578 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
583 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
592 if (streq(key, "state")) {
595 state = timer_state_from_string(value);
597 log_unit_debug(u->id, "Failed to parse state value %s", value);
599 t->deserialized_state = state;
600 } else if (streq(key, "result")) {
603 f = timer_result_from_string(value);
605 log_unit_debug(u->id, "Failed to parse result value %s", value);
606 else if (f != TIMER_SUCCESS)
608 } else if (streq(key, "last-trigger-realtime")) {
610 r = safe_atou64(value, &t->last_trigger.realtime);
612 log_unit_debug(u->id, "Failed to parse last-trigger-realtime value %s", value);
614 } else if (streq(key, "last-trigger-monotonic")) {
616 r = safe_atou64(value, &t->last_trigger.monotonic);
618 log_unit_debug(u->id, "Failed to parse last-trigger-monotonic value %s", value);
621 log_unit_debug(u->id, "Unknown serialization key '%s'", key);
626 _pure_ static UnitActiveState timer_active_state(Unit *u) {
629 return state_translation_table[TIMER(u)->state];
632 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
635 return timer_state_to_string(TIMER(u)->state);
638 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
639 Timer *t = TIMER(userdata);
643 if (t->state != TIMER_WAITING)
646 log_unit_debug(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
647 timer_enter_running(t);
651 static void timer_trigger_notify(Unit *u, Unit *other) {
658 if (other->load_state != UNIT_LOADED)
661 /* Reenable all timers that depend on unit state */
662 LIST_FOREACH(value, v, t->values)
663 if (v->base == TIMER_UNIT_ACTIVE ||
664 v->base == TIMER_UNIT_INACTIVE)
672 /* Recalculate sleep time */
673 timer_enter_waiting(t, false);
678 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
679 log_unit_debug(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
680 timer_enter_waiting(t, false);
689 assert_not_reached("Unknown timer state");
693 static void timer_reset_failed(Unit *u) {
698 if (t->state == TIMER_FAILED)
699 timer_set_state(t, TIMER_DEAD);
701 t->result = TIMER_SUCCESS;
704 static void timer_time_change(Unit *u) {
709 if (t->state != TIMER_WAITING)
712 log_unit_debug(u->id, "%s: time change, recalculating next elapse.", u->id);
713 timer_enter_waiting(t, false);
716 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
717 [TIMER_DEAD] = "dead",
718 [TIMER_WAITING] = "waiting",
719 [TIMER_RUNNING] = "running",
720 [TIMER_ELAPSED] = "elapsed",
721 [TIMER_FAILED] = "failed"
724 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
726 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
727 [TIMER_ACTIVE] = "OnActiveSec",
728 [TIMER_BOOT] = "OnBootSec",
729 [TIMER_STARTUP] = "OnStartupSec",
730 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
731 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
732 [TIMER_CALENDAR] = "OnCalendar"
735 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
737 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
738 [TIMER_SUCCESS] = "success",
739 [TIMER_FAILURE_RESOURCES] = "resources"
742 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
744 const UnitVTable timer_vtable = {
745 .object_size = sizeof(Timer),
751 .private_section = "Timer",
757 .coldplug = timer_coldplug,
761 .start = timer_start,
764 .serialize = timer_serialize,
765 .deserialize_item = timer_deserialize_item,
767 .active_state = timer_active_state,
768 .sub_state_to_string = timer_sub_state_to_string,
770 .trigger_notify = timer_trigger_notify,
772 .reset_failed = timer_reset_failed,
773 .time_change = timer_time_change,
775 .bus_interface = "org.freedesktop.systemd1.Timer",
776 .bus_vtable = bus_timer_vtable,
777 .bus_set_property = bus_timer_set_property,
779 .can_transient = true,