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"
32 static const UnitActiveState state_translation_table
[_TIMER_STATE_MAX
] = {
33 [TIMER_DEAD
] = UNIT_INACTIVE
,
34 [TIMER_WAITING
] = UNIT_ACTIVE
,
35 [TIMER_RUNNING
] = UNIT_ACTIVE
,
36 [TIMER_ELAPSED
] = UNIT_ACTIVE
,
37 [TIMER_FAILED
] = UNIT_FAILED
40 static int timer_dispatch(sd_event_source
*s
, uint64_t usec
, void *userdata
);
42 static void timer_init(Unit
*u
) {
46 assert(u
->load_state
== UNIT_STUB
);
48 t
->next_elapse_monotonic_or_boottime
= USEC_INFINITY
;
49 t
->next_elapse_realtime
= USEC_INFINITY
;
50 t
->accuracy_usec
= u
->manager
->default_timer_accuracy_usec
;
53 void timer_free_values(Timer
*t
) {
58 while ((v
= t
->values
)) {
59 LIST_REMOVE(value
, t
->values
, v
);
62 calendar_spec_free(v
->calendar_spec
);
68 static void timer_done(Unit
*u
) {
75 t
->monotonic_event_source
= sd_event_source_unref(t
->monotonic_event_source
);
76 t
->realtime_event_source
= sd_event_source_unref(t
->realtime_event_source
);
81 static int timer_verify(Timer
*t
) {
84 if (UNIT(t
)->load_state
!= UNIT_LOADED
)
88 log_unit_error(UNIT(t
)->id
, "%s lacks value setting. Refusing.", UNIT(t
)->id
);
95 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);
110 LIST_FOREACH(value
, v
, t
->values
) {
111 if (v
->base
== TIMER_CALENDAR
) {
112 r
= unit_add_dependency_by_name(UNIT(t
), UNIT_AFTER
, SPECIAL_TIME_SYNC_TARGET
, NULL
, true);
120 return unit_add_two_dependencies_by_name(UNIT(t
), UNIT_BEFORE
, UNIT_CONFLICTS
, SPECIAL_SHUTDOWN_TARGET
, NULL
, true);
123 static int timer_setup_persistent(Timer
*t
) {
131 if (UNIT(t
)->manager
->running_as
== SYSTEMD_SYSTEM
) {
133 r
= unit_require_mounts_for(UNIT(t
), "/var/lib/systemd/timers");
137 t
->stamp_path
= strappend("/var/lib/systemd/timers/stamp-", UNIT(t
)->id
);
141 e
= getenv("XDG_DATA_HOME");
143 t
->stamp_path
= strjoin(e
, "/systemd/timers/stamp-", UNIT(t
)->id
, NULL
);
146 _cleanup_free_
char *h
= NULL
;
148 r
= get_home_dir(&h
);
150 return log_error_errno(r
, "Failed to determine home directory: %m");
152 t
->stamp_path
= strjoin(h
, "/.local/share/systemd/timers/stamp-", UNIT(t
)->id
, NULL
);
162 static int timer_load(Unit
*u
) {
167 assert(u
->load_state
== UNIT_STUB
);
169 r
= unit_load_fragment_and_dropin(u
);
173 if (u
->load_state
== UNIT_LOADED
) {
175 if (set_isempty(u
->dependencies
[UNIT_TRIGGERS
])) {
178 r
= unit_load_related_unit(u
, ".service", &x
);
182 r
= unit_add_two_dependencies(u
, UNIT_BEFORE
, UNIT_TRIGGERS
, x
, true);
187 r
= timer_setup_persistent(t
);
191 if (u
->default_dependencies
) {
192 r
= timer_add_default_dependencies(t
);
198 return timer_verify(t
);
201 static void timer_dump(Unit
*u
, FILE *f
, const char *prefix
) {
202 char buf
[FORMAT_TIMESPAN_MAX
];
207 trigger
= UNIT_TRIGGER(u
);
210 "%sTimer State: %s\n"
216 prefix
, timer_state_to_string(t
->state
),
217 prefix
, timer_result_to_string(t
->result
),
218 prefix
, trigger
? trigger
->id
: "n/a",
219 prefix
, yes_no(t
->persistent
),
220 prefix
, yes_no(t
->wake_system
),
221 prefix
, format_timespan(buf
, sizeof(buf
), t
->accuracy_usec
, 1));
223 LIST_FOREACH(value
, v
, t
->values
) {
225 if (v
->base
== TIMER_CALENDAR
) {
226 _cleanup_free_
char *p
= NULL
;
228 calendar_spec_to_string(v
->calendar_spec
, &p
);
233 timer_base_to_string(v
->base
),
236 char timespan1
[FORMAT_TIMESPAN_MAX
];
241 timer_base_to_string(v
->base
),
242 format_timespan(timespan1
, sizeof(timespan1
), v
->value
, 0));
247 static void timer_set_state(Timer
*t
, TimerState state
) {
248 TimerState old_state
;
251 old_state
= t
->state
;
254 if (state
!= TIMER_WAITING
) {
255 t
->monotonic_event_source
= sd_event_source_unref(t
->monotonic_event_source
);
256 t
->realtime_event_source
= sd_event_source_unref(t
->realtime_event_source
);
259 if (state
!= old_state
)
260 log_unit_debug(UNIT(t
)->id
,
261 "%s changed %s -> %s", UNIT(t
)->id
,
262 timer_state_to_string(old_state
),
263 timer_state_to_string(state
));
265 unit_notify(UNIT(t
), state_translation_table
[old_state
], state_translation_table
[state
], true);
268 static void timer_enter_waiting(Timer
*t
, bool initial
);
270 static int timer_coldplug(Unit
*u
) {
274 assert(t
->state
== TIMER_DEAD
);
276 if (t
->deserialized_state
!= t
->state
) {
278 if (t
->deserialized_state
== TIMER_WAITING
)
279 timer_enter_waiting(t
, false);
281 timer_set_state(t
, t
->deserialized_state
);
287 static void timer_enter_dead(Timer
*t
, TimerResult f
) {
290 if (f
!= TIMER_SUCCESS
)
293 timer_set_state(t
, t
->result
!= TIMER_SUCCESS
? TIMER_FAILED
: TIMER_DEAD
);
296 static usec_t
monotonic_to_boottime(usec_t t
) {
302 a
= now(CLOCK_BOOTTIME
);
303 b
= now(CLOCK_MONOTONIC
);
311 static void timer_enter_waiting(Timer
*t
, bool initial
) {
312 bool found_monotonic
= false, found_realtime
= false;
313 usec_t ts_realtime
, ts_monotonic
;
318 /* If we shall wake the system we use the boottime clock
319 * rather than the monotonic clock. */
321 ts_realtime
= now(CLOCK_REALTIME
);
322 ts_monotonic
= now(t
->wake_system
? CLOCK_BOOTTIME
: CLOCK_MONOTONIC
);
323 t
->next_elapse_monotonic_or_boottime
= t
->next_elapse_realtime
= 0;
325 LIST_FOREACH(value
, v
, t
->values
) {
330 if (v
->base
== TIMER_CALENDAR
) {
333 /* If we know the last time this was
334 * triggered, schedule the job based relative
335 * to that. If we don't just start from
338 b
= t
->last_trigger
.realtime
> 0 ? t
->last_trigger
.realtime
: ts_realtime
;
340 r
= calendar_spec_next_usec(v
->calendar_spec
, b
, &v
->next_elapse
);
345 t
->next_elapse_realtime
= v
->next_elapse
;
347 t
->next_elapse_realtime
= MIN(t
->next_elapse_realtime
, v
->next_elapse
);
349 found_realtime
= true;
355 if (state_translation_table
[t
->state
] == UNIT_ACTIVE
)
356 base
= UNIT(t
)->inactive_exit_timestamp
.monotonic
;
362 /* CLOCK_MONOTONIC equals the uptime on Linux */
367 base
= UNIT(t
)->manager
->userspace_timestamp
.monotonic
;
370 case TIMER_UNIT_ACTIVE
:
372 base
= UNIT_TRIGGER(UNIT(t
))->inactive_exit_timestamp
.monotonic
;
375 base
= t
->last_trigger
.monotonic
;
382 case TIMER_UNIT_INACTIVE
:
384 base
= UNIT_TRIGGER(UNIT(t
))->inactive_enter_timestamp
.monotonic
;
387 base
= t
->last_trigger
.monotonic
;
395 assert_not_reached("Unknown timer base");
399 base
= monotonic_to_boottime(base
);
401 v
->next_elapse
= base
+ v
->value
;
403 if (!initial
&& v
->next_elapse
< ts_monotonic
&& IN_SET(v
->base
, TIMER_ACTIVE
, TIMER_BOOT
, TIMER_STARTUP
)) {
404 /* This is a one time trigger, disable it now */
409 if (!found_monotonic
)
410 t
->next_elapse_monotonic_or_boottime
= v
->next_elapse
;
412 t
->next_elapse_monotonic_or_boottime
= MIN(t
->next_elapse_monotonic_or_boottime
, v
->next_elapse
);
414 found_monotonic
= true;
418 if (!found_monotonic
&& !found_realtime
) {
419 log_unit_debug(UNIT(t
)->id
, "%s: Timer is elapsed.", UNIT(t
)->id
);
420 timer_set_state(t
, TIMER_ELAPSED
);
424 if (found_monotonic
) {
425 char buf
[FORMAT_TIMESPAN_MAX
];
427 log_unit_debug(UNIT(t
)->id
, "%s: Monotonic timer elapses in %s.",
429 format_timespan(buf
, sizeof(buf
), t
->next_elapse_monotonic_or_boottime
> ts_monotonic
? t
->next_elapse_monotonic_or_boottime
- ts_monotonic
: 0, 0));
431 if (t
->monotonic_event_source
) {
432 r
= sd_event_source_set_time(t
->monotonic_event_source
, t
->next_elapse_monotonic_or_boottime
);
436 r
= sd_event_source_set_enabled(t
->monotonic_event_source
, SD_EVENT_ONESHOT
);
438 r
= sd_event_add_time(
439 UNIT(t
)->manager
->event
,
440 &t
->monotonic_event_source
,
441 t
->wake_system
? CLOCK_BOOTTIME_ALARM
: CLOCK_MONOTONIC
,
442 t
->next_elapse_monotonic_or_boottime
, t
->accuracy_usec
,
447 (void) sd_event_source_set_description(t
->monotonic_event_source
, "timer-monotonic");
449 } else if (t
->monotonic_event_source
) {
451 r
= sd_event_source_set_enabled(t
->monotonic_event_source
, SD_EVENT_OFF
);
456 if (found_realtime
) {
457 char buf
[FORMAT_TIMESTAMP_MAX
];
458 log_unit_debug(UNIT(t
)->id
, "%s: Realtime timer elapses at %s.", UNIT(t
)->id
, format_timestamp(buf
, sizeof(buf
), t
->next_elapse_realtime
));
460 if (t
->realtime_event_source
) {
461 r
= sd_event_source_set_time(t
->realtime_event_source
, t
->next_elapse_realtime
);
465 r
= sd_event_source_set_enabled(t
->realtime_event_source
, SD_EVENT_ONESHOT
);
467 r
= sd_event_add_time(
468 UNIT(t
)->manager
->event
,
469 &t
->realtime_event_source
,
470 t
->wake_system
? CLOCK_REALTIME_ALARM
: CLOCK_REALTIME
,
471 t
->next_elapse_realtime
, t
->accuracy_usec
,
476 (void) sd_event_source_set_description(t
->realtime_event_source
, "timer-realtime");
478 } else if (t
->realtime_event_source
) {
480 r
= sd_event_source_set_enabled(t
->realtime_event_source
, SD_EVENT_OFF
);
485 timer_set_state(t
, TIMER_WAITING
);
489 log_unit_warning_errno(UNIT(t
)->id
, r
, "%s failed to enter waiting state: %m", UNIT(t
)->id
);
490 timer_enter_dead(t
, TIMER_FAILURE_RESOURCES
);
493 static void timer_enter_running(Timer
*t
) {
494 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
499 /* Don't start job if we are supposed to go down */
500 if (unit_stop_pending(UNIT(t
)))
503 r
= manager_add_job(UNIT(t
)->manager
, JOB_START
, UNIT_TRIGGER(UNIT(t
)),
504 JOB_REPLACE
, true, &error
, NULL
);
508 dual_timestamp_get(&t
->last_trigger
);
511 touch_file(t
->stamp_path
, true, t
->last_trigger
.realtime
, UID_INVALID
, GID_INVALID
, 0);
513 timer_set_state(t
, TIMER_RUNNING
);
517 log_unit_warning(UNIT(t
)->id
,
518 "%s failed to queue unit startup job: %s",
519 UNIT(t
)->id
, bus_error_message(&error
, r
));
520 timer_enter_dead(t
, TIMER_FAILURE_RESOURCES
);
523 static int timer_start(Unit
*u
) {
528 assert(t
->state
== TIMER_DEAD
|| t
->state
== TIMER_FAILED
);
530 if (UNIT_TRIGGER(u
)->load_state
!= UNIT_LOADED
)
533 t
->last_trigger
= DUAL_TIMESTAMP_NULL
;
535 /* Reenable all timers that depend on unit activation time */
536 LIST_FOREACH(value
, v
, t
->values
)
537 if (v
->base
== TIMER_ACTIVE
)
543 if (stat(t
->stamp_path
, &st
) >= 0)
544 t
->last_trigger
.realtime
= timespec_load(&st
.st_atim
);
545 else if (errno
== ENOENT
)
546 /* The timer has never run before,
547 * make sure a stamp file exists.
549 touch_file(t
->stamp_path
, true, USEC_INFINITY
, UID_INVALID
, GID_INVALID
, 0);
552 t
->result
= TIMER_SUCCESS
;
553 timer_enter_waiting(t
, true);
557 static int timer_stop(Unit
*u
) {
561 assert(t
->state
== TIMER_WAITING
|| t
->state
== TIMER_RUNNING
|| t
->state
== TIMER_ELAPSED
);
563 timer_enter_dead(t
, TIMER_SUCCESS
);
567 static int timer_serialize(Unit
*u
, FILE *f
, FDSet
*fds
) {
574 unit_serialize_item(u
, f
, "state", timer_state_to_string(t
->state
));
575 unit_serialize_item(u
, f
, "result", timer_result_to_string(t
->result
));
577 if (t
->last_trigger
.realtime
> 0)
578 unit_serialize_item_format(u
, f
, "last-trigger-realtime", "%" PRIu64
, t
->last_trigger
.realtime
);
580 if (t
->last_trigger
.monotonic
> 0)
581 unit_serialize_item_format(u
, f
, "last-trigger-monotonic", "%" PRIu64
, t
->last_trigger
.monotonic
);
586 static int timer_deserialize_item(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
595 if (streq(key
, "state")) {
598 state
= timer_state_from_string(value
);
600 log_unit_debug(u
->id
, "Failed to parse state value %s", value
);
602 t
->deserialized_state
= state
;
603 } else if (streq(key
, "result")) {
606 f
= timer_result_from_string(value
);
608 log_unit_debug(u
->id
, "Failed to parse result value %s", value
);
609 else if (f
!= TIMER_SUCCESS
)
611 } else if (streq(key
, "last-trigger-realtime")) {
613 r
= safe_atou64(value
, &t
->last_trigger
.realtime
);
615 log_unit_debug(u
->id
, "Failed to parse last-trigger-realtime value %s", value
);
617 } else if (streq(key
, "last-trigger-monotonic")) {
619 r
= safe_atou64(value
, &t
->last_trigger
.monotonic
);
621 log_unit_debug(u
->id
, "Failed to parse last-trigger-monotonic value %s", value
);
624 log_unit_debug(u
->id
, "Unknown serialization key '%s'", key
);
629 _pure_
static UnitActiveState
timer_active_state(Unit
*u
) {
632 return state_translation_table
[TIMER(u
)->state
];
635 _pure_
static const char *timer_sub_state_to_string(Unit
*u
) {
638 return timer_state_to_string(TIMER(u
)->state
);
641 static int timer_dispatch(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
642 Timer
*t
= TIMER(userdata
);
646 if (t
->state
!= TIMER_WAITING
)
649 log_unit_debug(UNIT(t
)->id
, "Timer elapsed on %s", UNIT(t
)->id
);
650 timer_enter_running(t
);
654 static void timer_trigger_notify(Unit
*u
, Unit
*other
) {
661 if (other
->load_state
!= UNIT_LOADED
)
664 /* Reenable all timers that depend on unit state */
665 LIST_FOREACH(value
, v
, t
->values
)
666 if (v
->base
== TIMER_UNIT_ACTIVE
||
667 v
->base
== TIMER_UNIT_INACTIVE
)
675 /* Recalculate sleep time */
676 timer_enter_waiting(t
, false);
681 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other
))) {
682 log_unit_debug(UNIT(t
)->id
, "%s got notified about unit deactivation.", UNIT(t
)->id
);
683 timer_enter_waiting(t
, false);
692 assert_not_reached("Unknown timer state");
696 static void timer_reset_failed(Unit
*u
) {
701 if (t
->state
== TIMER_FAILED
)
702 timer_set_state(t
, TIMER_DEAD
);
704 t
->result
= TIMER_SUCCESS
;
707 static void timer_time_change(Unit
*u
) {
712 if (t
->state
!= TIMER_WAITING
)
715 log_unit_debug(u
->id
, "%s: time change, recalculating next elapse.", u
->id
);
716 timer_enter_waiting(t
, false);
719 static const char* const timer_state_table
[_TIMER_STATE_MAX
] = {
720 [TIMER_DEAD
] = "dead",
721 [TIMER_WAITING
] = "waiting",
722 [TIMER_RUNNING
] = "running",
723 [TIMER_ELAPSED
] = "elapsed",
724 [TIMER_FAILED
] = "failed"
727 DEFINE_STRING_TABLE_LOOKUP(timer_state
, TimerState
);
729 static const char* const timer_base_table
[_TIMER_BASE_MAX
] = {
730 [TIMER_ACTIVE
] = "OnActiveSec",
731 [TIMER_BOOT
] = "OnBootSec",
732 [TIMER_STARTUP
] = "OnStartupSec",
733 [TIMER_UNIT_ACTIVE
] = "OnUnitActiveSec",
734 [TIMER_UNIT_INACTIVE
] = "OnUnitInactiveSec",
735 [TIMER_CALENDAR
] = "OnCalendar"
738 DEFINE_STRING_TABLE_LOOKUP(timer_base
, TimerBase
);
740 static const char* const timer_result_table
[_TIMER_RESULT_MAX
] = {
741 [TIMER_SUCCESS
] = "success",
742 [TIMER_FAILURE_RESOURCES
] = "resources"
745 DEFINE_STRING_TABLE_LOOKUP(timer_result
, TimerResult
);
747 const UnitVTable timer_vtable
= {
748 .object_size
= sizeof(Timer
),
754 .private_section
= "Timer",
760 .coldplug
= timer_coldplug
,
764 .start
= timer_start
,
767 .serialize
= timer_serialize
,
768 .deserialize_item
= timer_deserialize_item
,
770 .active_state
= timer_active_state
,
771 .sub_state_to_string
= timer_sub_state_to_string
,
773 .trigger_notify
= timer_trigger_notify
,
775 .reset_failed
= timer_reset_failed
,
776 .time_change
= timer_time_change
,
778 .bus_interface
= "org.freedesktop.systemd1.Timer",
779 .bus_vtable
= bus_timer_vtable
,
780 .bus_set_property
= bus_timer_set_property
,
782 .can_transient
= true,