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/>.
24 #include "alloc-util.h"
25 #include "bus-error.h"
27 #include "dbus-timer.h"
29 #include "parse-util.h"
31 #include "string-table.h"
32 #include "string-util.h"
34 #include "unit-name.h"
36 #include "user-util.h"
38 static const UnitActiveState state_translation_table
[_TIMER_STATE_MAX
] = {
39 [TIMER_DEAD
] = UNIT_INACTIVE
,
40 [TIMER_WAITING
] = UNIT_ACTIVE
,
41 [TIMER_RUNNING
] = UNIT_ACTIVE
,
42 [TIMER_ELAPSED
] = UNIT_ACTIVE
,
43 [TIMER_FAILED
] = UNIT_FAILED
46 static int timer_dispatch(sd_event_source
*s
, uint64_t usec
, void *userdata
);
48 static void timer_init(Unit
*u
) {
52 assert(u
->load_state
== UNIT_STUB
);
54 t
->next_elapse_monotonic_or_boottime
= USEC_INFINITY
;
55 t
->next_elapse_realtime
= USEC_INFINITY
;
56 t
->accuracy_usec
= u
->manager
->default_timer_accuracy_usec
;
59 void timer_free_values(Timer
*t
) {
64 while ((v
= t
->values
)) {
65 LIST_REMOVE(value
, t
->values
, v
);
66 calendar_spec_free(v
->calendar_spec
);
71 static void timer_done(Unit
*u
) {
78 t
->monotonic_event_source
= sd_event_source_unref(t
->monotonic_event_source
);
79 t
->realtime_event_source
= sd_event_source_unref(t
->realtime_event_source
);
84 static int timer_verify(Timer
*t
) {
87 if (UNIT(t
)->load_state
!= UNIT_LOADED
)
91 log_unit_error(UNIT(t
), "Timer unit lacks value setting. Refusing.");
98 static int timer_add_default_dependencies(Timer
*t
) {
104 r
= unit_add_dependency_by_name(UNIT(t
), UNIT_BEFORE
, SPECIAL_TIMERS_TARGET
, NULL
, true);
108 if (UNIT(t
)->manager
->running_as
== MANAGER_SYSTEM
) {
109 r
= unit_add_two_dependencies_by_name(UNIT(t
), UNIT_AFTER
, UNIT_REQUIRES
, SPECIAL_SYSINIT_TARGET
, NULL
, true);
113 LIST_FOREACH(value
, v
, t
->values
) {
114 if (v
->base
== TIMER_CALENDAR
) {
115 r
= unit_add_dependency_by_name(UNIT(t
), UNIT_AFTER
, SPECIAL_TIME_SYNC_TARGET
, NULL
, true);
123 return unit_add_two_dependencies_by_name(UNIT(t
), UNIT_BEFORE
, UNIT_CONFLICTS
, SPECIAL_SHUTDOWN_TARGET
, NULL
, true);
126 static int timer_setup_persistent(Timer
*t
) {
134 if (UNIT(t
)->manager
->running_as
== MANAGER_SYSTEM
) {
136 r
= unit_require_mounts_for(UNIT(t
), "/var/lib/systemd/timers");
140 t
->stamp_path
= strappend("/var/lib/systemd/timers/stamp-", UNIT(t
)->id
);
144 e
= getenv("XDG_DATA_HOME");
146 t
->stamp_path
= strjoin(e
, "/systemd/timers/stamp-", UNIT(t
)->id
, NULL
);
149 _cleanup_free_
char *h
= NULL
;
151 r
= get_home_dir(&h
);
153 return log_unit_error_errno(UNIT(t
), r
, "Failed to determine home directory: %m");
155 t
->stamp_path
= strjoin(h
, "/.local/share/systemd/timers/stamp-", UNIT(t
)->id
, NULL
);
165 static int timer_load(Unit
*u
) {
170 assert(u
->load_state
== UNIT_STUB
);
172 r
= unit_load_fragment_and_dropin(u
);
176 if (u
->load_state
== UNIT_LOADED
) {
178 if (set_isempty(u
->dependencies
[UNIT_TRIGGERS
])) {
181 r
= unit_load_related_unit(u
, ".service", &x
);
185 r
= unit_add_two_dependencies(u
, UNIT_BEFORE
, UNIT_TRIGGERS
, x
, true);
190 r
= timer_setup_persistent(t
);
194 if (u
->default_dependencies
) {
195 r
= timer_add_default_dependencies(t
);
201 return timer_verify(t
);
204 static void timer_dump(Unit
*u
, FILE *f
, const char *prefix
) {
205 char buf
[FORMAT_TIMESPAN_MAX
];
210 trigger
= UNIT_TRIGGER(u
);
213 "%sTimer State: %s\n"
219 prefix
, timer_state_to_string(t
->state
),
220 prefix
, timer_result_to_string(t
->result
),
221 prefix
, trigger
? trigger
->id
: "n/a",
222 prefix
, yes_no(t
->persistent
),
223 prefix
, yes_no(t
->wake_system
),
224 prefix
, format_timespan(buf
, sizeof(buf
), t
->accuracy_usec
, 1));
226 LIST_FOREACH(value
, v
, t
->values
) {
228 if (v
->base
== TIMER_CALENDAR
) {
229 _cleanup_free_
char *p
= NULL
;
231 calendar_spec_to_string(v
->calendar_spec
, &p
);
236 timer_base_to_string(v
->base
),
239 char timespan1
[FORMAT_TIMESPAN_MAX
];
244 timer_base_to_string(v
->base
),
245 format_timespan(timespan1
, sizeof(timespan1
), v
->value
, 0));
250 static void timer_set_state(Timer
*t
, TimerState state
) {
251 TimerState old_state
;
254 old_state
= t
->state
;
257 if (state
!= TIMER_WAITING
) {
258 t
->monotonic_event_source
= sd_event_source_unref(t
->monotonic_event_source
);
259 t
->realtime_event_source
= sd_event_source_unref(t
->realtime_event_source
);
262 if (state
!= old_state
)
263 log_unit_debug(UNIT(t
), "Changed %s -> %s", timer_state_to_string(old_state
), 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
), "Timer is elapsed.");
420 timer_set_state(t
, TIMER_ELAPSED
);
424 if (found_monotonic
) {
425 char buf
[FORMAT_TIMESPAN_MAX
];
427 log_unit_debug(UNIT(t
), "Monotonic timer elapses in %s.", format_timespan(buf
, sizeof(buf
), t
->next_elapse_monotonic_or_boottime
> ts_monotonic
? t
->next_elapse_monotonic_or_boottime
- ts_monotonic
: 0, 0));
429 if (t
->monotonic_event_source
) {
430 r
= sd_event_source_set_time(t
->monotonic_event_source
, t
->next_elapse_monotonic_or_boottime
);
434 r
= sd_event_source_set_enabled(t
->monotonic_event_source
, SD_EVENT_ONESHOT
);
439 r
= sd_event_add_time(
440 UNIT(t
)->manager
->event
,
441 &t
->monotonic_event_source
,
442 t
->wake_system
? CLOCK_BOOTTIME_ALARM
: CLOCK_MONOTONIC
,
443 t
->next_elapse_monotonic_or_boottime
, t
->accuracy_usec
,
448 (void) sd_event_source_set_description(t
->monotonic_event_source
, "timer-monotonic");
451 } else if (t
->monotonic_event_source
) {
453 r
= sd_event_source_set_enabled(t
->monotonic_event_source
, SD_EVENT_OFF
);
458 if (found_realtime
) {
459 char buf
[FORMAT_TIMESTAMP_MAX
];
460 log_unit_debug(UNIT(t
), "Realtime timer elapses at %s.", format_timestamp(buf
, sizeof(buf
), t
->next_elapse_realtime
));
462 if (t
->realtime_event_source
) {
463 r
= sd_event_source_set_time(t
->realtime_event_source
, t
->next_elapse_realtime
);
467 r
= sd_event_source_set_enabled(t
->realtime_event_source
, SD_EVENT_ONESHOT
);
471 r
= sd_event_add_time(
472 UNIT(t
)->manager
->event
,
473 &t
->realtime_event_source
,
474 t
->wake_system
? CLOCK_REALTIME_ALARM
: CLOCK_REALTIME
,
475 t
->next_elapse_realtime
, t
->accuracy_usec
,
480 (void) sd_event_source_set_description(t
->realtime_event_source
, "timer-realtime");
483 } else if (t
->realtime_event_source
) {
485 r
= sd_event_source_set_enabled(t
->realtime_event_source
, SD_EVENT_OFF
);
490 timer_set_state(t
, TIMER_WAITING
);
494 log_unit_warning_errno(UNIT(t
), r
, "Failed to enter waiting state: %m");
495 timer_enter_dead(t
, TIMER_FAILURE_RESOURCES
);
498 static void timer_enter_running(Timer
*t
) {
499 _cleanup_bus_error_free_ sd_bus_error error
= SD_BUS_ERROR_NULL
;
504 /* Don't start job if we are supposed to go down */
505 if (unit_stop_pending(UNIT(t
)))
508 r
= manager_add_job(UNIT(t
)->manager
, JOB_START
, UNIT_TRIGGER(UNIT(t
)),
509 JOB_REPLACE
, true, &error
, NULL
);
513 dual_timestamp_get(&t
->last_trigger
);
516 touch_file(t
->stamp_path
, true, t
->last_trigger
.realtime
, UID_INVALID
, GID_INVALID
, 0);
518 timer_set_state(t
, TIMER_RUNNING
);
522 log_unit_warning(UNIT(t
), "Failed to queue unit startup job: %s", bus_error_message(&error
, r
));
523 timer_enter_dead(t
, TIMER_FAILURE_RESOURCES
);
526 static int timer_start(Unit
*u
) {
531 assert(t
->state
== TIMER_DEAD
|| t
->state
== TIMER_FAILED
);
533 if (UNIT_TRIGGER(u
)->load_state
!= UNIT_LOADED
)
536 t
->last_trigger
= DUAL_TIMESTAMP_NULL
;
538 /* Reenable all timers that depend on unit activation time */
539 LIST_FOREACH(value
, v
, t
->values
)
540 if (v
->base
== TIMER_ACTIVE
)
546 if (stat(t
->stamp_path
, &st
) >= 0)
547 t
->last_trigger
.realtime
= timespec_load(&st
.st_atim
);
548 else if (errno
== ENOENT
)
549 /* The timer has never run before,
550 * make sure a stamp file exists.
552 touch_file(t
->stamp_path
, true, USEC_INFINITY
, UID_INVALID
, GID_INVALID
, 0);
555 t
->result
= TIMER_SUCCESS
;
556 timer_enter_waiting(t
, true);
560 static int timer_stop(Unit
*u
) {
564 assert(t
->state
== TIMER_WAITING
|| t
->state
== TIMER_RUNNING
|| t
->state
== TIMER_ELAPSED
);
566 timer_enter_dead(t
, TIMER_SUCCESS
);
570 static int timer_serialize(Unit
*u
, FILE *f
, FDSet
*fds
) {
577 unit_serialize_item(u
, f
, "state", timer_state_to_string(t
->state
));
578 unit_serialize_item(u
, f
, "result", timer_result_to_string(t
->result
));
580 if (t
->last_trigger
.realtime
> 0)
581 unit_serialize_item_format(u
, f
, "last-trigger-realtime", "%" PRIu64
, t
->last_trigger
.realtime
);
583 if (t
->last_trigger
.monotonic
> 0)
584 unit_serialize_item_format(u
, f
, "last-trigger-monotonic", "%" PRIu64
, t
->last_trigger
.monotonic
);
589 static int timer_deserialize_item(Unit
*u
, const char *key
, const char *value
, FDSet
*fds
) {
598 if (streq(key
, "state")) {
601 state
= timer_state_from_string(value
);
603 log_unit_debug(u
, "Failed to parse state value: %s", value
);
605 t
->deserialized_state
= state
;
606 } else if (streq(key
, "result")) {
609 f
= timer_result_from_string(value
);
611 log_unit_debug(u
, "Failed to parse result value: %s", value
);
612 else if (f
!= TIMER_SUCCESS
)
614 } else if (streq(key
, "last-trigger-realtime")) {
616 r
= safe_atou64(value
, &t
->last_trigger
.realtime
);
618 log_unit_debug(u
, "Failed to parse last-trigger-realtime value: %s", value
);
620 } else if (streq(key
, "last-trigger-monotonic")) {
622 r
= safe_atou64(value
, &t
->last_trigger
.monotonic
);
624 log_unit_debug(u
, "Failed to parse last-trigger-monotonic value: %s", value
);
627 log_unit_debug(u
, "Unknown serialization key: %s", key
);
632 _pure_
static UnitActiveState
timer_active_state(Unit
*u
) {
635 return state_translation_table
[TIMER(u
)->state
];
638 _pure_
static const char *timer_sub_state_to_string(Unit
*u
) {
641 return timer_state_to_string(TIMER(u
)->state
);
644 static int timer_dispatch(sd_event_source
*s
, uint64_t usec
, void *userdata
) {
645 Timer
*t
= TIMER(userdata
);
649 if (t
->state
!= TIMER_WAITING
)
652 log_unit_debug(UNIT(t
), "Timer elapsed.");
653 timer_enter_running(t
);
657 static void timer_trigger_notify(Unit
*u
, Unit
*other
) {
664 if (other
->load_state
!= UNIT_LOADED
)
667 /* Reenable all timers that depend on unit state */
668 LIST_FOREACH(value
, v
, t
->values
)
669 if (v
->base
== TIMER_UNIT_ACTIVE
||
670 v
->base
== TIMER_UNIT_INACTIVE
)
678 /* Recalculate sleep time */
679 timer_enter_waiting(t
, false);
684 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other
))) {
685 log_unit_debug(UNIT(t
), "Got notified about unit deactivation.");
686 timer_enter_waiting(t
, false);
695 assert_not_reached("Unknown timer state");
699 static void timer_reset_failed(Unit
*u
) {
704 if (t
->state
== TIMER_FAILED
)
705 timer_set_state(t
, TIMER_DEAD
);
707 t
->result
= TIMER_SUCCESS
;
710 static void timer_time_change(Unit
*u
) {
715 if (t
->state
!= TIMER_WAITING
)
718 log_unit_debug(u
, "Time change, recalculating next elapse.");
719 timer_enter_waiting(t
, false);
722 static const char* const timer_base_table
[_TIMER_BASE_MAX
] = {
723 [TIMER_ACTIVE
] = "OnActiveSec",
724 [TIMER_BOOT
] = "OnBootSec",
725 [TIMER_STARTUP
] = "OnStartupSec",
726 [TIMER_UNIT_ACTIVE
] = "OnUnitActiveSec",
727 [TIMER_UNIT_INACTIVE
] = "OnUnitInactiveSec",
728 [TIMER_CALENDAR
] = "OnCalendar"
731 DEFINE_STRING_TABLE_LOOKUP(timer_base
, TimerBase
);
733 static const char* const timer_result_table
[_TIMER_RESULT_MAX
] = {
734 [TIMER_SUCCESS
] = "success",
735 [TIMER_FAILURE_RESOURCES
] = "resources"
738 DEFINE_STRING_TABLE_LOOKUP(timer_result
, TimerResult
);
740 const UnitVTable timer_vtable
= {
741 .object_size
= sizeof(Timer
),
747 .private_section
= "Timer",
753 .coldplug
= timer_coldplug
,
757 .start
= timer_start
,
760 .serialize
= timer_serialize
,
761 .deserialize_item
= timer_deserialize_item
,
763 .active_state
= timer_active_state
,
764 .sub_state_to_string
= timer_sub_state_to_string
,
766 .trigger_notify
= timer_trigger_notify
,
768 .reset_failed
= timer_reset_failed
,
769 .time_change
= timer_time_change
,
771 .bus_vtable
= bus_timer_vtable
,
772 .bus_set_property
= bus_timer_set_property
,
774 .can_transient
= true,