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/", 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 _cleanup_close_ int fd = -1;
502 mkdir_parents_label(t->stamp_path, 0755);
504 /* Update the file atime + mtime, if we can */
505 fd = open(t->stamp_path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
507 struct timespec ts[2];
509 timespec_store(&ts[0], t->last_trigger.realtime);
516 timer_set_state(t, TIMER_RUNNING);
520 log_warning_unit(UNIT(t)->id,
521 "%s failed to queue unit startup job: %s",
522 UNIT(t)->id, bus_error_message(&error, r));
523 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
526 static int timer_start(Unit *u) {
530 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
532 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
535 t->last_trigger = DUAL_TIMESTAMP_NULL;
540 if (stat(t->stamp_path, &st) >= 0)
541 t->last_trigger.realtime = timespec_load(&st.st_atim);
544 t->result = TIMER_SUCCESS;
545 timer_enter_waiting(t, true);
549 static int timer_stop(Unit *u) {
553 assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
555 timer_enter_dead(t, TIMER_SUCCESS);
559 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
566 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
567 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
569 if (t->last_trigger.realtime > 0)
570 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
572 if (t->last_trigger.monotonic > 0)
573 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
578 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
587 if (streq(key, "state")) {
590 state = timer_state_from_string(value);
592 log_debug_unit(u->id, "Failed to parse state value %s", value);
594 t->deserialized_state = state;
595 } else if (streq(key, "result")) {
598 f = timer_result_from_string(value);
600 log_debug_unit(u->id, "Failed to parse result value %s", value);
601 else if (f != TIMER_SUCCESS)
603 } else if (streq(key, "last-trigger-realtime")) {
605 r = safe_atou64(value, &t->last_trigger.realtime);
607 log_debug_unit(u->id, "Failed to parse last-trigger-realtime value %s", value);
609 } else if (streq(key, "last-trigger-monotonic")) {
611 r = safe_atou64(value, &t->last_trigger.monotonic);
613 log_debug_unit(u->id, "Failed to parse last-trigger-monotonic value %s", value);
616 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
621 _pure_ static UnitActiveState timer_active_state(Unit *u) {
624 return state_translation_table[TIMER(u)->state];
627 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
630 return timer_state_to_string(TIMER(u)->state);
633 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
634 Timer *t = TIMER(userdata);
638 if (t->state != TIMER_WAITING)
641 log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
642 timer_enter_running(t);
646 static void timer_trigger_notify(Unit *u, Unit *other) {
653 if (other->load_state != UNIT_LOADED)
656 /* Reenable all timers that depend on unit state */
657 LIST_FOREACH(value, v, t->values)
658 if (v->base == TIMER_UNIT_ACTIVE ||
659 v->base == TIMER_UNIT_INACTIVE)
667 /* Recalculate sleep time */
668 timer_enter_waiting(t, false);
673 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
674 log_debug_unit(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
675 timer_enter_waiting(t, false);
684 assert_not_reached("Unknown timer state");
688 static void timer_reset_failed(Unit *u) {
693 if (t->state == TIMER_FAILED)
694 timer_set_state(t, TIMER_DEAD);
696 t->result = TIMER_SUCCESS;
699 static void timer_time_change(Unit *u) {
704 if (t->state != TIMER_WAITING)
707 log_debug_unit(u->id, "%s: time change, recalculating next elapse.", u->id);
708 timer_enter_waiting(t, false);
711 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
712 [TIMER_DEAD] = "dead",
713 [TIMER_WAITING] = "waiting",
714 [TIMER_RUNNING] = "running",
715 [TIMER_ELAPSED] = "elapsed",
716 [TIMER_FAILED] = "failed"
719 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
721 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
722 [TIMER_ACTIVE] = "OnActiveSec",
723 [TIMER_BOOT] = "OnBootSec",
724 [TIMER_STARTUP] = "OnStartupSec",
725 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
726 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
727 [TIMER_CALENDAR] = "OnCalendar"
730 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
732 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
733 [TIMER_SUCCESS] = "success",
734 [TIMER_FAILURE_RESOURCES] = "resources"
737 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
739 const UnitVTable timer_vtable = {
740 .object_size = sizeof(Timer),
751 .coldplug = timer_coldplug,
755 .start = timer_start,
758 .serialize = timer_serialize,
759 .deserialize_item = timer_deserialize_item,
761 .active_state = timer_active_state,
762 .sub_state_to_string = timer_sub_state_to_string,
764 .trigger_notify = timer_trigger_notify,
766 .reset_failed = timer_reset_failed,
767 .time_change = timer_time_change,
769 .bus_interface = "org.freedesktop.systemd1.Timer",
770 .bus_vtable = bus_timer_vtable,