job.c revision cb8ccb2271727fc114ca43104d3333ee4635cc79
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering This file is part of systemd.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Copyright 2010 Lennart Poettering
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is free software; you can redistribute it and/or modify it
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering under the terms of the GNU Lesser General Public License as published by
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering (at your option) any later version.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering systemd is distributed in the hope that it will be useful, but
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering Lesser General Public License for more details.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering You should have received a copy of the GNU Lesser General Public License
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering /* used for deserialization */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* We don't link it here, that's what job_dependency() is for */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(run_queue, j->manager->run_queue, j);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering sd_event_source_unref(j->timer_event_source);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Detach from next 'bigger' objects */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* daemon-reload should be transparent to job observers */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic bool job_type_allows_late_merge(JobType t) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek /* Tells whether it is OK to merge a job of type 't' with an already
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek * Reloads cannot be merged this way. Think of the sequence:
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek * 1. Reload of a daemon is in progress; the daemon has already loaded
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering * its config file, but hasn't completed the reload operation yet.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * 2. Edit foo's config file.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * 3. Trigger another reload to have the daemon use the new config.
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek * Should the second reload job be merged into the first one, the daemon
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek * would not know about the new config.
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek * JOB_RESTART jobs on the other hand can be merged, because they get
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * patched into JOB_START after stopping the unit. So if we see a
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek * JOB_RESTART running, it means the unit hasn't stopped yet and at
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek * this time the merge is still allowed. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void job_merge_into_installed(Job *j, Job *other) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert(j->unit == other->unit);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek job_type_merge_and_collapse(&j->type, other->type, j->unit);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert(other->type == JOB_NOP);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek j->override = j->override || other->override;
4b8268f843b0da1cfe1995d93a0b1f95faccc454Zbigniew Jędrzejewski-Szmek j->irreversible = j->irreversible || other->irreversible;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek j->ignore_order = j->ignore_order || other->ignore_order;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (j->type != JOB_NOP && job_type_is_conflicting(uj->type, j->type))
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek job_finish_and_invalidate(uj, JOB_CANCELED, false);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek /* not conflicting, i.e. mergeable */
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek if (j->type == JOB_NOP || uj->state == JOB_WAITING ||
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek (job_type_allows_late_merge(j->type) && job_type_is_superset(uj->type, j->type))) {
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek job_merge_into_installed(uj, j);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "Merged into installed job %s/%s as %u",
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek /* already running and not safe to merge into */
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek /* Patch uj to become a merged job and re-run it. */
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek /* XXX It should be safer to queue j to run after uj finishes, but it is
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek * not currently possible to have more than one installed job per unit. */
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek job_merge_into_installed(uj, j);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek "Merged into running job, re-running: %s/%s as %u",
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek uj->unit->id, job_type_to_string(uj->type), (unsigned) uj->id);
baf167ee0a2953f98e4e7d4c35752ef737832674Zbigniew Jędrzejewski-Szmek /* Install the job */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "Installed new job %s/%s as %u",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering if (j->type < 0 || j->type >= _JOB_TYPE_MAX_IN_TRANSACTION) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt log_debug("Invalid job type %s in deserialization.", strna(job_type_to_string(j->type)));
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek pj = (j->type == JOB_NOP) ? &j->unit->nop_job : &j->unit->job;
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek "Unit %s already has a job installed. Not installing deserialized job.",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "Reinstalled deserialized job %s/%s as %u",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering j->unit->id, job_type_to_string(j->type), (unsigned) j->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringJobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Adds a new job link, which encodes that the 'subject' job
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * needs the 'object' job in some way. If 'subject' is NULL
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * this means the 'anchor' job (i.e. the one the user
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * explicitly asked for) is the requester. */
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek LIST_PREPEND(subject, subject->subject_list, l);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_PREPEND(object, object->object_list, l);
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmekvoid job_dependency_free(JobDependency *l) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(subject, l->subject->subject_list, l);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek LIST_REMOVE(object, l->object->object_list, l);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringvoid job_dump(Job *j, FILE*f, const char *prefix) {
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek "%s-> Job %u:\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%s\tAction: %s -> %s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%s\tState: %s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%s\tForced: %s\n"
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "%s\tIrreversible: %s\n",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering prefix, j->unit->id, job_type_to_string(j->type),
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek prefix, job_state_to_string(j->state),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * Merging is commutative, so imagine the matrix as symmetric. We store only
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * its lower triangle to avoid duplication. We don't store the main diagonal,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * because A merged with A is simply A.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * If the resulting type is collapsed immediately afterwards (to get rid of
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * the JOB_RELOAD_OR_START, which lies outside the lookup function's domain),
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * the following properties hold:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * Merging is associative! A merged with B merged with C is the same as
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * A merged with C merged with B.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * Mergeability is transitive! If A can be merged with B and B with C then
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * A also with C.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * Also, if A merged with B cannot be merged with C, then either A or B cannot
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * be merged with C either.
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic const JobType job_merging_table[] = {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/* What \ With * JOB_START JOB_VERIFY_ACTIVE JOB_STOP JOB_RELOAD */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*********************************************************************************/
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*JOB_RELOAD */ JOB_RELOAD_OR_START, JOB_RELOAD, -1,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering/*JOB_RESTART */ JOB_RESTART, JOB_RESTART, -1, JOB_RESTART,
d4205751d4643c272059a3728045929dd0e5e800Lennart PoetteringJobType job_type_lookup_merge(JobType a, JobType b) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert_cc(ELEMENTSOF(job_merging_table) == _JOB_TYPE_MAX_MERGING * (_JOB_TYPE_MAX_MERGING - 1) / 2);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(a >= 0 && a < _JOB_TYPE_MAX_MERGING);
c7332b0844e28d9b70c3c763b929f105c1056fe8Zbigniew Jędrzejewski-Szmek assert(b >= 0 && b < _JOB_TYPE_MAX_MERGING);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek return job_merging_table[(a - 1) * a / 2 + b];
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekbool job_type_is_redundant(JobType a, UnitActiveState b) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek assert_not_reached("Invalid job type");
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmekvoid job_type_collapse(JobType *t, Unit *u) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s))
dacd6cee76a08331b8c8616c5f30f70ee49aa2f9Lennart Poetteringint job_type_merge_and_collapse(JobType *a, JobType b, Unit *u) {
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek JobType t = job_type_lookup_merge(*a, b);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Checks whether there is any job running for the units this
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek * job needs to be running after (in the case of a 'positive'
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek * job type) or before (in the case of a 'negative' job
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Note that unit types have a say in what is runnable,
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * too. For example, if they return -EAGAIN from
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek * unit_start() they can indicate they are not
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * runnable yet. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* First check if there is an override */
e3b9d9c8027a7c4c55cf1614e0fe9423fad69e8fZbigniew Jędrzejewski-Szmek j->type == JOB_VERIFY_ACTIVE ||
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Immediate result is that the job is or might be
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * started. In this case lets wait for the
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * dependencies, regardless whether they are
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * starting or stopping something. */
80343dc19a9bcd703275ad2ad88f43e5310559d6Zbigniew Jędrzejewski-Szmek SET_FOREACH(other, j->unit->dependencies[UNIT_AFTER], i)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Also, if something else is being stopped and we should
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * change state after it, then lets wait. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering SET_FOREACH(other, j->unit->dependencies[UNIT_BEFORE], i)
18cd5fe99f70a55a2d6f2303d6ee0624942695b1Zbigniew Jędrzejewski-Szmek /* This means that for a service a and a service b where b
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * shall be started after a:
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * start a + start b → 1st step start a, 2nd step start b
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * start a + stop b → 1st step stop b, 2nd step start a
7ff7394d9e4e9189c30fd018235e6b1728c6f2d0Zbigniew Jędrzejewski-Szmek * stop a + start b → 1st step stop a, 2nd step start b
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * stop a + stop b → 1st step stop b, 2nd step stop a
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek * This has the side effect that restarts are properly
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt * synchronized too. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poetteringstatic void job_change_type(Job *j, JobType newtype) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering "Converting job %s/%s -> %s/%s",
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering j->unit->id, job_type_to_string(j->type),
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek j->unit->id, job_type_to_string(newtype));
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering assert(j->type < _JOB_TYPE_MAX_IN_TRANSACTION);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering LIST_REMOVE(run_queue, j->manager->run_queue, j);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* While we execute this operation the job might go away (for
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering * example: because it is replaced by a new, conflicting
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * job.) To make sure we don't access a freed job later on we
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering * store the id here, so that we can verify the job is still
03e334a1c7dc8c20c38902aa039440763acc9b17Lennart Poettering /* If this unit cannot be started, then simply wait */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering UnitActiveState t = unit_active_state(j->unit);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* If this unit cannot stopped, then simply wait. */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = job_finish_and_invalidate(j, JOB_DONE, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (r == -EBADR)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = job_finish_and_invalidate(j, JOB_SKIPPED, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (r == -ENOEXEC)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = job_finish_and_invalidate(j, JOB_INVALID, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (r == -EAGAIN) {
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering } else if (r < 0)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering r = job_finish_and_invalidate(j, JOB_FAILED, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering_pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering const UnitStatusMessageFormats *format_table;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering format_table = &UNIT_VTABLE(u)->status_message_formats;
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return format_table->finished_start_job[result];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering else if (t == JOB_STOP || t == JOB_RESTART)
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return format_table->finished_stop_job[result];
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering_pure_ static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering format = job_get_status_message_format(u, t, result);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering /* Return generic strings */
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Started %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Failed to start %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Dependency failed for %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Timed out starting %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (t == JOB_STOP || t == JOB_RESTART) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Stopped %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Stopped (with error) %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Timed out stoppping %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (t == JOB_RELOAD) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Reloaded %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Reload failed for %s.";
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering return "Timed out reloading %s.";
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek#pragma GCC diagnostic ignored "-Wformat-nonliteral"
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekstatic void job_print_status_message(Unit *u, JobType t, JobResult result) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek format = job_get_status_message_format(u, t, result);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering manager_flip_auto_status(u->manager, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek manager_status_printf(u->manager, false, NULL, "See 'systemctl status %s' for details.", u->id);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering manager_flip_auto_status(u->manager, true);
83f6936a018b08880670838756e0f4e9ea98b4a7Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering manager_flip_auto_status(u->manager, true);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering } else if (t == JOB_STOP || t == JOB_RESTART) {
d4205751d4643c272059a3728045929dd0e5e800Lennart Poettering format = job_get_status_message_format(u, t, result);
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek manager_flip_auto_status(u->manager, true);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format);
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek } else if (t == JOB_VERIFY_ACTIVE) {
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek /* When verify-active detects the unit is inactive, report it.
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek * Most likely a DEPEND warning from a requisiting unit will
844ec79b3c2f246114ea316ebe1f36044bdb688eZbigniew Jędrzejewski-Szmek * occur next and it's nice to see what was requisited. */
e53fc357a9bb9d0a5362ccc4246d598cb0febd5eLennart Poettering unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active.");
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmek#pragma GCC diagnostic ignored "-Wformat-nonliteral"
54b7254c1fa629937f92fd6fa34bdf127b696a00Zbigniew Jędrzejewski-Szmekstatic void job_log_status_message(Unit *u, JobType t, JobResult result) {
assert(t >= 0);
if (log_on_console())
if (!format)
if (t == JOB_START) {
u->id,
NULL);
} else if (t == JOB_STOP)
u->id,
NULL);
else if (t == JOB_RELOAD)
u->id,
NULL);
Unit *u;
JobType t;
Iterator i;
assert(j);
u = j->unit;
t = j->type;
goto finish;
job_uninstall(j);
job_free(j);
if (t == JOB_START ||
t == JOB_VERIFY_ACTIVE) {
} else if (t == JOB_STOP) {
u->id,
u->id,
NULL);
assert(j);
if (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);
assert(j);
if (j->in_run_queue)
j->in_run_queue = true;
assert(j);
if (j->in_dbus_queue)
* connection/client. */
j->in_dbus_queue = true;
assert(j);
return NULL;
if (j->begin_usec > 0)
assert(j);
size_t k;
if (feof(f))
return -errno;
JobType t;
t = job_type_from_string(v);
else if (t >= _JOB_TYPE_MAX_IN_TRANSACTION)
j->type = t;
JobState s;
s = job_state_from_string(v);
j->state = s;
b = parse_boolean(v);
b = parse_boolean(v);
b = parse_boolean(v);
b = parse_boolean(v);
unsigned long long ull;
assert(j);
if (j->begin_usec <= 0)
if (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);
assert(j);
assert(u);
if (j->timer_event_source) {