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 <sys/timerfd.h>
25 #include <sys/epoll.h>
27 #include "systemd/sd-id128.h"
28 #include "systemd/sd-messages.h"
33 #include "load-fragment.h"
34 #include "load-dropin.h"
38 JobBusClient* job_bus_client_new(DBusConnection *connection, const char *name) {
42 name_len = strlen(name);
43 cl = malloc0(sizeof(JobBusClient) + name_len + 1);
48 memcpy(cl->name, name, name_len + 1);
52 Job* job_new_raw(Unit *unit) {
55 /* used for deserialization */
63 j->manager = unit->manager;
65 j->type = _JOB_TYPE_INVALID;
66 j->timer_watch.type = WATCH_INVALID;
71 Job* job_new(Unit *unit, JobType type) {
74 assert(type < _JOB_TYPE_MAX);
76 j = job_new_raw(unit);
80 j->id = j->manager->current_job_id++;
83 /* We don't link it here, that's what job_dependency() is for */
88 void job_free(Job *j) {
92 assert(!j->installed);
93 assert(!j->transaction_prev);
94 assert(!j->transaction_next);
95 assert(!j->subject_list);
96 assert(!j->object_list);
99 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
101 if (j->in_dbus_queue)
102 LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
104 if (j->timer_watch.type != WATCH_INVALID) {
105 assert(j->timer_watch.type == WATCH_JOB_TIMER);
106 assert(j->timer_watch.data.job == j);
107 assert(j->timer_watch.fd >= 0);
109 assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
110 close_nointr_nofail(j->timer_watch.fd);
113 while ((cl = j->bus_client_list)) {
114 LIST_REMOVE(JobBusClient, client, j->bus_client_list, cl);
120 void job_uninstall(Job *j) {
123 assert(j->installed);
125 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
128 /* Detach from next 'bigger' objects */
130 /* daemon-reload should be transparent to job observers */
131 if (j->manager->n_reloading <= 0)
132 bus_job_send_removed_signal(j);
136 unit_add_to_gc_queue(j->unit);
138 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
139 j->installed = false;
142 static bool job_type_allows_late_merge(JobType t) {
143 /* Tells whether it is OK to merge a job of type 't' with an already
145 * Reloads cannot be merged this way. Think of the sequence:
146 * 1. Reload of a daemon is in progress; the daemon has already loaded
147 * its config file, but hasn't completed the reload operation yet.
148 * 2. Edit foo's config file.
149 * 3. Trigger another reload to have the daemon use the new config.
150 * Should the second reload job be merged into the first one, the daemon
151 * would not know about the new config.
152 * JOB_RESTART jobs on the other hand can be merged, because they get
153 * patched into JOB_START after stopping the unit. So if we see a
154 * JOB_RESTART running, it means the unit hasn't stopped yet and at
155 * this time the merge is still allowed. */
156 return t != JOB_RELOAD;
159 static void job_merge_into_installed(Job *j, Job *other) {
160 assert(j->installed);
161 assert(j->unit == other->unit);
163 if (j->type != JOB_NOP)
164 job_type_merge_and_collapse(&j->type, other->type, j->unit);
166 assert(other->type == JOB_NOP);
168 j->override = j->override || other->override;
171 Job* job_install(Job *j) {
175 assert(!j->installed);
176 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
178 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
182 if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
183 job_finish_and_invalidate(uj, JOB_CANCELED, false);
185 /* not conflicting, i.e. mergeable */
187 if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
188 (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
189 job_merge_into_installed(uj, j);
190 log_debug_unit(uj->unit->id,
191 "Merged into installed job %s/%s as %u",
192 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
195 /* already running and not safe to merge into */
196 /* Patch uj to become a merged job and re-run it. */
197 /* XXX It should be safer to queue j to run after uj finishes, but it is
198 * not currently possible to have more than one installed job per unit. */
199 job_merge_into_installed(uj, j);
200 log_debug_unit(uj->unit->id,
201 "Merged into running job, re-running: %s/%s as %u",
202 uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
203 uj->state = JOB_WAITING;
209 /* Install the job */
212 j->manager->n_installed_jobs ++;
213 log_debug_unit(j->unit->id,
214 "Installed new job %s/%s as %u",
215 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
219 int job_install_deserialized(Job *j) {
222 assert(!j->installed);
224 if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
225 log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
229 pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
232 log_debug_unit(j->unit->id,
233 "Unit %s already has a job installed. Not installing deserialized job.",
239 log_debug_unit(j->unit->id,
240 "Reinstalled deserialized job %s/%s as %u",
241 j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
245 JobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
250 /* Adds a new job link, which encodes that the 'subject' job
251 * needs the 'object' job in some way. If 'subject' is NULL
252 * this means the 'anchor' job (i.e. the one the user
253 * explicitly asked for) is the requester. */
255 if (!(l = new0(JobDependency, 1)))
258 l->subject = subject;
260 l->matters = matters;
261 l->conflicts = conflicts;
264 LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
266 LIST_PREPEND(JobDependency, object, object->object_list, l);
271 void job_dependency_free(JobDependency *l) {
275 LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
277 LIST_REMOVE(JobDependency, object, l->object->object_list, l);
282 void job_dump(Job *j, FILE*f, const char *prefix) {
291 "%s\tAction: %s -> %s\n"
295 prefix, j->unit->id, job_type_to_string(j->type),
296 prefix, job_state_to_string(j->state),
297 prefix, yes_no(j->override));
301 * Merging is commutative, so imagine the matrix as symmetric. We store only
302 * its lower triangle to avoid duplication. We don't store the main diagonal,
303 * because A merged with A is simply A.
305 * If the resulting type is collapsed immediately afterwards (to get rid of
306 * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
307 * the following properties hold:
309 * Merging is associative! A merged with B merged with C is the same as
310 * A merged with C merged with B.
312 * Mergeability is transitive! If A can be merged with B and B with C then
315 * Also, if A merged with B cannot be merged with C, then either A or B cannot
316 * be merged with C either.
318 static const JobType job_merging_table[] = {
319 /* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
320 /*********************************************************************************/
322 /*JOB_VERIFY_ACTIVE */ JOB_START,
323 /*JOB_STOP */ -1, -1,
324 /*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
325 /*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
328 JobType job_type_lookup_merge(JobType a, JobType b) {
329 assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
330 assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
331 assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
342 return job_merging_table[(a - 1) * a / 2 + b];
345 bool job_type_is_redundant(JobType a, UnitActiveState b) {
355 b == UNIT_INACTIVE ||
358 case JOB_VERIFY_ACTIVE:
369 b == UNIT_ACTIVATING;
372 assert_not_reached("Invalid job type");
376 void job_type_collapse(JobType *t, Unit *u) {
381 case JOB_TRY_RESTART:
382 s = unit_active_state(u);
383 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
389 case JOB_RELOAD_OR_START:
390 s = unit_active_state(u);
391 if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
402 int job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
403 JobType t = job_type_lookup_merge(*a, b);
407 job_type_collapse(a, u);
411 bool job_is_runnable(Job *j) {
416 assert(j->installed);
418 /* Checks whether there is any job running for the units this
419 * job needs to be running after (in the case of a 'positive'
420 * job type) or before (in the case of a 'negative' job
423 /* First check if there is an override */
427 if (j->type == JOB_NOP)
430 if (j->type == JOB_START ||
431 j->type == JOB_VERIFY_ACTIVE ||
432 j->type == JOB_RELOAD) {
434 /* Immediate result is that the job is or might be
435 * started. In this case lets wait for the
436 * dependencies, regardless whether they are
437 * starting or stopping something. */
439 SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
444 /* Also, if something else is being stopped and we should
445 * change state after it, then lets wait. */
447 SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
449 (other->job->type == JOB_STOP ||
450 other->job->type == JOB_RESTART))
453 /* This means that for a service a and a service b where b
454 * shall be started after a:
456 * start a + start b → 1st step start a, 2nd step start b
457 * start a + stop b → 1st step stop b, 2nd step start a
458 * stop a + start b → 1st step stop a, 2nd step start b
459 * stop a + stop b → 1st step stop b, 2nd step stop a
461 * This has the side effect that restarts are properly
462 * synchronized too. */
467 static void job_change_type(Job *j, JobType newtype) {
468 log_debug_unit(j->unit->id,
469 "Converting job %s/%s -> %s/%s",
470 j->unit->id, job_type_to_string(j->type),
471 j->unit->id, job_type_to_string(newtype));
476 int job_run_and_invalidate(Job *j) {
482 assert(j->installed);
483 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
484 assert(j->in_run_queue);
486 LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
487 j->in_run_queue = false;
489 if (j->state != JOB_WAITING)
492 if (!job_is_runnable(j))
495 j->state = JOB_RUNNING;
496 job_add_to_dbus_queue(j);
498 /* While we execute this operation the job might go away (for
499 * example: because it is replaced by a new, conflicting
500 * job.) To make sure we don't access a freed job later on we
501 * store the id here, so that we can verify the job is still
509 r = unit_start(j->unit);
511 /* If this unit cannot be started, then simply wait */
516 case JOB_VERIFY_ACTIVE: {
517 UnitActiveState t = unit_active_state(j->unit);
518 if (UNIT_IS_ACTIVE_OR_RELOADING(t))
520 else if (t == UNIT_ACTIVATING)
529 r = unit_stop(j->unit);
531 /* If this unit cannot stopped, then simply wait. */
537 r = unit_reload(j->unit);
545 assert_not_reached("Unknown job type");
548 j = manager_get_job(m, id);
551 r = job_finish_and_invalidate(j, JOB_DONE, true);
552 else if (r == -ENOEXEC)
553 r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
554 else if (r == -EAGAIN)
555 j->state = JOB_WAITING;
557 r = job_finish_and_invalidate(j, JOB_FAILED, true);
563 static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
564 const UnitStatusMessageFormats *format_table;
568 assert(t < _JOB_TYPE_MAX);
570 format_table = &UNIT_VTABLE(u)->status_message_formats;
575 return format_table->finished_start_job[result];
576 else if (t == JOB_STOP || t == JOB_RESTART)
577 return format_table->finished_stop_job[result];
582 static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
587 assert(t < _JOB_TYPE_MAX);
589 format = job_get_status_message_format(u, t, result);
593 /* Return generic strings */
594 if (t == JOB_START) {
595 if (result == JOB_DONE)
596 return "Started %s.";
597 else if (result == JOB_FAILED)
598 return "Failed to start %s.";
599 else if (result == JOB_DEPENDENCY)
600 return "Dependency failed for %s.";
601 else if (result == JOB_TIMEOUT)
602 return "Timed out starting %s.";
603 } else if (t == JOB_STOP || t == JOB_RESTART) {
604 if (result == JOB_DONE)
605 return "Stopped %s.";
606 else if (result == JOB_FAILED)
607 return "Stopped (with error) %s.";
608 else if (result == JOB_TIMEOUT)
609 return "Timed out stoppping %s.";
610 } else if (t == JOB_RELOAD) {
611 if (result == JOB_DONE)
612 return "Reloaded %s.";
613 else if (result == JOB_FAILED)
614 return "Reload failed for %s.";
615 else if (result == JOB_TIMEOUT)
616 return "Timed out reloading %s.";
622 static void job_print_status_message(Unit *u, JobType t, JobResult result) {
627 assert(t < _JOB_TYPE_MAX);
629 if (t == JOB_START) {
630 format = job_get_status_message_format(u, t, result);
637 if (u->condition_result)
638 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
642 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
643 unit_status_printf(u, NULL, "See 'systemctl status %s' for details.", u->id);
647 unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format, unit_description(u));
651 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
658 } else if (t == JOB_STOP || t == JOB_RESTART) {
660 format = job_get_status_message_format(u, t, result);
667 unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
672 unit_status_printf(u, ANSI_HIGHLIGHT_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format, unit_description(u));
679 } else if (t == JOB_VERIFY_ACTIVE) {
681 /* When verify-active detects the unit is inactive, report it.
682 * Most likely a DEPEND warning from a requisiting unit will
683 * occur next and it's nice to see what was requisited. */
684 if (result == JOB_SKIPPED)
685 unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.", unit_description(u));
689 #pragma GCC diagnostic push
690 #pragma GCC diagnostic ignored "-Wformat-nonliteral"
691 static void job_log_status_message(Unit *u, JobType t, JobResult result) {
697 assert(t < _JOB_TYPE_MAX);
699 /* Skip this if it goes to the console. since we already print
700 * to the console anyway... */
702 if (log_on_console())
705 format = job_get_status_message_format_try_harder(u, t, result);
709 snprintf(buf, sizeof(buf), format, unit_description(u));
712 if (t == JOB_START) {
715 mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
716 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
719 "RESULT=%s", job_result_to_string(result),
723 } else if (t == JOB_STOP)
724 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
726 MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
727 "RESULT=%s", job_result_to_string(result),
731 else if (t == JOB_RELOAD)
732 log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
734 MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
735 "RESULT=%s", job_result_to_string(result),
739 #pragma GCC diagnostic pop
741 int job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
748 assert(j->installed);
749 assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
756 log_debug_unit(u->id, "Job %s/%s finished, result=%s",
757 u->id, job_type_to_string(t), job_result_to_string(result));
759 job_print_status_message(u, t, result);
760 job_log_status_message(u, t, result);
762 job_add_to_dbus_queue(j);
764 /* Patch restart jobs so that they become normal start jobs */
765 if (result == JOB_DONE && t == JOB_RESTART) {
767 job_change_type(j, JOB_START);
768 j->state = JOB_WAITING;
770 job_add_to_run_queue(j);
775 if (result == JOB_FAILED)
776 j->manager->n_failed_jobs ++;
781 /* Fail depending jobs on failure */
782 if (result != JOB_DONE && recursive) {
784 if (t == JOB_START ||
785 t == JOB_VERIFY_ACTIVE) {
787 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
789 (other->job->type == JOB_START ||
790 other->job->type == JOB_VERIFY_ACTIVE))
791 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
793 SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
795 (other->job->type == JOB_START ||
796 other->job->type == JOB_VERIFY_ACTIVE))
797 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
799 SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
801 !other->job->override &&
802 (other->job->type == JOB_START ||
803 other->job->type == JOB_VERIFY_ACTIVE))
804 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
806 } else if (t == JOB_STOP) {
808 SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
810 (other->job->type == JOB_START ||
811 other->job->type == JOB_VERIFY_ACTIVE))
812 job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
816 /* Trigger OnFailure dependencies that are not generated by
817 * the unit itself. We don't treat JOB_CANCELED as failure in
818 * this context. And JOB_FAILURE is already handled by the
820 if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
821 log_struct_unit(LOG_NOTICE,
823 "JOB_TYPE=%s", job_type_to_string(t),
824 "JOB_RESULT=%s", job_result_to_string(result),
825 "Job %s/%s failed with result '%s'.",
827 job_type_to_string(t),
828 job_result_to_string(result),
831 unit_trigger_on_failure(u);
835 /* Try to start the next jobs that can be started */
836 SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
838 job_add_to_run_queue(other->job);
839 SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
841 job_add_to_run_queue(other->job);
843 manager_check_finished(u->manager);
848 int job_start_timer(Job *j) {
849 struct itimerspec its;
850 struct epoll_event ev;
854 if (j->unit->job_timeout <= 0 ||
855 j->timer_watch.type == WATCH_JOB_TIMER)
858 assert(j->timer_watch.type == WATCH_INVALID);
860 if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC)) < 0) {
866 timespec_store(&its.it_value, j->unit->job_timeout);
868 if (timerfd_settime(fd, 0, &its, NULL) < 0) {
874 ev.data.ptr = &j->timer_watch;
877 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) {
882 j->timer_watch.type = WATCH_JOB_TIMER;
883 j->timer_watch.fd = fd;
884 j->timer_watch.data.job = j;
890 close_nointr_nofail(fd);
895 void job_add_to_run_queue(Job *j) {
897 assert(j->installed);
902 LIST_PREPEND(Job, run_queue, j->manager->run_queue, j);
903 j->in_run_queue = true;
906 void job_add_to_dbus_queue(Job *j) {
908 assert(j->installed);
910 if (j->in_dbus_queue)
913 /* We don't check if anybody is subscribed here, since this
914 * job might just have been created and not yet assigned to a
915 * connection/client. */
917 LIST_PREPEND(Job, dbus_queue, j->manager->dbus_job_queue, j);
918 j->in_dbus_queue = true;
921 char *job_dbus_path(Job *j) {
926 if (asprintf(&p, "/org/freedesktop/systemd1/job/%lu", (unsigned long) j->id) < 0)
932 void job_timer_event(Job *j, uint64_t n_elapsed, Watch *w) {
934 assert(w == &j->timer_watch);
936 log_warning_unit(j->unit->id, "Job %s/%s timed out.",
937 j->unit->id, job_type_to_string(j->type));
938 job_finish_and_invalidate(j, JOB_TIMEOUT, true);
941 int job_serialize(Job *j, FILE *f, FDSet *fds) {
942 fprintf(f, "job-id=%u\n", j->id);
943 fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
944 fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
945 fprintf(f, "job-override=%s\n", yes_no(j->override));
946 fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
947 fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
948 /* Cannot save bus clients. Just note the fact that we're losing
949 * them. job_send_message() will fallback to broadcasting. */
950 fprintf(f, "job-forgot-bus-clients=%s\n",
951 yes_no(j->forgot_bus_clients || j->bus_client_list));
952 if (j->timer_watch.type == WATCH_JOB_TIMER) {
953 int copy = fdset_put_dup(fds, j->timer_watch.fd);
956 fprintf(f, "job-timer-watch-fd=%d\n", copy);
964 int job_deserialize(Job *j, FILE *f, FDSet *fds) {
966 char line[LINE_MAX], *l, *v;
969 if (!fgets(line, sizeof(line), f)) {
990 if (streq(l, "job-id")) {
991 if (safe_atou32(v, &j->id) < 0)
992 log_debug("Failed to parse job id value %s", v);
993 } else if (streq(l, "job-type")) {
994 JobType t = job_type_from_string(v);
996 log_debug("Failed to parse job type %s", v);
997 else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
998 log_debug("Cannot deserialize job of type %s", v);
1001 } else if (streq(l, "job-state")) {
1002 JobState s = job_state_from_string(v);
1004 log_debug("Failed to parse job state %s", v);
1007 } else if (streq(l, "job-override")) {
1008 int b = parse_boolean(v);
1010 log_debug("Failed to parse job override flag %s", v);
1012 j->override = j->override || b;
1013 } else if (streq(l, "job-sent-dbus-new-signal")) {
1014 int b = parse_boolean(v);
1016 log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
1018 j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
1019 } else if (streq(l, "job-ignore-order")) {
1020 int b = parse_boolean(v);
1022 log_debug("Failed to parse job ignore_order flag %s", v);
1024 j->ignore_order = j->ignore_order || b;
1025 } else if (streq(l, "job-forgot-bus-clients")) {
1026 int b = parse_boolean(v);
1028 log_debug("Failed to parse job forgot_bus_clients flag %s", v);
1030 j->forgot_bus_clients = j->forgot_bus_clients || b;
1031 } else if (streq(l, "job-timer-watch-fd")) {
1033 if (safe_atoi(v, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd))
1034 log_debug("Failed to parse job-timer-watch-fd value %s", v);
1036 if (j->timer_watch.type == WATCH_JOB_TIMER)
1037 close_nointr_nofail(j->timer_watch.fd);
1039 j->timer_watch.type = WATCH_JOB_TIMER;
1040 j->timer_watch.fd = fdset_remove(fds, fd);
1041 j->timer_watch.data.job = j;
1047 int job_coldplug(Job *j) {
1048 struct epoll_event ev;
1050 if (j->timer_watch.type != WATCH_JOB_TIMER)
1054 ev.data.ptr = &j->timer_watch;
1055 ev.events = EPOLLIN;
1057 if (epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_ADD, j->timer_watch.fd, &ev) < 0)
1063 static const char* const job_state_table[_JOB_STATE_MAX] = {
1064 [JOB_WAITING] = "waiting",
1065 [JOB_RUNNING] = "running"
1068 DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
1070 static const char* const job_type_table[_JOB_TYPE_MAX] = {
1071 [JOB_START] = "start",
1072 [JOB_VERIFY_ACTIVE] = "verify-active",
1073 [JOB_STOP] = "stop",
1074 [JOB_RELOAD] = "reload",
1075 [JOB_RELOAD_OR_START] = "reload-or-start",
1076 [JOB_RESTART] = "restart",
1077 [JOB_TRY_RESTART] = "try-restart",
1081 DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
1083 static const char* const job_mode_table[_JOB_MODE_MAX] = {
1084 [JOB_FAIL] = "fail",
1085 [JOB_REPLACE] = "replace",
1086 [JOB_ISOLATE] = "isolate",
1087 [JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
1088 [JOB_IGNORE_REQUIREMENTS] = "ignore-requirements"
1091 DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
1093 static const char* const job_result_table[_JOB_RESULT_MAX] = {
1094 [JOB_DONE] = "done",
1095 [JOB_CANCELED] = "canceled",
1096 [JOB_TIMEOUT] = "timeout",
1097 [JOB_FAILED] = "failed",
1098 [JOB_DEPENDENCY] = "dependency",
1099 [JOB_SKIPPED] = "skipped"
1102 DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);