timer.c revision 36697dc0199e25f09b78090fcf5f1cf8a3648ffd
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/***
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen This file is part of systemd.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2010 Lennart Poettering
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is free software; you can redistribute it and/or modify it
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen under the terms of the GNU Lesser General Public License as published by
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen the Free Software Foundation; either version 2.1 of the License, or
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (at your option) any later version.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is distributed in the hope that it will be useful, but
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen WITHOUT ANY WARRANTY; without even the implied warranty of
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Lesser General Public License for more details.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen You should have received a copy of the GNU Lesser General Public License
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen***/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <errno.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "unit.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "unit-name.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "timer.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "dbus-timer.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "special.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "bus-errors.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_DEAD] = UNIT_INACTIVE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_WAITING] = UNIT_ACTIVE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_RUNNING] = UNIT_ACTIVE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_ELAPSED] = UNIT_ACTIVE,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_FAILED] = UNIT_FAILED
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_init(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u->load_state == UNIT_STUB);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->next_elapse_monotonic = (usec_t) -1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->next_elapse_realtime = (usec_t) -1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen watch_init(&t->monotonic_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen watch_init(&t->realtime_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_done(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TimerValue *v;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen while ((v = t->values)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen LIST_REMOVE(TimerValue, value, t->values, v);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (v->calendar_spec)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen calendar_spec_free(v->calendar_spec);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(v);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_unwatch_timer(u, &t->monotonic_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_unwatch_timer(u, &t->realtime_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_ref_unset(&t->unit);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_verify(Timer *t) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT(t)->load_state != UNIT_LOADED)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!t->values) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("%s lacks value setting. Refusing.", UNIT(t)->id);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_add_default_dependencies(Timer *t) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_BASIC_TARGET, NULL, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_load(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u->load_state == UNIT_STUB);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = unit_load_fragment_and_dropin(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (u->load_state == UNIT_LOADED) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!UNIT_DEREF(t->unit)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Unit *x;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = unit_load_related_unit(u, ".service", &x);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_ref_set(&t->unit, x);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(t->unit), true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT(t)->default_dependencies) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = timer_add_default_dependencies(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen return r;
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen }
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen }
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return timer_verify(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_dump(Unit *u, FILE *f, const char *prefix) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TimerValue *v;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fprintf(f,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "%sTimer State: %s\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "%sResult: %s\n"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "%sUnit: %s\n",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen prefix, timer_state_to_string(t->state),
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen prefix, timer_result_to_string(t->result),
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen prefix, UNIT_DEREF(t->unit)->id);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen LIST_FOREACH(value, v, t->values) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (v->base == TIMER_CALENDAR) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *p = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen calendar_spec_to_string(v->calendar_spec, &p);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fprintf(f,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "%s%s: %s\n",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen prefix,
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen timer_base_to_string(v->base),
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen strna(p));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char timespan1[FORMAT_TIMESPAN_MAX];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fprintf(f,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "%s%s: %s\n",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen prefix,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_base_to_string(v->base),
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen strna(format_timespan(timespan1, sizeof(timespan1), v->value)));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_set_state(Timer *t, TimerState state) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TimerState old_state;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen old_state = t->state;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->state = state;
d171ed1c50ba64928b7fb30ee2ae729fdfe0826bThomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (state != TIMER_WAITING) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_unwatch_timer(UNIT(t), &t->realtime_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (state != old_state)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("%s changed %s -> %s",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen UNIT(t)->id,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_state_to_string(old_state),
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen timer_state_to_string(state));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_enter_waiting(Timer *t, bool initial);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_coldplug(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t->state == TIMER_DEAD);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (t->deserialized_state != t->state) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (t->deserialized_state == TIMER_WAITING)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_enter_waiting(t, false);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_set_state(t, t->deserialized_state);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_enter_dead(Timer *t, TimerResult f) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (f != TIMER_SUCCESS)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->result = f;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_enter_waiting(Timer *t, bool initial) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TimerValue *v;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen usec_t base = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dual_timestamp ts;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool found_monotonic = false, found_realtime = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dual_timestamp_get(&ts);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->next_elapse_monotonic = t->next_elapse_realtime = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen LIST_FOREACH(value, v, t->values) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (v->disabled)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (v->base == TIMER_CALENDAR) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = calendar_spec_next_usec(v->calendar_spec, ts.realtime, &v->next_elapse);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!initial && v->next_elapse < ts.realtime) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen v->disabled = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!found_realtime)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->next_elapse_realtime = v->next_elapse;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen found_realtime = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen switch (v->base) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_ACTIVE:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (state_translation_table[t->state] == UNIT_ACTIVE)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen base = UNIT(t)->inactive_exit_timestamp.monotonic;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen base = ts.monotonic;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_BOOT:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* CLOCK_MONOTONIC equals the uptime on Linux */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen base = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_STARTUP:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen base = UNIT(t)->manager->userspace_timestamp.monotonic;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_UNIT_ACTIVE:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic <= 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen base = UNIT_DEREF(t->unit)->inactive_exit_timestamp.monotonic;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_UNIT_INACTIVE:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic <= 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen base = UNIT_DEREF(t->unit)->inactive_enter_timestamp.monotonic;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen default:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_not_reached("Unknown timer base");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen v->next_elapse = base + v->value;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!initial && v->next_elapse < ts.monotonic) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen v->disabled = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!found_monotonic)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->next_elapse_monotonic = v->next_elapse;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->next_elapse_monotonic = MIN(t->next_elapse_monotonic, v->next_elapse);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen found_monotonic = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!found_monotonic && !found_realtime) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("%s: Timer is elapsed.", UNIT(t)->id);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_set_state(t, TIMER_ELAPSED);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (found_monotonic) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char buf[FORMAT_TIMESPAN_MAX];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("%s: Monotonic timer elapses in %s the next time.", UNIT(t)->id, format_timespan(buf, sizeof(buf), t->next_elapse_monotonic - ts.monotonic));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = unit_watch_timer(UNIT(t), CLOCK_MONOTONIC, false, t->next_elapse_monotonic, &t->monotonic_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto fail;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_unwatch_timer(UNIT(t), &t->monotonic_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (found_realtime) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char buf[FORMAT_TIMESTAMP_MAX];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("%s: Realtime timer elapses at %s the next time.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = unit_watch_timer(UNIT(t), CLOCK_REALTIME, false, t->next_elapse_realtime, &t->realtime_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto fail;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_unwatch_timer(UNIT(t), &t->realtime_watch);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_set_state(t, TIMER_WAITING);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenfail:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning("%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_enter_running(Timer *t) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen DBusError error;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dbus_error_init(&error);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Don't start job if we are supposed to go down */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT(t)->job && UNIT(t)->job->type == JOB_STOP)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_DEREF(t->unit), JOB_REPLACE, true, &error, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto fail;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_set_state(t, TIMER_RUNNING);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenfail:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_warning("%s failed to queue unit startup job: %s", UNIT(t)->id, bus_error(&error, r));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen dbus_error_free(&error);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_start(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT_DEREF(t->unit)->load_state != UNIT_LOADED)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOENT;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->result = TIMER_SUCCESS;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_enter_waiting(t, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_stop(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_enter_dead(t, TIMER_SUCCESS);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(f);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fds);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(key);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(value);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fds);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (streq(key, "state")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TimerState state;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen state = timer_state_from_string(value);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (state < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Failed to parse state value %s", value);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->deserialized_state = state;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (streq(key, "result")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TimerResult f;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen f = timer_result_from_string(value);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (f < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Failed to parse result value %s", value);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else if (f != TIMER_SUCCESS)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->result = f;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Unknown serialization key '%s'", key);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic UnitActiveState timer_active_state(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return state_translation_table[TIMER(u)->state];
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic const char *timer_sub_state_to_string(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek return timer_state_to_string(TIMER(u)->state);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmekstatic void timer_timer_event(Unit *u, uint64_t elapsed, Watch *w) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(elapsed == 1);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (t->state != TIMER_WAITING)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("Timer elapsed on %s", u->id);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_enter_running(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenvoid timer_unit_notify(Unit *u, UnitActiveState new_state) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Iterator i;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Unit *k;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (u->type == UNIT_TIMER)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen SET_FOREACH(k, u->dependencies[UNIT_TRIGGERED_BY], i) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TimerValue *v;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (k->type != UNIT_TIMER)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (k->load_state != UNIT_LOADED)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t = TIMER(k);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn /* Reenable all timers that depend on unit state */
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn LIST_FOREACH(value, v, t->values)
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn if (v->base == TIMER_UNIT_ACTIVE ||
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn v->base == TIMER_UNIT_INACTIVE)
805b573fad06b845502e76f3db3a0efa7583149dLukas Nykryn v->disabled = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen switch (t->state) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_WAITING:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_ELAPSED:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Recalculate sleep time */
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek timer_enter_waiting(t, false);
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek break;
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek case TIMER_RUNNING:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (UNIT_IS_INACTIVE_OR_FAILED(new_state)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_debug("%s got notified about unit deactivation.", UNIT(t)->id);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_enter_waiting(t, false);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_DEAD:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case TIMER_FAILED:
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen default:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_not_reached("Unknown timer state");
a2a5291b3f5ab6ed4c92f51d0fd10a03047380d8Zbigniew Jędrzejewski-Szmek }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void timer_reset_failed(Unit *u) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Timer *t = TIMER(u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(t);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (t->state == TIMER_FAILED)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen timer_set_state(t, TIMER_DEAD);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t->result = TIMER_SUCCESS;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic const char* const timer_state_table[_TIMER_STATE_MAX] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_DEAD] = "dead",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_WAITING] = "waiting",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_RUNNING] = "running",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_ELAPSED] = "elapsed",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_FAILED] = "failed"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenDEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic const char* const timer_base_table[_TIMER_BASE_MAX] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_ACTIVE] = "OnActiveSec",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_BOOT] = "OnBootSec",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_STARTUP] = "OnStartupSec",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_CALENDAR] = "OnCalendar"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenDEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic const char* const timer_result_table[_TIMER_RESULT_MAX] = {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_SUCCESS] = "success",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen [TIMER_FAILURE_RESOURCES] = "resources"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenDEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenconst UnitVTable timer_vtable = {
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek .object_size = sizeof(Timer),
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek .sections =
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek "Unit\0"
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek "Timer\0"
b2fadec6048adb3596f2633cb7fe7a49f5937a18Zbigniew Jędrzejewski-Szmek "Install\0",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .init = timer_init,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .done = timer_done,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .load = timer_load,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .coldplug = timer_coldplug,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .dump = timer_dump,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .start = timer_start,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .stop = timer_stop,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .serialize = timer_serialize,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .deserialize_item = timer_deserialize_item,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .active_state = timer_active_state,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .sub_state_to_string = timer_sub_state_to_string,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .timer_event = timer_timer_event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .reset_failed = timer_reset_failed,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .bus_interface = "org.freedesktop.systemd1.Timer",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .bus_message_handler = bus_timer_message_handler,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen .bus_invalidating_properties = bus_timer_invalidating_properties
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen