job.c revision 2cba2e03524ec0922ddc70f933e8a89b7d23b4ec
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/***
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering This file is part of systemd.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Copyright 2010 Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering (at your option) any later version.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering systemd is distributed in the hope that it will be useful, but
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Lesser General Public License for more details.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering***/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <assert.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <errno.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/timerfd.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include <sys/epoll.h>
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "sd-id128.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "sd-messages.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "set.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "unit.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "macro.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "strv.h"
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack#include "load-fragment.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "load-dropin.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "log.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "dbus-job.h"
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering#include "special.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "async.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "virt.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#include "dbus-client-track.h"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart PoetteringJob* job_new_raw(Unit *unit) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job *j;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* used for deserialization */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(unit);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j = new0(Job, 1);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!j)
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering return NULL;
4f10118016f9b2fd7e1d26c9ef7d91eb33fba694Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->manager = unit->manager;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->unit = unit;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->type = _JOB_TYPE_INVALID;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return j;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart PoetteringJob* job_new(Unit *unit, JobType type) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Job *j;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(type < _JOB_TYPE_MAX);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j = job_new_raw(unit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!j)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->id = j->manager->current_job_id++;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->type = type;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* We don't link it here, that's what job_dependency() is for */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return j;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_free(Job *j) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!j->installed);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!j->transaction_prev);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!j->transaction_next);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!j->subject_list);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(!j->object_list);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->in_run_queue)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(run_queue, j->manager->run_queue, j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->in_dbus_queue)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_event_source_unref(j->timer_event_source);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bus_client_track_free(j->subscribed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering free(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_uninstall(Job *j) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job **pj;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j->installed);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(*pj == j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Detach from next 'bigger' objects */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* daemon-reload should be transparent to job observers */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (j->manager->n_reloading <= 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering bus_job_send_removed_signal(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *pj = NULL;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_add_to_gc_queue(j->unit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->installed = false;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic bool job_type_allows_late_merge(JobType t) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Tells whether it is OK to merge a job of type 't' with an already
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * running job.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * Reloads cannot be merged this way. Think of the sequence:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * 1. Reload of a daemon is in progress; the daemon has already loaded
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * its config file, but hasn't completed the reload operation yet.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * 2. Edit foo's config file.
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * 3. Trigger another reload to have the daemon use the new config.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Should the second reload job be merged into the first one, the daemon
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * would not know about the new config.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * JOB_RESTART jobs on the other hand can be merged, because they get
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * patched into JOB_START after stopping the unit. So if we see a
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * JOB_RESTART running, it means the unit hasn't stopped yet and at
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * this time the merge is still allowed. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return t != JOB_RELOAD;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void job_merge_into_installed(Job *j, Job *other) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->installed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->unit == other->unit);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->type != JOB_NOP)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_type_merge_and_collapse(&j->type, other->type, j->unit);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(other->type == JOB_NOP);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->override = j->override || other->override;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->irreversible = j->irreversible || other->irreversible;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->ignore_order = j->ignore_order || other->ignore_order;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringJob* job_install(Job *j) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job **pj;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job *uj;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(!j->installed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uj = *pj;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (uj) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_finish_and_invalidate(uj, JOB_CANCELED, false);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* not conflicting, i.e. mergeable */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_merge_into_installed(uj, j);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack log_debug_unit(uj->unit->id,
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack "Merged into installed job %s/%s as %u",
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return uj;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack } else {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* already running and not safe to merge into */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* Patch uj to become a merged job and re-run it. */
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack /* XXX It should be safer to queue j to run after uj finishes, but it is
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * not currently possible to have more than one installed job per unit. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_merge_into_installed(uj, j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug_unit(uj->unit->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Merged into running job, re-running: %s/%s as %u",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uj->state = JOB_WAITING;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering uj->manager->n_running_jobs--;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return uj;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Install the job */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *pj = j;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->installed = true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->manager->n_installed_jobs ++;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug_unit(j->unit->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Installed new job %s/%s as %u",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return j;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint job_install_deserialized(Job *j) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job **pj;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(!j->installed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EINVAL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (*pj) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug_unit(j->unit->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Unit %s already has a job installed. Not installing deserialized job.",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->unit->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return -EEXIST;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *pj = j;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->installed = true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug_unit(j->unit->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "Reinstalled deserialized job %s/%s as %u",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringJobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering JobDependency *l;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(object);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Adds a new job link, which encodes that the 'subject' job
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * needs the 'object' job in some way. If 'subject' is NULL
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * this means the 'anchor' job (i.e. the one the user
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * explicitly asked for) is the requester. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!(l = new0(JobDependency, 1)))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering l->subject = subject;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering l->object = object;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering l->matters = matters;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering l->conflicts = conflicts;
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (subject)
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering LIST_PREPEND(subject, subject->subject_list, l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_PREPEND(object, object->object_list, l);
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return l;
3f9da416457c4265b8f1179516a32ad1a987ff7dLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_dependency_free(JobDependency *l) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(l);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (l->subject)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(subject, l->subject->subject_list, l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_REMOVE(object, l->object->object_list, l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering free(l);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_dump(Job *j, FILE*f, const char *prefix) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(f);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!prefix)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering prefix = "";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s-> Job %u:\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tAction: %s -> %s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tState: %s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tForced: %s\n"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "%s\tIrreversible: %s\n",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering prefix, j->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering prefix, j->unit->id, job_type_to_string(j->type),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering prefix, job_state_to_string(j->state),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering prefix, yes_no(j->override),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering prefix, yes_no(j->irreversible));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Merging is commutative, so imagine the matrix as symmetric. We store only
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * its lower triangle to avoid duplication. We don't store the main diagonal,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * because A merged with A is simply A.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * If the resulting type is collapsed immediately afterwards (to get rid of
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * the following properties hold:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Merging is associative! A merged with B merged with C is the same as
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * A merged with C merged with B.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Mergeability is transitive! If A can be merged with B and B with C then
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * A also with C.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * Also, if A merged with B cannot be merged with C, then either A or B cannot
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * be merged with C either.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic const JobType job_merging_table[] = {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*********************************************************************************/
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*JOB_START */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*JOB_VERIFY_ACTIVE */ JOB_START,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*JOB_STOP */ -1, -1,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering};
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart PoetteringJobType job_type_lookup_merge(JobType a, JobType b) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (a == b)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return a;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (a < b) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering JobType tmp = a;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering a = b;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b = tmp;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return job_merging_table[(a - 1) * a / 2 + b];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringbool job_type_is_redundant(JobType a, UnitActiveState b) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch (a) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_START:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering b == UNIT_ACTIVE ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering b == UNIT_RELOADING;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_STOP:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering b == UNIT_INACTIVE ||
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering b == UNIT_FAILED;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_VERIFY_ACTIVE:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b == UNIT_ACTIVE ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b == UNIT_RELOADING;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_RELOAD:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b == UNIT_RELOADING;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_RESTART:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering b == UNIT_ACTIVATING;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering default:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert_not_reached("Invalid job type");
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringvoid job_type_collapse(JobType *t, Unit *u) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering UnitActiveState s;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch (*t) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_TRY_RESTART:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering s = unit_active_state(u);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *t = JOB_NOP;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *t = JOB_RESTART;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_RELOAD_OR_START:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering s = unit_active_state(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *t = JOB_START;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering else
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *t = JOB_RELOAD;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering default:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering JobType t = job_type_lookup_merge(*a, b);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (t < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -EEXIST;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *a = t;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_type_collapse(a, u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic bool job_is_runnable(Job *j) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Iterator i;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Unit *other;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j->installed);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Checks whether there is any job running for the units this
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * job needs to be running after (in the case of a 'positive'
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * job type) or before (in the case of a 'negative' job
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * type. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Note that unit types have a say in what is runnable,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * too. For example, if they return -EAGAIN from
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * unit_start() they can indicate they are not
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * runnable yet. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* First check if there is an override */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (j->ignore_order)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (j->type == JOB_NOP)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (j->type == JOB_START ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->type == JOB_VERIFY_ACTIVE ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->type == JOB_RELOAD) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Immediate result is that the job is or might be
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * started. In this case lets wait for the
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * dependencies, regardless whether they are
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * starting or stopping something. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (other->job)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return false;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Also, if something else is being stopped and we should
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * change state after it, then lets wait. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (other->job &&
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (other->job->type == JOB_STOP ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering other->job->type == JOB_RESTART))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return false;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* This means that for a service a and a service b where b
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * shall be started after a:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering *
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * start a + start b → 1st step start a, 2nd step start b
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * start a + stop b → 1st step stop b, 2nd step start a
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * stop a + start b → 1st step stop a, 2nd step start b
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * stop a + stop b → 1st step stop b, 2nd step stop a
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering *
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * This has the side effect that restarts are properly
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * synchronized too. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringstatic void job_change_type(Job *j, JobType newtype) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug_unit(j->unit->id,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "Converting job %s/%s -> %s/%s",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->unit->id, job_type_to_string(j->type),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->unit->id, job_type_to_string(newtype));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->type = newtype;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint job_run_and_invalidate(Job *j) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering int r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering uint32_t id;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering Manager *m = j->manager;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j->installed);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j->in_run_queue);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering LIST_REMOVE(run_queue, j->manager->run_queue, j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->in_run_queue = false;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (j->state != JOB_WAITING)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return 0;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack if (!job_is_runnable(j))
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return -EAGAIN;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack j->state = JOB_RUNNING;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack m->n_running_jobs++;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack job_add_to_dbus_queue(j);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* While we execute this operation the job might go away (for
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * example: because it is replaced by a new, conflicting
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * job.) To make sure we don't access a freed job later on we
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * store the id here, so that we can verify the job is still
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * valid. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering id = j->id;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering switch (j->type) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_START:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = unit_start(j->unit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* If this unit cannot be started, then simply wait */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r == -EBADR)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_VERIFY_ACTIVE: {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering UnitActiveState t = unit_active_state(j->unit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (UNIT_IS_ACTIVE_OR_RELOADING(t))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = -EALREADY;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering else if (t == UNIT_ACTIVATING)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = -EAGAIN;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering else
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = -EBADR;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_STOP:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_RESTART:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = unit_stop(j->unit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* If this unit cannot stopped, then simply wait. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r == -EBADR)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_RELOAD:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = unit_reload(j->unit);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_NOP:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = -EALREADY;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering default:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert_not_reached("Unknown job type");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j = manager_get_job(m, id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (r == -EALREADY)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_DONE, true);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (r == -EBADR)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (r == -ENOEXEC)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_INVALID, true);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack else if (r == -EAGAIN) {
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack j->state = JOB_WAITING;
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack m->n_running_jobs--;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (r < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering r = job_finish_and_invalidate(j, JOB_FAILED, true);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return r;
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering}
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
ff975efb2e88dcd5221a2f0d76c4c87e85b821a8Lennart Poettering_pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering const UnitStatusMessageFormats *format_table;
16ac401407959cbc62312e61c2dd76dbc3a0793bLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(u);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(t >= 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(t < _JOB_TYPE_MAX);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format_table = &UNIT_VTABLE(u)->status_message_formats;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!format_table)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (t == JOB_START)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return format_table->finished_start_job[result];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (t == JOB_STOP || t == JOB_RESTART)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return format_table->finished_stop_job[result];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering_pure_ static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const char *format;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(u);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(t >= 0);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(t < _JOB_TYPE_MAX);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format = job_get_status_message_format(u, t, result);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (format)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return format;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Return generic strings */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (t == JOB_START) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (result == JOB_DONE)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Started %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering else if (result == JOB_FAILED)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Failed to start %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering else if (result == JOB_DEPENDENCY)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Dependency failed for %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering else if (result == JOB_TIMEOUT)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return "Timed out starting %s.";
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering } else if (t == JOB_STOP || t == JOB_RESTART) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result == JOB_DONE)
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack return "Stopped %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (result == JOB_FAILED)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Stopped (with error) %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (result == JOB_TIMEOUT)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Timed out stoppping %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_RELOAD) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (result == JOB_DONE)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Reloaded %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (result == JOB_FAILED)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Reload failed for %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (result == JOB_TIMEOUT)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return "Timed out reloading %s.";
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return NULL;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic push
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic ignored "-Wformat-nonliteral"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void job_print_status_message(Unit *u, JobType t, JobResult result) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const char *format;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(t >= 0);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(t < _JOB_TYPE_MAX);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (t == JOB_START) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering format = job_get_status_message_format(u, t, result);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (!format)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering switch (result) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering case JOB_DONE:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (u->condition_result)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_FAILED:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering manager_status_printf(u->manager, false, NULL, "See 'systemctl status %s' for details.", u->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_DEPENDENCY:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_TIMEOUT:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering default:
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering ;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_STOP || t == JOB_RESTART) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format = job_get_status_message_format(u, t, result);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!format)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering switch (result) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_TIMEOUT:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_DONE:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering case JOB_FAILED:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering break;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering default:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering ;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_VERIFY_ACTIVE) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* When verify-active detects the unit is inactive, report it.
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * Most likely a DEPEND warning from a requisiting unit will
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering * occur next and it's nice to see what was requisited. */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (result == JOB_SKIPPED)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic pop
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic push
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic ignored "-Wformat-nonliteral"
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic void job_log_status_message(Unit *u, JobType t, JobResult result) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering const char *format;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char buf[LINE_MAX];
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(t >= 0);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(t < _JOB_TYPE_MAX);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Skip this if it goes to the console. since we already print
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * to the console anyway... */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (log_on_console())
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering format = job_get_status_message_format_try_harder(u, t, result);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!format)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return;
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering snprintf(buf, sizeof(buf), format, unit_description(u));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char_array_0(buf);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (t == JOB_START) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering sd_id128_t mid;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering u->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MESSAGE_ID(mid),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "RESULT=%s", job_result_to_string(result),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "MESSAGE=%s", buf,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else if (t == JOB_STOP)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering u->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "RESULT=%s", job_result_to_string(result),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "MESSAGE=%s", buf,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering else if (t == JOB_RELOAD)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_struct_unit(result == JOB_DONE ? LOG_INFO : LOG_ERR,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering u->id,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "RESULT=%s", job_result_to_string(result),
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering "MESSAGE=%s", buf,
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering NULL);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering#pragma GCC diagnostic pop
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint job_finish_and_invalidate(Job *j, JobResult result, bool recursive) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Unit *u;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Unit *other;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering JobType t;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Iterator i;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->installed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering u = j->unit;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering t = j->type;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->result = result;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (j->state == JOB_RUNNING)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->manager->n_running_jobs--;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_debug_unit(u->id, "Job %s/%s finished, result=%s",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->id, job_type_to_string(t), job_result_to_string(result));
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_print_status_message(u, t, result);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_log_status_message(u, t, result);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_add_to_dbus_queue(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Patch restart jobs so that they become normal start jobs */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result == JOB_DONE && t == JOB_RESTART) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_change_type(j, JOB_START);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->state = JOB_WAITING;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_add_to_run_queue(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering goto finish;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result == JOB_FAILED || result == JOB_INVALID)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->manager->n_failed_jobs ++;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_uninstall(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_free(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Fail depending jobs on failure */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result != JOB_DONE && recursive) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (t == JOB_START ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering t == JOB_VERIFY_ACTIVE) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (other->job &&
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (other->job->type == JOB_START ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering other->job->type == JOB_VERIFY_ACTIVE))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_BOUND_BY], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (other->job &&
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (other->job->type == JOB_START ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering other->job->type == JOB_VERIFY_ACTIVE))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_REQUIRED_BY_OVERRIDABLE], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (other->job &&
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering !other->job->override &&
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (other->job->type == JOB_START ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering other->job->type == JOB_VERIFY_ACTIVE))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering } else if (t == JOB_STOP) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering SET_FOREACH(other, u->dependencies[UNIT_CONFLICTED_BY], i)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (other->job &&
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering (other->job->type == JOB_START ||
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering other->job->type == JOB_VERIFY_ACTIVE))
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_finish_and_invalidate(other->job, JOB_DEPENDENCY, true);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering /* Trigger OnFailure dependencies that are not generated by
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * the unit itself. We don't treat JOB_CANCELED as failure in
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * this context. And JOB_FAILURE is already handled by the
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * unit itself. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (result == JOB_TIMEOUT || result == JOB_DEPENDENCY) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering log_struct_unit(LOG_NOTICE,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->id,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "JOB_TYPE=%s", job_type_to_string(t),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "JOB_RESULT=%s", job_result_to_string(result),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering "Job %s/%s failed with result '%s'.",
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering u->id,
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_type_to_string(t),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering job_result_to_string(result),
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering NULL);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering unit_start_on_failure(u);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering unit_trigger_notify(u);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringfinish:
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* Try to start the next jobs that can be started */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, u->dependencies[UNIT_AFTER], i)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (other->job)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_add_to_run_queue(other->job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering SET_FOREACH(other, u->dependencies[UNIT_BEFORE], i)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (other->job)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering job_add_to_run_queue(other->job);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering manager_check_finished(u->manager);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringstatic int job_dispatch_timer(sd_event_source *s, uint64_t monotonic, void *userdata) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering Job *j = userdata;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(s == j->timer_event_source);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_warning_unit(j->unit->id, "Job %s/%s timed out.",
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->unit->id, job_type_to_string(j->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering job_finish_and_invalidate(j, JOB_TIMEOUT, true);
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering return 0;
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering}
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poetteringint job_start_timer(Job *j) {
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering int r;
2f671520ebade4877cbf6aca3572a5f8c4e1871dLennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->timer_event_source)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering j->begin_usec = now(CLOCK_MONOTONIC);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (j->unit->job_timeout <= 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (r < 0)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return r;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_add_to_run_queue(Job *j) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j->installed);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering if (j->in_run_queue)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!j->manager->run_queue)
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering sd_event_source_set_enabled(j->manager->run_queue_event_source, SD_EVENT_ONESHOT);
5892a914d173e4b968d2a14fbf717373dee3999aDaniel Mack
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering LIST_PREPEND(run_queue, j->manager->run_queue, j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering j->in_run_queue = true;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering}
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringvoid job_add_to_dbus_queue(Job *j) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering assert(j->installed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->in_dbus_queue)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* We don't check if anybody is subscribed here, since this
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * job might just have been created and not yet assigned to a
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering * connection/client. */
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering LIST_PREPEND(dbus_queue, j->manager->dbus_job_queue, j);
700ff4d97311902a440109a2c081731ab6ae8a20Lennart Poettering j->in_dbus_queue = true;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringchar *job_dbus_path(Job *j) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char *p;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack assert(j);
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack if (asprintf(&p, "/org/freedesktop/systemd1/job/%"PRIu32, j->id) < 0)
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack return NULL;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack return p;
54d76c92868838e17d6aad0a3bb0cc7a5b11e35fDaniel Mack}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poetteringint job_serialize(Job *j, FILE *f, FDSet *fds) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-id=%u\n", j->id);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-type=%s\n", job_type_to_string(j->type));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-state=%s\n", job_state_to_string(j->state));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-override=%s\n", yes_no(j->override));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-irreversible=%s\n", yes_no(j->irreversible));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-sent-dbus-new-signal=%s\n", yes_no(j->sent_dbus_new_signal));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-ignore-order=%s\n", yes_no(j->ignore_order));
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (j->begin_usec > 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fprintf(f, "job-begin="USEC_FMT"\n", j->begin_usec);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering bus_client_track_serialize(j->manager, f, j->subscribed);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* End marker */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering fputc('\n', f);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering}
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poetteringint job_deserialize(Job *j, FILE *f, FDSet *fds) {
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering assert(j);
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering for (;;) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char line[LINE_MAX], *l, *v;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering size_t k;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (!fgets(line, sizeof(line), f)) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (feof(f))
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering return -errno;
a4152e3fe28b53b8919cc404dd7eca7ead1bf9bdLennart Poettering }
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering char_array_0(line);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering l = strstrip(line);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering /* End marker */
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (l[0] == 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering return 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering k = strcspn(l, "=");
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (l[k] == '=') {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering l[k] = 0;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering v = l+k+1;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering } else
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering v = l+k;
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (streq(l, "job-id")) {
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering if (safe_atou32(v, &j->id) < 0)
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering log_debug("Failed to parse job id value %s", v);
e821075a23fdfa3ca7738fc30bb2d4c430fe10c0Lennart Poettering
} else if (streq(l, "job-type")) {
JobType t;
t = job_type_from_string(v);
if (t < 0)
log_debug("Failed to parse job type %s", v);
else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
log_debug("Cannot deserialize job of type %s", v);
else
j->type = t;
} else if (streq(l, "job-state")) {
JobState s;
s = job_state_from_string(v);
if (s < 0)
log_debug("Failed to parse job state %s", v);
else
j->state = s;
} else if (streq(l, "job-override")) {
int b;
b = parse_boolean(v);
if (b < 0)
log_debug("Failed to parse job override flag %s", v);
else
j->override = j->override || b;
} else if (streq(l, "job-irreversible")) {
int b;
b = parse_boolean(v);
if (b < 0)
log_debug("Failed to parse job irreversible flag %s", v);
else
j->irreversible = j->irreversible || b;
} else if (streq(l, "job-sent-dbus-new-signal")) {
int b;
b = parse_boolean(v);
if (b < 0)
log_debug("Failed to parse job sent_dbus_new_signal flag %s", v);
else
j->sent_dbus_new_signal = j->sent_dbus_new_signal || b;
} else if (streq(l, "job-ignore-order")) {
int b;
b = parse_boolean(v);
if (b < 0)
log_debug("Failed to parse job ignore_order flag %s", v);
else
j->ignore_order = j->ignore_order || b;
} else if (streq(l, "job-begin")) {
unsigned long long ull;
if (sscanf(v, "%llu", &ull) != 1)
log_debug("Failed to parse job-begin value %s", v);
else
j->begin_usec = ull;
} else {
char t[strlen(l) + 1 + strlen(v) + 1];
strcpy(stpcpy(stpcpy(t, l), "="), v);
if (bus_client_track_deserialize_item(j->manager, &j->subscribed, t) == 0)
log_debug("Unknown deserialization key '%s'", l);
}
}
}
int job_coldplug(Job *j) {
int r;
assert(j);
if (j->begin_usec <= 0)
return 0;
if (j->timer_event_source)
j->timer_event_source = sd_event_source_unref(j->timer_event_source);
r = sd_event_add_monotonic(j->manager->event, j->begin_usec + j->unit->job_timeout, 0, job_dispatch_timer, j, &j->timer_event_source);
if (r < 0)
log_debug("Failed to restart timeout for job: %s", strerror(-r));
return r;
}
void job_shutdown_magic(Job *j) {
assert(j);
/* The shutdown target gets some special treatment here: we
* tell the kernel to begin with flushing its disk caches, to
* optimize shutdown time a bit. Ideally we wouldn't hardcode
* this magic into PID 1. However all other processes aren't
* options either since they'd exit much sooner than PID 1 and
* asynchronous sync() would cause their exit to be
* delayed. */
if (j->type != JOB_START)
return;
if (j->unit->manager->running_as != SYSTEMD_SYSTEM)
return;
if (!unit_has_name(j->unit, SPECIAL_SHUTDOWN_TARGET))
return;
/* In case messages on console has been disabled on boot */
j->unit->manager->no_console_output = false;
if (detect_container(NULL) > 0)
return;
asynchronous_sync();
}
int job_get_timeout(Job *j, uint64_t *timeout) {
Unit *u = j->unit;
uint64_t x = -1, y = -1;
int r = 0, q = 0;
assert(u);
if (j->timer_event_source) {
r = sd_event_source_get_time(j->timer_event_source, &x);
if (r < 0)
return r;
r = 1;
}
if (UNIT_VTABLE(u)->get_timeout) {
q = UNIT_VTABLE(u)->get_timeout(u, &y);
if (q < 0)
return q;
}
if (r == 0 && q == 0)
return 0;
*timeout = MIN(x, y);
log_info("job_get_timeout %s %d/%"PRIu64" %d/%"PRIu64" -> 1/%"PRIu64,
j->unit->id, r, x, q, y, *timeout);
return 1;
}
static const char* const job_state_table[_JOB_STATE_MAX] = {
[JOB_WAITING] = "waiting",
[JOB_RUNNING] = "running"
};
DEFINE_STRING_TABLE_LOOKUP(job_state, JobState);
static const char* const job_type_table[_JOB_TYPE_MAX] = {
[JOB_START] = "start",
[JOB_VERIFY_ACTIVE] = "verify-active",
[JOB_STOP] = "stop",
[JOB_RELOAD] = "reload",
[JOB_RELOAD_OR_START] = "reload-or-start",
[JOB_RESTART] = "restart",
[JOB_TRY_RESTART] = "try-restart",
[JOB_NOP] = "nop",
};
DEFINE_STRING_TABLE_LOOKUP(job_type, JobType);
static const char* const job_mode_table[_JOB_MODE_MAX] = {
[JOB_FAIL] = "fail",
[JOB_REPLACE] = "replace",
[JOB_REPLACE_IRREVERSIBLY] = "replace-irreversibly",
[JOB_ISOLATE] = "isolate",
[JOB_IGNORE_DEPENDENCIES] = "ignore-dependencies",
[JOB_IGNORE_REQUIREMENTS] = "ignore-requirements",
[JOB_FLUSH] = "flush",
};
DEFINE_STRING_TABLE_LOOKUP(job_mode, JobMode);
static const char* const job_result_table[_JOB_RESULT_MAX] = {
[JOB_DONE] = "done",
[JOB_CANCELED] = "canceled",
[JOB_TIMEOUT] = "timeout",
[JOB_FAILED] = "failed",
[JOB_DEPENDENCY] = "dependency",
[JOB_SKIPPED] = "skipped",
[JOB_INVALID] = "invalid",
};
DEFINE_STRING_TABLE_LOOKUP(job_result, JobResult);