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 strna(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) {
526 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
528 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
531 t->last_trigger = DUAL_TIMESTAMP_NULL;
536 if (stat(t->stamp_path, &st) >= 0)
537 t->last_trigger.realtime = timespec_load(&st.st_atim);
538 else if (errno == ENOENT)
539 /* The timer has never run before,
540 * make sure a stamp file exists.
542 touch_file(t->stamp_path, true, (usec_t) -1, (uid_t) -1, (gid_t) -1, 0);
545 t->result = TIMER_SUCCESS;
546 timer_enter_waiting(t, true);
550 static int timer_stop(Unit *u) {
554 assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
556 timer_enter_dead(t, TIMER_SUCCESS);
560 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
567 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
568 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
570 if (t->last_trigger.realtime > 0)
571 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
573 if (t->last_trigger.monotonic > 0)
574 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
579 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
588 if (streq(key, "state")) {
591 state = timer_state_from_string(value);
593 log_debug_unit(u->id, "Failed to parse state value %s", value);
595 t->deserialized_state = state;
596 } else if (streq(key, "result")) {
599 f = timer_result_from_string(value);
601 log_debug_unit(u->id, "Failed to parse result value %s", value);
602 else if (f != TIMER_SUCCESS)
604 } else if (streq(key, "last-trigger-realtime")) {
606 r = safe_atou64(value, &t->last_trigger.realtime);
608 log_debug_unit(u->id, "Failed to parse last-trigger-realtime value %s", value);
610 } else if (streq(key, "last-trigger-monotonic")) {
612 r = safe_atou64(value, &t->last_trigger.monotonic);
614 log_debug_unit(u->id, "Failed to parse last-trigger-monotonic value %s", value);
617 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
622 _pure_ static UnitActiveState timer_active_state(Unit *u) {
625 return state_translation_table[TIMER(u)->state];
628 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
631 return timer_state_to_string(TIMER(u)->state);
634 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
635 Timer *t = TIMER(userdata);
639 if (t->state != TIMER_WAITING)
642 log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
643 timer_enter_running(t);
647 static void timer_trigger_notify(Unit *u, Unit *other) {
654 if (other->load_state != UNIT_LOADED)
657 /* Reenable all timers that depend on unit state */
658 LIST_FOREACH(value, v, t->values)
659 if (v->base == TIMER_UNIT_ACTIVE ||
660 v->base == TIMER_UNIT_INACTIVE)
668 /* Recalculate sleep time */
669 timer_enter_waiting(t, false);
674 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
675 log_debug_unit(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
676 timer_enter_waiting(t, false);
685 assert_not_reached("Unknown timer state");
689 static void timer_reset_failed(Unit *u) {
694 if (t->state == TIMER_FAILED)
695 timer_set_state(t, TIMER_DEAD);
697 t->result = TIMER_SUCCESS;
700 static void timer_time_change(Unit *u) {
705 if (t->state != TIMER_WAITING)
708 log_debug_unit(u->id, "%s: time change, recalculating next elapse.", u->id);
709 timer_enter_waiting(t, false);
712 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
713 [TIMER_DEAD] = "dead",
714 [TIMER_WAITING] = "waiting",
715 [TIMER_RUNNING] = "running",
716 [TIMER_ELAPSED] = "elapsed",
717 [TIMER_FAILED] = "failed"
720 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
722 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
723 [TIMER_ACTIVE] = "OnActiveSec",
724 [TIMER_BOOT] = "OnBootSec",
725 [TIMER_STARTUP] = "OnStartupSec",
726 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
727 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
728 [TIMER_CALENDAR] = "OnCalendar"
731 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
733 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
734 [TIMER_SUCCESS] = "success",
735 [TIMER_FAILURE_RESOURCES] = "resources"
738 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
740 const UnitVTable timer_vtable = {
741 .object_size = sizeof(Timer),
752 .coldplug = timer_coldplug,
756 .start = timer_start,
759 .serialize = timer_serialize,
760 .deserialize_item = timer_deserialize_item,
762 .active_state = timer_active_state,
763 .sub_state_to_string = timer_sub_state_to_string,
765 .trigger_notify = timer_trigger_notify,
767 .reset_failed = timer_reset_failed,
768 .time_change = timer_time_change,
770 .bus_interface = "org.freedesktop.systemd1.Timer",
771 .bus_vtable = bus_timer_vtable,