job.c revision ead8e4788ee31bbdc38b4cd3c6e71c8a95bbc95a
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering This file is part of systemd.
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering Copyright 2010 Lennart Poettering
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering systemd is free software; you can redistribute it and/or modify it
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering under the terms of the GNU General Public License as published by
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering the Free Software Foundation; either version 2 of the License, or
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering (at your option) any later version.
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering systemd is distributed in the hope that it will be useful, but
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering General Public License for more details.
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU General Public License
0b3b020a178cf3b957fed627de13c895773995ecLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-SzmekJob* job_new(Manager *m, JobType type, Unit *unit) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek j->timer_watch.type = WATCH_INVALID;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* We don't link it here, that's what job_dependency() is for */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Detach from next 'bigger' objects */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek bus_job_send_removed_signal(j, !j->failed);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering /* Detach from next 'smaller' objects */
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering manager_transaction_unlink_job(j->manager, j, true);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek LIST_REMOVE(Job, run_queue, j->manager->run_queue, j);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek LIST_REMOVE(Job, dbus_queue, j->manager->dbus_job_queue, j);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (j->timer_watch.type != WATCH_INVALID) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(j->timer_watch.type == WATCH_JOB_TIMER);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert(j->timer_watch.data.job == j);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek assert_se(epoll_ctl(j->manager->epoll_fd, EPOLL_CTL_DEL, j->timer_watch.fd, NULL) >= 0);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek close_nointr_nofail(j->timer_watch.fd);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-SzmekJobDependency* job_dependency_new(Job *subject, Job *object, bool matters, bool conflicts) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Adds a new job link, which encodes that the 'subject' job
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * needs the 'object' job in some way. If 'subject' is NULL
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * this means the 'anchor' job (i.e. the one the user
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * explcitily asked for) is the requester. */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (!(l = new0(JobDependency, 1)))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek LIST_PREPEND(JobDependency, subject, subject->subject_list, l);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek LIST_PREPEND(JobDependency, subject, object->manager->transaction_anchor, l);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek LIST_PREPEND(JobDependency, object, object->object_list, l);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekvoid job_dependency_free(JobDependency *l) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek LIST_REMOVE(JobDependency, subject, l->subject->subject_list, l);
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering LIST_REMOVE(JobDependency, subject, l->object->manager->transaction_anchor, l);
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering LIST_REMOVE(JobDependency, object, l->object->object_list, l);
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poetteringvoid job_dump(Job *j, FILE*f, const char *prefix) {
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering "%s-> Job %u:\n"
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering "%s\tAction: %s -> %s\n"
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering "%s\tState: %s\n"
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering "%s\tForced: %s\n",
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek prefix, j->unit->meta.id, job_type_to_string(j->type),
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek prefix, job_state_to_string(j->state),
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekstatic bool types_match(JobType a, JobType b, JobType c, JobType d) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek (a == c && b == d) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek (a == d && b == c);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekint job_type_merge(JobType *a, JobType b) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Merging is associative! a merged with b merged with c is
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * the same as a merged with c merged with b. */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Mergeability is transitive! if a can be merged with b and b
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * with c then a also with c */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Also, if a merged with b cannot be merged with c, then
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek * either a or b cannot be merged with c either */
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek if (types_match(*a, b, JOB_START, JOB_VERIFY_ACTIVE))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek else if (types_match(*a, b, JOB_START, JOB_RELOAD) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek types_match(*a, b, JOB_START, JOB_RELOAD_OR_START) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_RELOAD_OR_START) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek types_match(*a, b, JOB_RELOAD, JOB_RELOAD_OR_START))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek else if (types_match(*a, b, JOB_START, JOB_RESTART) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek types_match(*a, b, JOB_START, JOB_TRY_RESTART) ||
707b66c66381c899d7ef640e158ffdd5bcff4debLennart Poettering types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_RESTART) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek types_match(*a, b, JOB_RELOAD, JOB_RESTART) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek types_match(*a, b, JOB_RELOAD_OR_START, JOB_RESTART) ||
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek types_match(*a, b, JOB_RELOAD_OR_START, JOB_TRY_RESTART) ||
667c24a6a86a5a26a906b7477ae81dcf4c73e64eLennart Poettering types_match(*a, b, JOB_RESTART, JOB_TRY_RESTART))
667c24a6a86a5a26a906b7477ae81dcf4c73e64eLennart Poettering else if (types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_RELOAD))
667c24a6a86a5a26a906b7477ae81dcf4c73e64eLennart Poettering else if (types_match(*a, b, JOB_VERIFY_ACTIVE, JOB_TRY_RESTART) ||
707b66c66381c899d7ef640e158ffdd5bcff4debLennart Poettering types_match(*a, b, JOB_RELOAD, JOB_TRY_RESTART))
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekbool job_type_is_mergeable(JobType a, JobType b) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return job_type_merge(&a, b) >= 0;
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekbool job_type_is_superset(JobType a, JobType b) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek /* Checks whether operation a is a "superset" of b in its
707b66c66381c899d7ef640e158ffdd5bcff4debLennart Poetteringbool job_type_is_conflicting(JobType a, JobType b) {
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmek return (a == JOB_STOP) != (b == JOB_STOP);
798d3a524ea57aaf40cb53858aaa45ec702f012dZbigniew Jędrzejewski-Szmekbool job_type_is_redundant(JobType a, UnitActiveState b) {
b == UNIT_RELOADING;
case JOB_RESTART:
b == UNIT_ACTIVATING;
case JOB_TRY_RESTART:
b == UNIT_ACTIVATING;
Iterator i;
assert(j);
Manager *m;
assert(j);
if (j->in_run_queue) {
j->in_run_queue = false;
if (!job_is_runnable(j))
return -EAGAIN;
m = j->manager;
switch (j->type) {
case JOB_START:
if (r == -EBADR)
case JOB_VERIFY_ACTIVE: {
if (UNIT_IS_ACTIVE_OR_RELOADING(t))
r = -EALREADY;
else if (t == UNIT_ACTIVATING)
r = -EAGAIN;
r = -ENOEXEC;
case JOB_STOP:
case JOB_RELOAD:
case JOB_RELOAD_OR_START:
case JOB_RESTART: {
case JOB_TRY_RESTART: {
r = -ENOEXEC;
else if (t == UNIT_ACTIVATING) {
if (r == -EALREADY)
r = job_finish_and_invalidate(j, true);
else if (r == -EAGAIN)
r = job_finish_and_invalidate(j, false);
Unit *u;
JobType t;
Iterator i;
assert(j);
log_debug("Job %s/%s finished, success=%s", j->unit->meta.id, job_type_to_string(j->type), yes_no(success));
if (j->failed)
u = j->unit;
t = j->type;
job_free(j);
unit_status_printf(u, "Starting %s " ANSI_HIGHLIGHT_ON "failed" ANSI_HIGHLIGHT_OFF ".\n", unit_description(u));
if (!success) {
if (t == JOB_START ||
t == JOB_VERIFY_ACTIVE ||
t == JOB_RELOAD_OR_START) {
} else if (t == JOB_STOP) {
int fd, r;
assert(j);
r = -errno;
goto fail;
r = -errno;
goto fail;
r = -errno;
goto fail;
fail:
if (fd >= 0)
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;
assert(j);
job_finish_and_invalidate(j, false);