chiark / gitweb /
8ed0291ee63ce769efb276f79d92738457aa2125
[elogind.git] / src / core / timer.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <errno.h>
23
24 #include "unit.h"
25 #include "unit-name.h"
26 #include "timer.h"
27 #include "dbus-timer.h"
28 #include "special.h"
29 #include "bus-util.h"
30 #include "bus-error.h"
31 #include "mkdir.h"
32
33 static const UnitActiveState state_translation_table[_TIMER_STATE_MAX] = {
34         [TIMER_DEAD] = UNIT_INACTIVE,
35         [TIMER_WAITING] = UNIT_ACTIVE,
36         [TIMER_RUNNING] = UNIT_ACTIVE,
37         [TIMER_ELAPSED] = UNIT_ACTIVE,
38         [TIMER_FAILED] = UNIT_FAILED
39 };
40
41 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata);
42
43 static void timer_init(Unit *u) {
44         Timer *t = TIMER(u);
45
46         assert(u);
47         assert(u->load_state == UNIT_STUB);
48
49         t->next_elapse_monotonic = (usec_t) -1;
50         t->next_elapse_realtime = (usec_t) -1;
51         t->accuracy_usec = USEC_PER_MINUTE;
52 }
53
54 void timer_free_values(Timer *t) {
55         TimerValue *v;
56
57         assert(t);
58
59         while ((v = t->values)) {
60                 LIST_REMOVE(value, t->values, v);
61
62                 if (v->calendar_spec)
63                         calendar_spec_free(v->calendar_spec);
64
65                 free(v);
66         }
67 }
68
69 static void timer_done(Unit *u) {
70         Timer *t = TIMER(u);
71
72         assert(t);
73
74         timer_free_values(t);
75
76         t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
77         t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
78
79         free(t->stamp_path);
80 }
81
82 static int timer_verify(Timer *t) {
83         assert(t);
84
85         if (UNIT(t)->load_state != UNIT_LOADED)
86                 return 0;
87
88         if (!t->values) {
89                 log_error_unit(UNIT(t)->id, "%s lacks value setting. Refusing.", UNIT(t)->id);
90                 return -EINVAL;
91         }
92
93         return 0;
94 }
95
96 static int timer_add_default_dependencies(Timer *t) {
97         int r;
98
99         assert(t);
100
101         r = unit_add_dependency_by_name(UNIT(t), UNIT_BEFORE, SPECIAL_TIMERS_TARGET, NULL, true);
102         if (r < 0)
103                 return r;
104
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);
107                 if (r < 0)
108                         return r;
109         }
110
111         return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true);
112 }
113
114 static int timer_setup_persistent(Timer *t) {
115         int r;
116
117         assert(t);
118
119         if (!t->persistent)
120                 return 0;
121
122         if (UNIT(t)->manager->running_as == SYSTEMD_SYSTEM) {
123
124                 r = unit_require_mounts_for(UNIT(t), "/var/lib/systemd/timers");
125                 if (r < 0)
126                         return r;
127
128                 t->stamp_path = strappend("/var/lib/systemd/timers/stamp-", UNIT(t)->id);
129         } else {
130                 const char *e;
131
132                 e = getenv("XDG_DATA_HOME");
133                 if (e)
134                         t->stamp_path = strjoin(e, "/systemd/timers/", UNIT(t)->id, NULL);
135                 else {
136
137                         _cleanup_free_ char *h = NULL;
138
139                         r = get_home_dir(&h);
140                         if (r < 0) {
141                                 log_error("Failed to determine home directory: %s", strerror(-r));
142                                 return r;
143                         }
144
145                         t->stamp_path = strjoin(h, "/.local/share/systemd/timers/stamp-", UNIT(t)->id, NULL);
146                 }
147         }
148
149         if (!t->stamp_path)
150                 return log_oom();
151
152         return 0;
153 }
154
155 static int timer_load(Unit *u) {
156         Timer *t = TIMER(u);
157         int r;
158
159         assert(u);
160         assert(u->load_state == UNIT_STUB);
161
162         r = unit_load_fragment_and_dropin(u);
163         if (r < 0)
164                 return r;
165
166         if (u->load_state == UNIT_LOADED) {
167
168                 if (set_isempty(u->dependencies[UNIT_TRIGGERS])) {
169                         Unit *x;
170
171                         r = unit_load_related_unit(u, ".service", &x);
172                         if (r < 0)
173                                 return r;
174
175                         r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, x, true);
176                         if (r < 0)
177                                 return r;
178                 }
179
180                 r = timer_setup_persistent(t);
181                 if (r < 0)
182                         return r;
183
184                 if (u->default_dependencies) {
185                         r = timer_add_default_dependencies(t);
186                         if (r < 0)
187                                 return r;
188                 }
189         }
190
191         return timer_verify(t);
192 }
193
194 static void timer_dump(Unit *u, FILE *f, const char *prefix) {
195         char buf[FORMAT_TIMESPAN_MAX];
196         Timer *t = TIMER(u);
197         Unit *trigger;
198         TimerValue *v;
199
200         trigger = UNIT_TRIGGER(u);
201
202         fprintf(f,
203                 "%sTimer State: %s\n"
204                 "%sResult: %s\n"
205                 "%sUnit: %s\n"
206                 "%sAccuracy: %s\n",
207                 prefix, timer_state_to_string(t->state),
208                 prefix, timer_result_to_string(t->result),
209                 prefix, trigger ? trigger->id : "n/a",
210                 prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1));
211
212         LIST_FOREACH(value, v, t->values) {
213
214                 if (v->base == TIMER_CALENDAR) {
215                         _cleanup_free_ char *p = NULL;
216
217                         calendar_spec_to_string(v->calendar_spec, &p);
218
219                         fprintf(f,
220                                 "%s%s: %s\n",
221                                 prefix,
222                                 timer_base_to_string(v->base),
223                                 strna(p));
224                 } else  {
225                         char timespan1[FORMAT_TIMESPAN_MAX];
226
227                         fprintf(f,
228                                 "%s%s: %s\n",
229                                 prefix,
230                                 timer_base_to_string(v->base),
231                                 strna(format_timespan(timespan1, sizeof(timespan1), v->value, 0)));
232                 }
233         }
234 }
235
236 static void timer_set_state(Timer *t, TimerState state) {
237         TimerState old_state;
238         assert(t);
239
240         old_state = t->state;
241         t->state = state;
242
243         if (state != TIMER_WAITING) {
244                 t->monotonic_event_source = sd_event_source_unref(t->monotonic_event_source);
245                 t->realtime_event_source = sd_event_source_unref(t->realtime_event_source);
246         }
247
248         if (state != old_state)
249                 log_debug_unit(UNIT(t)->id,
250                                "%s changed %s -> %s", UNIT(t)->id,
251                                timer_state_to_string(old_state),
252                                timer_state_to_string(state));
253
254         unit_notify(UNIT(t), state_translation_table[old_state], state_translation_table[state], true);
255 }
256
257 static void timer_enter_waiting(Timer *t, bool initial);
258
259 static int timer_coldplug(Unit *u) {
260         Timer *t = TIMER(u);
261
262         assert(t);
263         assert(t->state == TIMER_DEAD);
264
265         if (t->deserialized_state != t->state) {
266
267                 if (t->deserialized_state == TIMER_WAITING)
268                         timer_enter_waiting(t, false);
269                 else
270                         timer_set_state(t, t->deserialized_state);
271         }
272
273         return 0;
274 }
275
276 static void timer_enter_dead(Timer *t, TimerResult f) {
277         assert(t);
278
279         if (f != TIMER_SUCCESS)
280                 t->result = f;
281
282         timer_set_state(t, t->result != TIMER_SUCCESS ? TIMER_FAILED : TIMER_DEAD);
283 }
284
285 static void timer_enter_waiting(Timer *t, bool initial) {
286         TimerValue *v;
287         usec_t base = 0;
288         dual_timestamp ts;
289         bool found_monotonic = false, found_realtime = false;
290         int r;
291
292         dual_timestamp_get(&ts);
293         t->next_elapse_monotonic = t->next_elapse_realtime = 0;
294
295         LIST_FOREACH(value, v, t->values) {
296
297                 if (v->disabled)
298                         continue;
299
300                 if (v->base == TIMER_CALENDAR) {
301                         usec_t b;
302
303                         /* If we know the last time this was
304                          * triggered, schedule the job based relative
305                          * to that. If we don't just start from
306                          * now. */
307
308                         b = t->last_trigger.realtime > 0 ? t->last_trigger.realtime : ts.realtime;
309
310                         r = calendar_spec_next_usec(v->calendar_spec, b, &v->next_elapse);
311                         if (r < 0)
312                                 continue;
313
314                         if (!found_realtime)
315                                 t->next_elapse_realtime = v->next_elapse;
316                         else
317                                 t->next_elapse_realtime = MIN(t->next_elapse_realtime, v->next_elapse);
318
319                         found_realtime = true;
320
321                 } else  {
322                         switch (v->base) {
323
324                         case TIMER_ACTIVE:
325                                 if (state_translation_table[t->state] == UNIT_ACTIVE)
326                                         base = UNIT(t)->inactive_exit_timestamp.monotonic;
327                                 else
328                                         base = ts.monotonic;
329                                 break;
330
331                         case TIMER_BOOT:
332                                 /* CLOCK_MONOTONIC equals the uptime on Linux */
333                                 base = 0;
334                                 break;
335
336                         case TIMER_STARTUP:
337                                 base = UNIT(t)->manager->userspace_timestamp.monotonic;
338                                 break;
339
340                         case TIMER_UNIT_ACTIVE:
341
342                                 base = UNIT_TRIGGER(UNIT(t))->inactive_exit_timestamp.monotonic;
343
344                                 if (base <= 0)
345                                         base = t->last_trigger.monotonic;
346
347                                 if (base <= 0)
348                                         continue;
349
350                                 break;
351
352                         case TIMER_UNIT_INACTIVE:
353
354                                 base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic;
355
356                                 if (base <= 0)
357                                         base = t->last_trigger.monotonic;
358
359                                 if (base <= 0)
360                                         continue;
361
362                                 break;
363
364                         default:
365                                 assert_not_reached("Unknown timer base");
366                         }
367
368                         v->next_elapse = base + v->value;
369
370                         if (!initial && v->next_elapse < ts.monotonic && IN_SET(v->base, TIMER_ACTIVE, TIMER_BOOT, TIMER_STARTUP)) {
371                                 /* This is a one time trigger, disable it now */
372                                 v->disabled = true;
373                                 continue;
374                         }
375
376                         if (!found_monotonic)
377                                 t->next_elapse_monotonic = v->next_elapse;
378                         else
379                                 t->next_elapse_monotonic = MIN(t->next_elapse_monotonic, v->next_elapse);
380
381                         found_monotonic = true;
382                 }
383         }
384
385         if (!found_monotonic && !found_realtime) {
386                 log_debug_unit(UNIT(t)->id, "%s: Timer is elapsed.", UNIT(t)->id);
387                 timer_set_state(t, TIMER_ELAPSED);
388                 return;
389         }
390
391         if (found_monotonic) {
392                 char buf[FORMAT_TIMESPAN_MAX];
393                 log_debug_unit(UNIT(t)->id, "%s: Monotonic timer elapses in %s.", UNIT(t)->id, format_timespan(buf, sizeof(buf), t->next_elapse_monotonic > ts.monotonic ? t->next_elapse_monotonic - ts.monotonic : 0, 0));
394
395                 if (t->monotonic_event_source) {
396                         r = sd_event_source_set_time(t->monotonic_event_source, t->next_elapse_monotonic);
397                         if (r < 0)
398                                 goto fail;
399
400                         r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_ONESHOT);
401                 } else
402                         r = sd_event_add_monotonic(UNIT(t)->manager->event, &t->monotonic_event_source, t->next_elapse_monotonic, t->accuracy_usec, timer_dispatch, t);
403                 if (r < 0)
404                         goto fail;
405
406         } else if (t->monotonic_event_source) {
407
408                 r = sd_event_source_set_enabled(t->monotonic_event_source, SD_EVENT_OFF);
409                 if (r < 0)
410                         goto fail;
411         }
412
413         if (found_realtime) {
414                 char buf[FORMAT_TIMESTAMP_MAX];
415                 log_debug_unit(UNIT(t)->id, "%s: Realtime timer elapses at %s.", UNIT(t)->id, format_timestamp(buf, sizeof(buf), t->next_elapse_realtime));
416
417                 if (t->realtime_event_source) {
418                         r = sd_event_source_set_time(t->realtime_event_source, t->next_elapse_realtime);
419                         if (r < 0)
420                                 goto fail;
421
422                         r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_ONESHOT);
423                 } else
424                         r = sd_event_add_realtime(UNIT(t)->manager->event, &t->realtime_event_source, t->next_elapse_realtime, t->accuracy_usec, timer_dispatch, t);
425                 if (r < 0)
426                         goto fail;
427
428         } else if (t->realtime_event_source) {
429
430                 r = sd_event_source_set_enabled(t->realtime_event_source, SD_EVENT_OFF);
431                 if (r < 0)
432                         goto fail;
433         }
434
435         timer_set_state(t, TIMER_WAITING);
436         return;
437
438 fail:
439         log_warning_unit(UNIT(t)->id, "%s failed to enter waiting state: %s", UNIT(t)->id, strerror(-r));
440         timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
441 }
442
443 static void timer_enter_running(Timer *t) {
444         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
445         int r;
446
447         assert(t);
448
449         /* Don't start job if we are supposed to go down */
450         if (unit_stop_pending(UNIT(t)))
451                 return;
452
453         r = manager_add_job(UNIT(t)->manager, JOB_START, UNIT_TRIGGER(UNIT(t)),
454                             JOB_REPLACE, true, &error, NULL);
455         if (r < 0)
456                 goto fail;
457
458         dual_timestamp_get(&t->last_trigger);
459
460         if (t->stamp_path) {
461                 _cleanup_close_ int fd = -1;
462
463                 mkdir_parents_label(t->stamp_path, 0755);
464
465                 /* Update the file atime + mtime, if we can */
466                 fd = open(t->stamp_path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
467                 if (fd >= 0) {
468                         struct timespec ts[2];
469
470                         timespec_store(&ts[0], t->last_trigger.realtime);
471                         ts[1] = ts[0];
472
473                         futimens(fd, ts);
474                 }
475         }
476
477         timer_set_state(t, TIMER_RUNNING);
478         return;
479
480 fail:
481         log_warning_unit(UNIT(t)->id,
482                          "%s failed to queue unit startup job: %s",
483                          UNIT(t)->id, bus_error_message(&error, r));
484         timer_enter_dead(t, TIMER_FAILURE_RESOURCES);
485 }
486
487 static int timer_start(Unit *u) {
488         Timer *t = TIMER(u);
489
490         assert(t);
491         assert(t->state == TIMER_DEAD || t->state == TIMER_FAILED);
492
493         if (UNIT_TRIGGER(u)->load_state != UNIT_LOADED)
494                 return -ENOENT;
495
496         t->last_trigger = DUAL_TIMESTAMP_NULL;
497
498         if (t->stamp_path) {
499                 struct stat st;
500
501                 if (stat(t->stamp_path, &st) >= 0)
502                         t->last_trigger.realtime = timespec_load(&st.st_atim);
503         }
504
505         t->result = TIMER_SUCCESS;
506         timer_enter_waiting(t, true);
507         return 0;
508 }
509
510 static int timer_stop(Unit *u) {
511         Timer *t = TIMER(u);
512
513         assert(t);
514         assert(t->state == TIMER_WAITING || t->state == TIMER_RUNNING || t->state == TIMER_ELAPSED);
515
516         timer_enter_dead(t, TIMER_SUCCESS);
517         return 0;
518 }
519
520 static int timer_serialize(Unit *u, FILE *f, FDSet *fds) {
521         Timer *t = TIMER(u);
522
523         assert(u);
524         assert(f);
525         assert(fds);
526
527         unit_serialize_item(u, f, "state", timer_state_to_string(t->state));
528         unit_serialize_item(u, f, "result", timer_result_to_string(t->result));
529
530         if (t->last_trigger.realtime > 0)
531                 unit_serialize_item_format(u, f, "last-trigger-realtime", "%" PRIu64, t->last_trigger.realtime);
532
533         if (t->last_trigger.monotonic > 0)
534                 unit_serialize_item_format(u, f, "last-trigger-monotonic", "%" PRIu64, t->last_trigger.monotonic);
535
536         return 0;
537 }
538
539 static int timer_deserialize_item(Unit *u, const char *key, const char *value, FDSet *fds) {
540         Timer *t = TIMER(u);
541         int r;
542
543         assert(u);
544         assert(key);
545         assert(value);
546         assert(fds);
547
548         if (streq(key, "state")) {
549                 TimerState state;
550
551                 state = timer_state_from_string(value);
552                 if (state < 0)
553                         log_debug_unit(u->id, "Failed to parse state value %s", value);
554                 else
555                         t->deserialized_state = state;
556         } else if (streq(key, "result")) {
557                 TimerResult f;
558
559                 f = timer_result_from_string(value);
560                 if (f < 0)
561                         log_debug_unit(u->id, "Failed to parse result value %s", value);
562                 else if (f != TIMER_SUCCESS)
563                         t->result = f;
564         } else if (streq(key, "last-trigger-realtime")) {
565
566                 r = safe_atou64(value, &t->last_trigger.realtime);
567                 if (r < 0)
568                         log_debug_unit(u->id, "Failed to parse last-trigger-realtime value %s", value);
569
570         } else if (streq(key, "last-trigger-monotonic")) {
571
572                 r = safe_atou64(value, &t->last_trigger.monotonic);
573                 if (r < 0)
574                         log_debug_unit(u->id, "Failed to parse last-trigger-monotonic value %s", value);
575
576         } else
577                 log_debug_unit(u->id, "Unknown serialization key '%s'", key);
578
579         return 0;
580 }
581
582 _pure_ static UnitActiveState timer_active_state(Unit *u) {
583         assert(u);
584
585         return state_translation_table[TIMER(u)->state];
586 }
587
588 _pure_ static const char *timer_sub_state_to_string(Unit *u) {
589         assert(u);
590
591         return timer_state_to_string(TIMER(u)->state);
592 }
593
594 static int timer_dispatch(sd_event_source *s, uint64_t usec, void *userdata) {
595         Timer *t = TIMER(userdata);
596
597         assert(t);
598
599         if (t->state != TIMER_WAITING)
600                 return 0;
601
602         log_debug_unit(UNIT(t)->id, "Timer elapsed on %s", UNIT(t)->id);
603         timer_enter_running(t);
604         return 0;
605 }
606
607 static void timer_trigger_notify(Unit *u, Unit *other) {
608         Timer *t = TIMER(u);
609         TimerValue *v;
610
611         assert(u);
612         assert(other);
613
614         if (other->load_state != UNIT_LOADED)
615                 return;
616
617         /* Reenable all timers that depend on unit state */
618         LIST_FOREACH(value, v, t->values)
619                 if (v->base == TIMER_UNIT_ACTIVE ||
620                     v->base == TIMER_UNIT_INACTIVE)
621                         v->disabled = false;
622
623         switch (t->state) {
624
625         case TIMER_WAITING:
626         case TIMER_ELAPSED:
627
628                 /* Recalculate sleep time */
629                 timer_enter_waiting(t, false);
630                 break;
631
632         case TIMER_RUNNING:
633
634                 if (UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) {
635                         log_debug_unit(UNIT(t)->id, "%s got notified about unit deactivation.", UNIT(t)->id);
636                         timer_enter_waiting(t, false);
637                 }
638                 break;
639
640         case TIMER_DEAD:
641         case TIMER_FAILED:
642                 break;
643
644         default:
645                 assert_not_reached("Unknown timer state");
646         }
647 }
648
649 static void timer_reset_failed(Unit *u) {
650         Timer *t = TIMER(u);
651
652         assert(t);
653
654         if (t->state == TIMER_FAILED)
655                 timer_set_state(t, TIMER_DEAD);
656
657         t->result = TIMER_SUCCESS;
658 }
659
660 static void timer_time_change(Unit *u) {
661         Timer *t = TIMER(u);
662
663         assert(u);
664
665         if (t->state != TIMER_WAITING)
666                 return;
667
668         log_debug_unit(u->id, "%s: time change, recalculating next elapse.", u->id);
669         timer_enter_waiting(t, false);
670 }
671
672 static const char* const timer_state_table[_TIMER_STATE_MAX] = {
673         [TIMER_DEAD] = "dead",
674         [TIMER_WAITING] = "waiting",
675         [TIMER_RUNNING] = "running",
676         [TIMER_ELAPSED] = "elapsed",
677         [TIMER_FAILED] = "failed"
678 };
679
680 DEFINE_STRING_TABLE_LOOKUP(timer_state, TimerState);
681
682 static const char* const timer_base_table[_TIMER_BASE_MAX] = {
683         [TIMER_ACTIVE] = "OnActiveSec",
684         [TIMER_BOOT] = "OnBootSec",
685         [TIMER_STARTUP] = "OnStartupSec",
686         [TIMER_UNIT_ACTIVE] = "OnUnitActiveSec",
687         [TIMER_UNIT_INACTIVE] = "OnUnitInactiveSec",
688         [TIMER_CALENDAR] = "OnCalendar"
689 };
690
691 DEFINE_STRING_TABLE_LOOKUP(timer_base, TimerBase);
692
693 static const char* const timer_result_table[_TIMER_RESULT_MAX] = {
694         [TIMER_SUCCESS] = "success",
695         [TIMER_FAILURE_RESOURCES] = "resources"
696 };
697
698 DEFINE_STRING_TABLE_LOOKUP(timer_result, TimerResult);
699
700 const UnitVTable timer_vtable = {
701         .object_size = sizeof(Timer),
702
703         .sections =
704                 "Unit\0"
705                 "Timer\0"
706                 "Install\0",
707
708         .init = timer_init,
709         .done = timer_done,
710         .load = timer_load,
711
712         .coldplug = timer_coldplug,
713
714         .dump = timer_dump,
715
716         .start = timer_start,
717         .stop = timer_stop,
718
719         .serialize = timer_serialize,
720         .deserialize_item = timer_deserialize_item,
721
722         .active_state = timer_active_state,
723         .sub_state_to_string = timer_sub_state_to_string,
724
725         .trigger_notify = timer_trigger_notify,
726
727         .reset_failed = timer_reset_failed,
728         .time_change = timer_time_change,
729
730         .bus_interface = "org.freedesktop.systemd1.Timer",
731         .bus_vtable = bus_timer_vtable,
732 };