]> git.proxmox.com Git - systemd.git/blame - src/core/timer.c
New upstream version 236
[systemd.git] / src / core / timer.c
CommitLineData
52ad194e 1/* SPDX-License-Identifier: LGPL-2.1+ */
663996b3
MS
2/***
3 This file is part of systemd.
4
5 Copyright 2010 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include <errno.h>
22
db2df898
MP
23#include "alloc-util.h"
24#include "bus-error.h"
25#include "bus-util.h"
663996b3 26#include "dbus-timer.h"
db2df898
MP
27#include "fs-util.h"
28#include "parse-util.h"
4c89c718 29#include "random-util.h"
663996b3 30#include "special.h"
db2df898
MP
31#include "string-table.h"
32#include "string-util.h"
33#include "timer.h"
34#include "unit-name.h"
35#include "unit.h"
36#include "user-util.h"
37#include "virt.h"
663996b3
MS
38
39static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
40 [TIMER_DEAD] = UNIT_INACTIVE,
41 [TIMER_WAITING] = UNIT_ACTIVE,
42 [TIMER_RUNNING] = UNIT_ACTIVE,
43 [TIMER_ELAPSED] = UNIT_ACTIVE,
44 [TIMER_FAILED] = UNIT_FAILED
45};
46
60f067b4
JS
47static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
48
663996b3
MS
49static void timer_init(Unit *u) {
50 Timer *t = TIMER(u);
51
52 assert(u);
53 assert(u->load_state == UNIT_STUB);
54
5eef597e
MP
55 t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
56 t->next_elapse_realtime = USEC_INFINITY;
60f067b4 57 t->accuracy_usec = u->manager->default_timer_accuracy_usec;
db2df898 58 t->remain_after_elapse = true;
663996b3
MS
59}
60
61void timer_free_values(Timer *t) {
62 TimerValue *v;
63
64 assert(t);
65
66 while ((v = t->values)) {
60f067b4 67 LIST_REMOVE(value, t->values, v);
13d276d0 68 calendar_spec_free(v->calendar_spec);
663996b3
MS
69 free(v);
70 }
71}
72
73static void timer_done(Unit *u) {
74 Timer *t = TIMER(u);
75
76 assert(t);
77
78 timer_free_values(t);
79
60f067b4
JS
80 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
81 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
82
83 free(t->stamp_path);
663996b3
MS
84}
85
86static int timer_verify(Timer *t) {
87 assert(t);
88
89 if (UNIT(t)->load_state != UNIT_LOADED)
90 return 0;
91
92 if (!t->values) {
e3bff60a 93 log_unit_error(UNIT(t), "Timer unit lacks value setting. Refusing.");
663996b3
MS
94 return -EINVAL;
95 }
96
97 return 0;
98}
99
100static int timer_add_default_dependencies(Timer *t) {
101 int r;
5eef597e 102 TimerValue *v;
663996b3
MS
103
104 assert(t);
105
db2df898
MP
106 if (!UNIT(t)->default_dependencies)
107 return 0;
108
52ad194e 109 r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
663996b3
MS
110 if (r < 0)
111 return r;
112
aa27b158 113 if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
52ad194e 114 r = unit_add_two_dependencies_by_name(UNIT(t), UNIT_AFTER, UNIT_REQUIRES, SPECIAL_SYSINIT_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
663996b3
MS
115 if (r < 0)
116 return r;
5eef597e
MP
117
118 LIST_FOREACH(value, v, t->values) {
119 if (v->base == TIMER_CALENDAR) {
52ad194e 120 r = unit_add_dependency_by_name(UNIT(t), UNIT_AFTER, SPECIAL_TIME_SYNC_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
5eef597e
MP
121 if (r < 0)
122 return r;
123 break;
124 }
125 }
663996b3
MS
126 }
127
52ad194e
MB
128 return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true, UNIT_DEPENDENCY_DEFAULT);
129}
130
131static int timer_add_trigger_dependencies(Timer *t) {
132 Unit *x;
133 int r;
134
135 assert(t);
136
137 if (!hashmap_isempty(UNIT(t)->dependencies[UNIT_TRIGGERS]))
138 return 0;
139
140 r = unit_load_related_unit(UNIT(t), ".service", &x);
141 if (r < 0)
142 return r;
143
144 return unit_add_two_dependencies(UNIT(t), UNIT_BEFORE, UNIT_TRIGGERS, x, true, UNIT_DEPENDENCY_IMPLICIT);
663996b3
MS
145}
146
60f067b4
JS
147static int timer_setup_persistent(Timer *t) {
148 int r;
149
150 assert(t);
151
152 if (!t->persistent)
153 return 0;
154
aa27b158 155 if (MANAGER_IS_SYSTEM(UNIT(t)->manager)) {
60f067b4 156
52ad194e 157 r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers", UNIT_DEPENDENCY_FILE);
60f067b4
JS
158 if (r < 0)
159 return r;
160
161 t->stamp_path = strappend("/var/lib/systemd/timers/stamp-", UNIT(t)->id);
162 } else {
163 const char *e;
164
165 e = getenv("XDG_DATA_HOME");
166 if (e)
2897b343 167 t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id);
60f067b4
JS
168 else {
169
170 _cleanup_free_ char *h = NULL;
171
172 r = get_home_dir(&h);
f47781d8 173 if (r < 0)
e3bff60a 174 return log_unit_error_errno(UNIT(t), r, "Failed to determine home directory: %m");
60f067b4 175
2897b343 176 t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id);
60f067b4
JS
177 }
178 }
179
180 if (!t->stamp_path)
181 return log_oom();
182
183 return 0;
184}
185
663996b3
MS
186static int timer_load(Unit *u) {
187 Timer *t = TIMER(u);
188 int r;
189
190 assert(u);
191 assert(u->load_state == UNIT_STUB);
192
193 r = unit_load_fragment_and_dropin(u);
194 if (r < 0)
195 return r;
196
197 if (u->load_state == UNIT_LOADED) {
198
52ad194e
MB
199 r = timer_add_trigger_dependencies(t);
200 if (r < 0)
201 return r;
663996b3 202
60f067b4
JS
203 r = timer_setup_persistent(t);
204 if (r < 0)
205 return r;
206
db2df898
MP
207 r = timer_add_default_dependencies(t);
208 if (r < 0)
209 return r;
663996b3
MS
210 }
211
212 return timer_verify(t);
213}
214
215static void timer_dump(Unit *u, FILE *f, const char *prefix) {
60f067b4 216 char buf[FORMAT_TIMESPAN_MAX];
663996b3
MS
217 Timer *t = TIMER(u);
218 Unit *trigger;
219 TimerValue *v;
220
221 trigger = UNIT_TRIGGER(u);
222
223 fprintf(f,
224 "%sTimer State: %s\n"
225 "%sResult: %s\n"
60f067b4
JS
226 "%sUnit: %s\n"
227 "%sPersistent: %s\n"
228 "%sWakeSystem: %s\n"
db2df898
MP
229 "%sAccuracy: %s\n"
230 "%sRemainAfterElapse: %s\n",
663996b3
MS
231 prefix, timer_state_to_string(t->state),
232 prefix, timer_result_to_string(t->result),
60f067b4
JS
233 prefix, trigger ? trigger->id : "n/a",
234 prefix, yes_no(t->persistent),
235 prefix, yes_no(t->wake_system),
db2df898
MP
236 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1),
237 prefix, yes_no(t->remain_after_elapse));
663996b3
MS
238
239 LIST_FOREACH(value, v, t->values) {
240
241 if (v->base == TIMER_CALENDAR) {
242 _cleanup_free_ char *p = NULL;
243
2897b343 244 (void) calendar_spec_to_string(v->calendar_spec, &p);
663996b3
MS
245
246 fprintf(f,
247 "%s%s: %s\n",
248 prefix,
249 timer_base_to_string(v->base),
250 strna(p));
251 } else {
252 char timespan1[FORMAT_TIMESPAN_MAX];
253
254 fprintf(f,
255 "%s%s: %s\n",
256 prefix,
257 timer_base_to_string(v->base),
5eef597e 258 format_timespan(timespan1, sizeof(timespan1), v->value, 0));
663996b3
MS
259 }
260 }
261}
262
263static void timer_set_state(Timer *t, TimerState state) {
264 TimerState old_state;
265 assert(t);
266
267 old_state = t->state;
268 t->state = state;
269
270 if (state != TIMER_WAITING) {
60f067b4
JS
271 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
272 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
8a584da2
MP
273 t->next_elapse_monotonic_or_boottime = USEC_INFINITY;
274 t->next_elapse_realtime = USEC_INFINITY;
663996b3
MS
275 }
276
277 if (state != old_state)
e3bff60a 278 log_unit_debug(UNIT(t), "Changed %s -> %s", timer_state_to_string(old_state), timer_state_to_string(state));
663996b3
MS
279
280 unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
281}
282
283static void timer_enter_waiting(Timer *t, bool initial);
284
285static int timer_coldplug(Unit *u) {
286 Timer *t = TIMER(u);
287
288 assert(t);
289 assert(t->state == TIMER_DEAD);
290
db2df898
MP
291 if (t->deserialized_state == t->state)
292 return 0;
663996b3 293
db2df898
MP
294 if (t->deserialized_state == TIMER_WAITING)
295 timer_enter_waiting(t, false);
296 else
297 timer_set_state(t, t->deserialized_state);
663996b3
MS
298
299 return 0;
300}
301
302static void timer_enter_dead(Timer *t, TimerResult f) {
303 assert(t);
304
8a584da2 305 if (t->result == TIMER_SUCCESS)
663996b3
MS
306 t->result = f;
307
f5e65279
MB
308 if (t->result != TIMER_SUCCESS)
309 log_unit_warning(UNIT(t), "Failed with result '%s'.", timer_result_to_string(t->result));
310
663996b3
MS
311 timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
312}
313
db2df898
MP
314static void timer_enter_elapsed(Timer *t, bool leave_around) {
315 assert(t);
316
317 /* If a unit is marked with RemainAfterElapse=yes we leave it
318 * around even after it elapsed once, so that starting it
319 * later again does not necessarily mean immediate
320 * retriggering. We unconditionally leave units with
321 * TIMER_UNIT_ACTIVE or TIMER_UNIT_INACTIVE triggers around,
322 * since they might be restarted automatically at any time
323 * later on. */
324
325 if (t->remain_after_elapse || leave_around)
326 timer_set_state(t, TIMER_ELAPSED);
327 else
328 timer_enter_dead(t, TIMER_SUCCESS);
329}
330
4c89c718
MP
331static void add_random(Timer *t, usec_t *v) {
332 char s[FORMAT_TIMESPAN_MAX];
333 usec_t add;
334
335 assert(t);
aa27b158 336 assert(v);
4c89c718
MP
337
338 if (t->random_usec == 0)
339 return;
340 if (*v == USEC_INFINITY)
341 return;
342
343 add = random_u64() % t->random_usec;
344
345 if (*v + add < *v) /* overflow */
346 *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */
347 else
348 *v += add;
349
2897b343 350 log_unit_debug(UNIT(t), "Adding %s random time.", format_timespan(s, sizeof(s), add, 0));
4c89c718
MP
351}
352
663996b3 353static void timer_enter_waiting(Timer *t, bool initial) {
663996b3 354 bool found_monotonic = false, found_realtime = false;
db2df898 355 bool leave_around = false;
81c58355
MB
356 triple_timestamp ts;
357 usec_t base = 0;
60f067b4 358 TimerValue *v;
4c89c718 359 Unit *trigger;
663996b3
MS
360 int r;
361
4c89c718
MP
362 assert(t);
363
364 trigger = UNIT_TRIGGER(UNIT(t));
365 if (!trigger) {
366 log_unit_error(UNIT(t), "Unit to trigger vanished.");
367 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
368 return;
369 }
370
81c58355 371 triple_timestamp_get(&ts);
60f067b4 372 t->next_elapse_monotonic_or_boottime = t->next_elapse_realtime = 0;
663996b3
MS
373
374 LIST_FOREACH(value, v, t->values) {
375
376 if (v->disabled)
377 continue;
378
379 if (v->base == TIMER_CALENDAR) {
60f067b4
JS
380 usec_t b;
381
382 /* If we know the last time this was
383 * triggered, schedule the job based relative
384 * to that. If we don't just start from
385 * now. */
663996b3 386
81c58355 387 b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts.realtime;
60f067b4
JS
388
389 r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
663996b3
MS
390 if (r < 0)
391 continue;
392
393 if (!found_realtime)
394 t->next_elapse_realtime = v->next_elapse;
395 else
396 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
397
398 found_realtime = true;
399
400 } else {
81c58355 401
663996b3
MS
402 switch (v->base) {
403
404 case TIMER_ACTIVE:
405 if (state_translation_table[t->state] == UNIT_ACTIVE)
406 base = UNIT(t)->inactive_exit_timestamp.monotonic;
407 else
81c58355 408 base = ts.monotonic;
663996b3
MS
409 break;
410
411 case TIMER_BOOT:
db2df898
MP
412 if (detect_container() <= 0) {
413 /* CLOCK_MONOTONIC equals the uptime on Linux */
414 base = 0;
415 break;
416 }
417 /* In a container we don't want to include the time the host
418 * was already up when the container started, so count from
2897b343 419 * our own startup. */
52ad194e 420 _fallthrough_;
663996b3 421 case TIMER_STARTUP:
52ad194e 422 base = UNIT(t)->manager->timestamps[MANAGER_TIMESTAMP_USERSPACE].monotonic;
663996b3
MS
423 break;
424
425 case TIMER_UNIT_ACTIVE:
db2df898 426 leave_around = true;
4c89c718 427 base = trigger->inactive_exit_timestamp.monotonic;
663996b3
MS
428
429 if (base <= 0)
60f067b4 430 base = t->last_trigger.monotonic;
663996b3
MS
431
432 if (base <= 0)
433 continue;
434
435 break;
436
437 case TIMER_UNIT_INACTIVE:
db2df898 438 leave_around = true;
4c89c718 439 base = trigger->inactive_enter_timestamp.monotonic;
663996b3
MS
440
441 if (base <= 0)
60f067b4 442 base = t->last_trigger.monotonic;
663996b3
MS
443
444 if (base <= 0)
445 continue;
446
447 break;
448
449 default:
450 assert_not_reached("Unknown timer base");
451 }
452
81c58355 453 v->next_elapse = usec_add(usec_shift_clock(base, CLOCK_MONOTONIC, TIMER_MONOTONIC_CLOCK(t)), v->value);
663996b3 454
81c58355
MB
455 if (!initial &&
456 v->next_elapse < triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)) &&
457 IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
663996b3
MS
458 /* This is a one time trigger, disable it now */
459 v->disabled = true;
460 continue;
461 }
462
463 if (!found_monotonic)
60f067b4 464 t->next_elapse_monotonic_or_boottime = v->next_elapse;
663996b3 465 else
60f067b4 466 t->next_elapse_monotonic_or_boottime = MIN(t->next_elapse_monotonic_or_boottime, v->next_elapse);
663996b3
MS
467
468 found_monotonic = true;
469 }
470 }
471
472 if (!found_monotonic && !found_realtime) {
e3bff60a 473 log_unit_debug(UNIT(t), "Timer is elapsed.");
db2df898 474 timer_enter_elapsed(t, leave_around);
663996b3
MS
475 return;
476 }
477
478 if (found_monotonic) {
479 char buf[FORMAT_TIMESPAN_MAX];
db2df898 480 usec_t left;
60f067b4 481
4c89c718
MP
482 add_random(t, &t->next_elapse_monotonic_or_boottime);
483
81c58355 484 left = usec_sub_unsigned(t->next_elapse_monotonic_or_boottime, triple_timestamp_by_clock(&ts, TIMER_MONOTONIC_CLOCK(t)));
db2df898 485 log_unit_debug(UNIT(t), "Monotonic timer elapses in %s.", format_timespan(buf, sizeof(buf), left, 0));
663996b3 486
60f067b4
JS
487 if (t->monotonic_event_source) {
488 r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic_or_boottime);
489 if (r < 0)
490 goto fail;
491
492 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
e3bff60a
MP
493 if (r < 0)
494 goto fail;
495 } else {
496
60f067b4
JS
497 r = sd_event_add_time(
498 UNIT(t)->manager->event,
499 &t->monotonic_event_source,
500 t->wake_system ? CLOCK_BOOTTIME_ALARM : CLOCK_MONOTONIC,
501 t->next_elapse_monotonic_or_boottime, t->accuracy_usec,
502 timer_dispatch, t);
e3bff60a
MP
503 if (r < 0)
504 goto fail;
505
506 (void) sd_event_source_set_description(t->monotonic_event_source, "timer-monotonic");
507 }
60f067b4
JS
508
509 } else if (t->monotonic_event_source) {
510
511 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
512 if (r < 0)
513 goto fail;
514 }
663996b3
MS
515
516 if (found_realtime) {
517 char buf[FORMAT_TIMESTAMP_MAX];
4c89c718
MP
518
519 add_random(t, &t->next_elapse_realtime);
520
e3bff60a 521 log_unit_debug(UNIT(t), "Realtime timer elapses at %s.", format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
663996b3 522
60f067b4
JS
523 if (t->realtime_event_source) {
524 r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
525 if (r < 0)
526 goto fail;
527
528 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
e3bff60a
MP
529 if (r < 0)
530 goto fail;
531 } else {
60f067b4
JS
532 r = sd_event_add_time(
533 UNIT(t)->manager->event,
534 &t->realtime_event_source,
535 t->wake_system ? CLOCK_REALTIME_ALARM : CLOCK_REALTIME,
536 t->next_elapse_realtime, t->accuracy_usec,
537 timer_dispatch, t);
e3bff60a
MP
538 if (r < 0)
539 goto fail;
540
541 (void) sd_event_source_set_description(t->realtime_event_source, "timer-realtime");
542 }
60f067b4
JS
543
544 } else if (t->realtime_event_source) {
545
546 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
547 if (r < 0)
548 goto fail;
549 }
663996b3
MS
550
551 timer_set_state(t, TIMER_WAITING);
552 return;
553
554fail:
e3bff60a 555 log_unit_warning_errno(UNIT(t), r, "Failed to enter waiting state: %m");
663996b3
MS
556 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
557}
558
559static void timer_enter_running(Timer *t) {
4c89c718
MP
560 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
561 Unit *trigger;
663996b3
MS
562 int r;
563
564 assert(t);
663996b3
MS
565
566 /* Don't start job if we are supposed to go down */
567 if (unit_stop_pending(UNIT(t)))
568 return;
569
4c89c718
MP
570 trigger = UNIT_TRIGGER(UNIT(t));
571 if (!trigger) {
572 log_unit_error(UNIT(t), "Unit to trigger vanished.");
573 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
574 return;
575 }
576
577 r = manager_add_job(UNIT(t)->manager, JOB_START, trigger, JOB_REPLACE, &error, NULL);
663996b3
MS
578 if (r < 0)
579 goto fail;
580
60f067b4
JS
581 dual_timestamp_get(&t->last_trigger);
582
583 if (t->stamp_path)
db2df898 584 touch_file(t->stamp_path, true, t->last_trigger.realtime, UID_INVALID, GID_INVALID, MODE_INVALID);
663996b3
MS
585
586 timer_set_state(t, TIMER_RUNNING);
587 return;
588
589fail:
e3bff60a 590 log_unit_warning(UNIT(t), "Failed to queue unit startup job: %s", bus_error_message(&error, r));
663996b3 591 timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
663996b3
MS
592}
593
594static int timer_start(Unit *u) {
595 Timer *t = TIMER(u);
f47781d8 596 TimerValue *v;
4c89c718 597 Unit *trigger;
aa27b158 598 int r;
663996b3
MS
599
600 assert(t);
f5e65279 601 assert(IN_SET(t->state, TIMER_DEAD, TIMER_FAILED));
663996b3 602
4c89c718
MP
603 trigger = UNIT_TRIGGER(u);
604 if (!trigger || trigger->load_state != UNIT_LOADED) {
605 log_unit_error(u, "Refusing to start, unit to trigger not loaded.");
663996b3 606 return -ENOENT;
4c89c718 607 }
663996b3 608
aa27b158
MP
609 r = unit_start_limit_test(u);
610 if (r < 0) {
611 timer_enter_dead(t, TIMER_FAILURE_START_LIMIT_HIT);
612 return r;
613 }
614
8a584da2
MP
615 r = unit_acquire_invocation_id(u);
616 if (r < 0)
617 return r;
618
60f067b4
JS
619 t->last_trigger = DUAL_TIMESTAMP_NULL;
620
f47781d8
MP
621 /* Reenable all timers that depend on unit activation time */
622 LIST_FOREACH(value, v, t->values)
623 if (v->base == TIMER_ACTIVE)
624 v->disabled = false;
625
60f067b4
JS
626 if (t->stamp_path) {
627 struct stat st;
628
f5e65279
MB
629 if (stat(t->stamp_path, &st) >= 0) {
630 usec_t ft;
631
632 /* Load the file timestamp, but only if it is actually in the past. If it is in the future,
633 * something is wrong with the system clock. */
634
635 ft = timespec_load(&st.st_mtim);
636 if (ft < now(CLOCK_REALTIME))
637 t->last_trigger.realtime = ft;
638 else {
639 char z[FORMAT_TIMESTAMP_MAX];
640
641 log_unit_warning(u, "Not using persistent file timestamp %s as it is in the future.",
642 format_timestamp(z, sizeof(z), ft));
643 }
644
645 } else if (errno == ENOENT)
60f067b4
JS
646 /* The timer has never run before,
647 * make sure a stamp file exists.
648 */
8a584da2 649 (void) touch_file(t->stamp_path, true, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
60f067b4
JS
650 }
651
663996b3
MS
652 t->result = TIMER_SUCCESS;
653 timer_enter_waiting(t, true);
e735f4d4 654 return 1;
663996b3
MS
655}
656
657static int timer_stop(Unit *u) {
658 Timer *t = TIMER(u);
659
660 assert(t);
f5e65279 661 assert(IN_SET(t->state, TIMER_WAITING, TIMER_RUNNING, TIMER_ELAPSED));
663996b3
MS
662
663 timer_enter_dead(t, TIMER_SUCCESS);
e735f4d4 664 return 1;
663996b3
MS
665}
666
667static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
668 Timer *t = TIMER(u);
669
670 assert(u);
671 assert(f);
672 assert(fds);
673
674 unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
675 unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
676
60f067b4
JS
677 if (t->last_trigger.realtime > 0)
678 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
679
680 if (t->last_trigger.monotonic > 0)
681 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
682
663996b3
MS
683 return 0;
684}
685
686static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
687 Timer *t = TIMER(u);
60f067b4 688 int r;
663996b3
MS
689
690 assert(u);
691 assert(key);
692 assert(value);
693 assert(fds);
694
695 if (streq(key, "state")) {
696 TimerState state;
697
698 state = timer_state_from_string(value);
699 if (state < 0)
e3bff60a 700 log_unit_debug(u, "Failed to parse state value: %s", value);
663996b3
MS
701 else
702 t->deserialized_state = state;
703 } else if (streq(key, "result")) {
704 TimerResult f;
705
706 f = timer_result_from_string(value);
707 if (f < 0)
e3bff60a 708 log_unit_debug(u, "Failed to parse result value: %s", value);
663996b3
MS
709 else if (f != TIMER_SUCCESS)
710 t->result = f;
60f067b4
JS
711 } else if (streq(key, "last-trigger-realtime")) {
712
713 r = safe_atou64(value, &t->last_trigger.realtime);
714 if (r < 0)
e3bff60a 715 log_unit_debug(u, "Failed to parse last-trigger-realtime value: %s", value);
60f067b4
JS
716
717 } else if (streq(key, "last-trigger-monotonic")) {
718
719 r = safe_atou64(value, &t->last_trigger.monotonic);
720 if (r < 0)
e3bff60a 721 log_unit_debug(u, "Failed to parse last-trigger-monotonic value: %s", value);
663996b3
MS
722
723 } else
e3bff60a 724 log_unit_debug(u, "Unknown serialization key: %s", key);
663996b3
MS
725
726 return 0;
727}
728
729_pure_ static UnitActiveState timer_active_state(Unit *u) {
730 assert(u);
731
732 return state_translation_table[TIMER(u)->state];
733}
734
735_pure_ static const char *timer_sub_state_to_string(Unit *u) {
736 assert(u);
737
738 return timer_state_to_string(TIMER(u)->state);
739}
740
60f067b4
JS
741static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
742 Timer *t = TIMER(userdata);
663996b3
MS
743
744 assert(t);
663996b3
MS
745
746 if (t->state != TIMER_WAITING)
60f067b4 747 return 0;
663996b3 748
e3bff60a 749 log_unit_debug(UNIT(t), "Timer elapsed.");
663996b3 750 timer_enter_running(t);
60f067b4 751 return 0;
663996b3
MS
752}
753
754static void timer_trigger_notify(Unit *u, Unit *other) {
755 Timer *t = TIMER(u);
756 TimerValue *v;
757
758 assert(u);
759 assert(other);
760
761 if (other->load_state != UNIT_LOADED)
762 return;
763
764 /* Reenable all timers that depend on unit state */
765 LIST_FOREACH(value, v, t->values)
f5e65279 766 if (IN_SET(v->base, TIMER_UNIT_ACTIVE, TIMER_UNIT_INACTIVE))
663996b3
MS
767 v->disabled = false;
768
769 switch (t->state) {
770
771 case TIMER_WAITING:
772 case TIMER_ELAPSED:
773
774 /* Recalculate sleep time */
775 timer_enter_waiting(t, false);
776 break;
777
778 case TIMER_RUNNING:
779
780 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
e3bff60a 781 log_unit_debug(UNIT(t), "Got notified about unit deactivation.");
663996b3
MS
782 timer_enter_waiting(t, false);
783 }
784 break;
785
786 case TIMER_DEAD:
787 case TIMER_FAILED:
788 break;
789
790 default:
791 assert_not_reached("Unknown timer state");
792 }
793}
794
795static void timer_reset_failed(Unit *u) {
796 Timer *t = TIMER(u);
797
798 assert(t);
799
800 if (t->state == TIMER_FAILED)
801 timer_set_state(t, TIMER_DEAD);
802
803 t->result = TIMER_SUCCESS;
804}
805
806static void timer_time_change(Unit *u) {
807 Timer *t = TIMER(u);
808
809 assert(u);
810
811 if (t->state != TIMER_WAITING)
812 return;
813
e3bff60a 814 log_unit_debug(u, "Time change, recalculating next elapse.");
663996b3
MS
815 timer_enter_waiting(t, false);
816}
817
663996b3
MS
818static const char* const timer_base_table[_TIMER_BASE_MAX] = {
819 [TIMER_ACTIVE] = "OnActiveSec",
820 [TIMER_BOOT] = "OnBootSec",
821 [TIMER_STARTUP] = "OnStartupSec",
822 [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
823 [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
824 [TIMER_CALENDAR] = "OnCalendar"
825};
826
827DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
828
829static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
830 [TIMER_SUCCESS] = "success",
aa27b158
MP
831 [TIMER_FAILURE_RESOURCES] = "resources",
832 [TIMER_FAILURE_START_LIMIT_HIT] = "start-limit-hit",
663996b3
MS
833};
834
835DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
836
837const UnitVTable timer_vtable = {
838 .object_size = sizeof(Timer),
60f067b4 839
663996b3
MS
840 .sections =
841 "Unit\0"
842 "Timer\0"
843 "Install\0",
f47781d8 844 .private_section = "Timer",
663996b3
MS
845
846 .init = timer_init,
847 .done = timer_done,
848 .load = timer_load,
849
850 .coldplug = timer_coldplug,
851
852 .dump = timer_dump,
853
854 .start = timer_start,
855 .stop = timer_stop,
856
857 .serialize = timer_serialize,
858 .deserialize_item = timer_deserialize_item,
859
860 .active_state = timer_active_state,
861 .sub_state_to_string = timer_sub_state_to_string,
862
663996b3
MS
863 .trigger_notify = timer_trigger_notify,
864
865 .reset_failed = timer_reset_failed,
866 .time_change = timer_time_change,
867
60f067b4 868 .bus_vtable = bus_timer_vtable,
f47781d8
MP
869 .bus_set_property = bus_timer_set_property,
870
871 .can_transient = true,
663996b3 872};