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