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 = (usec_t) -1;
50 t->next_elapse_realtime = (usec_t) -1;
51 t->accuracy_usec = USEC_PER_MINUTE;
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"
207 prefix, timer_state_to_string(t->state),
208 prefix, timer_result_to_string(t->result),
209 prefix, trigger ? trigger->id : "n/a",
210 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1));
212 LIST_FOREACH(value, v, t->values) {
214 if (v->base == TIMER_CALENDAR) {
215 _cleanup_free_ char *p = NULL;
217 calendar_spec_to_string(v->calendar_spec, &p);
222 timer_base_to_string(v->base),
225 char timespan1[FORMAT_TIMESPAN_MAX];
230 timer_base_to_string(v->base),
231 strna(format_timespan(timespan1, sizeof(timespan1), v->value, 0)));
236 static void timer_set_state(Timer *t, TimerState state) {
237 TimerState old_state;
240 old_state = t->state;
243 if (state != TIMER_WAITING) {
244 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
245 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
248 if (state != old_state)
249 log_debug_unit(UNIT(t)->id,
250 "%s changed %s -> %s", UNIT(t)->id,
251 timer_state_to_string(old_state),
252 timer_state_to_string(state));
254 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
257 static void timer_enter_waiting(Timer *t, bool initial);
259 static int timer_coldplug(Unit *u) {
263 assert(t->state == TIMER_DEAD);
265 if (t->deserialized_state != t->state) {
267 if (t->deserialized_state == TIMER_WAITING)
268 timer_enter_waiting(t, false);
270 timer_set_state(t, t->deserialized_state);
276 static void timer_enter_dead(Timer *t, TimerResult f) {
279 if (f != TIMER_SUCCESS)
282 timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
285 static void timer_enter_waiting(Timer *t, bool initial) {
289 bool found_monotonic = false, found_realtime = false;
292 dual_timestamp_get(&ts);
293 t->next_elapse_monotonic = t->next_elapse_realtime = 0;
295 LIST_FOREACH(value, v, t->values) {
300 if (v->base == TIMER_CALENDAR) {
303 /* If we know the last time this was
304 * triggered, schedule the job based relative
305 * to that. If we don't just start from
308 b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts.realtime;
310 r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
315 t->next_elapse_realtime = v->next_elapse;
317 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
319 found_realtime = true;
325 if (state_translation_table[t->state] == UNIT_ACTIVE)
326 base = UNIT(t)->inactive_exit_timestamp.monotonic;
332 /* CLOCK_MONOTONIC equals the uptime on Linux */
337 base = UNIT(t)->manager->userspace_timestamp.monotonic;
340 case TIMER_UNIT_ACTIVE:
342 base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
345 base = t->last_trigger.monotonic;
352 case TIMER_UNIT_INACTIVE:
354 base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
357 base = t->last_trigger.monotonic;
365 assert_not_reached("Unknown timer base");
368 v->next_elapse = base + v->value;
370 if (!initial && v->next_elapse < ts.monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
371 /* This is a one time trigger, disable it now */
376 if (!found_monotonic)
377 t->next_elapse_monotonic = v->next_elapse;
379 t->next_elapse_monotonic = MIN(t->next_elapse_monotonic, v->next_elapse);
381 found_monotonic = true;
385 if (!found_monotonic && !found_realtime) {
386 log_debug_unit(UNIT(t)->id, "%s: Timer is elapsed.", UNIT(t)->id);
387 timer_set_state(t, TIMER_ELAPSED);
391 if (found_monotonic) {
392 char buf[FORMAT_TIMESPAN_MAX];
393 log_debug_unit(UNIT(t)->id, "%s: Monotonic timer elapses in %s.", UNIT(t)->id, format_timespan(buf, sizeof(buf), t->next_elapse_monotonic > ts.monotonic ? t->next_elapse_monotonic - ts.monotonic : 0, 0));
395 if (t->monotonic_event_source) {
396 r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic);
400 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
402 r = sd_event_add_time(
403 UNIT(t)->manager->event,
404 &t->monotonic_event_source,
406 t->next_elapse_monotonic, t->accuracy_usec,
411 } else if (t->monotonic_event_source) {
413 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
418 if (found_realtime) {
419 char buf[FORMAT_TIMESTAMP_MAX];
420 log_debug_unit(UNIT(t)->id, "%s: Realtime timer elapses at %s.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
422 if (t->realtime_event_source) {
423 r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
427 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
429 r = sd_event_add_time(
430 UNIT(t)->manager->event,
431 &t->realtime_event_source,
433 t->next_elapse_realtime, t->accuracy_usec,
438 } else if (t->realtime_event_source) {
440 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
445 timer_set_state(t, TIMER_WAITING);
449 log_warning_unit(UNIT(t)->id, "%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
450 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
453 static void timer_enter_running(Timer *t) {
454 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
459 /* Don't start job if we are supposed to go down */
460 if (unit_stop_pending(UNIT(t)))
463 r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
464 JOB_REPLACE, true, &error, NULL);
468 dual_timestamp_get(&t->last_trigger);
471 _cleanup_close_ int fd = -1;
473 mkdir_parents_label(t->stamp_path, 0755);
475 /* Update the file atime + mtime, if we can */
476 fd = open(t->stamp_path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
478 struct timespec ts[2];
480 timespec_store(&ts[0], t->last_trigger.realtime);
487 timer_set_state(t, TIMER_RUNNING);
491 log_warning_unit(UNIT(t)->id,
492 "%s failed to queue unit startup job: %s",
493 UNIT(t)->id, bus_error_message(&error, r));
494 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
497 static int timer_start(Unit *u) {
501 assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
503 if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
506 t->last_trigger = DUAL_TIMESTAMP_NULL;
511 if (stat(t->stamp_path, &st) >= 0)
512 t->last_trigger.realtime = timespec_load(&st.st_atim);
515 t->result = TIMER_SUCCESS;
516 timer_enter_waiting(t, true);
520 static int timer_stop(Unit *u) {
524 assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
526 timer_enter_dead(t, TIMER_SUCCESS);
530 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
537 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
538 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
540 if (t->last_trigger.realtime > 0)
541 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
543 if (t->last_trigger.monotonic > 0)
544 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
549 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
558 if (streq(key, "state")) {
561 state = timer_state_from_string(value);
563 log_debug_unit(u->id, "Failed to parse state value %s", value);
565 t->deserialized_state = state;
566 } else if (streq(key, "result")) {
569 f = timer_result_from_string(value);
571 log_debug_unit(u->id, "Failed to parse result value %s", value);
572 else if (f != TIMER_SUCCESS)
574 } else if (streq(key, "last-trigger-realtime")) {
576 r = safe_atou64(value, &t->last_trigger.realtime);
578 log_debug_unit(u->id, "Failed to parse last-trigger-realtime value %s", value);
580 } else if (streq(key, "last-trigger-monotonic")) {
582 r = safe_atou64(value, &t->last_trigger.monotonic);
584 log_debug_unit(u->id, "Failed to parse last-trigger-monotonic value %s", value);
587 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
592 _pure_ static UnitActiveState timer_active_state(Unit *u) {
595 return state_translation_table[TIMER(u)->state];
598 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
601 return timer_state_to_string(TIMER(u)->state);
604 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
605 Timer *t = TIMER(userdata);
609 if (t->state != TIMER_WAITING)
612 log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
613 timer_enter_running(t);
617 static void timer_trigger_notify(Unit *u, Unit *other) {
624 if (other->load_state != UNIT_LOADED)
627 /* Reenable all timers that depend on unit state */
628 LIST_FOREACH(value, v, t->values)
629 if (v->base == TIMER_UNIT_ACTIVE ||
630 v->base == TIMER_UNIT_INACTIVE)
638 /* Recalculate sleep time */
639 timer_enter_waiting(t, false);
644 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
645 log_debug_unit(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
646 timer_enter_waiting(t, false);
655 assert_not_reached("Unknown timer state");
659 static void timer_reset_failed(Unit *u) {
664 if (t->state == TIMER_FAILED)
665 timer_set_state(t, TIMER_DEAD);
667 t->result = TIMER_SUCCESS;
670 static void timer_time_change(Unit *u) {
675 if (t->state != TIMER_WAITING)
678 log_debug_unit(u->id, "%s: time change, recalculating next elapse.", u->id);
679 timer_enter_waiting(t, false);
682 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
683 [TIMER_DEAD] = "dead",
684 [TIMER_WAITING] = "waiting",
685 [TIMER_RUNNING] = "running",
686 [TIMER_ELAPSED] = "elapsed",
687 [TIMER_FAILED] = "failed"
690 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
692 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
693 [TIMER_ACTIVE] = "OnActiveSec",
694 [TIMER_BOOT] = "OnBootSec",
695 [TIMER_STARTUP] = "OnStartupSec",
696 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
697 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
698 [TIMER_CALENDAR] = "OnCalendar"
701 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
703 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
704 [TIMER_SUCCESS] = "success",
705 [TIMER_FAILURE_RESOURCES] = "resources"
708 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
710 const UnitVTable timer_vtable = {
711 .object_size = sizeof(Timer),
722 .coldplug = timer_coldplug,
726 .start = timer_start,
729 .serialize = timer_serialize,
730 .deserialize_item = timer_deserialize_item,
732 .active_state = timer_active_state,
733 .sub_state_to_string = timer_sub_state_to_string,
735 .trigger_notify = timer_trigger_notify,
737 .reset_failed = timer_reset_failed,
738 .time_change = timer_time_change,
740 .bus_interface = "org.freedesktop.systemd1.Timer",
741 .bus_vtable = bus_timer_vtable,