X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Ftransaction.c;h=a2efcbcff4a03ea939fa8487f2c3e957ff93dda8;hb=33e48d472e4e8e123be7bce5a0962cab7eaaa508;hp=cac58e6834769c99df03e09a7d7ca09bfcbeffb2;hpb=0d9989aa68963037a18fb7ed4f309f6155927d70;p=elogind.git diff --git a/src/core/transaction.c b/src/core/transaction.c index cac58e683..a2efcbcff 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -11,8 +11,7 @@ static void transaction_delete_job(Transaction *tr, Job *j, bool delete_dependen transaction_unlink_job(tr, j, delete_dependencies); - if (!j->installed) - job_free(j); + job_free(j); } static void transaction_delete_unit(Transaction *tr, Unit *u) { @@ -34,8 +33,6 @@ void transaction_abort(Transaction *tr) { transaction_delete_job(tr, j, true); assert(hashmap_isempty(tr->jobs)); - - assert(!tr->anchor); } static void transaction_find_jobs_that_matter_to_anchor(Job *j, unsigned generation) { @@ -245,21 +242,14 @@ static int transaction_merge_jobs(Transaction *tr, DBusError *e) { LIST_FOREACH(transaction, k, j->transaction_next) assert_se(job_type_merge(&t, k->type) == 0); - /* If an active job is mergeable, merge it too */ - if (j->unit->job) - job_type_merge(&t, j->unit->job->type); /* Might fail. Which is OK */ - while ((k = j->transaction_next)) { - if (j->installed) { + if (tr->anchor_job == k) { transaction_merge_and_delete_job(tr, k, j, t); j = k; } else transaction_merge_and_delete_job(tr, j, k, t); } - if (j->unit->job && !j->installed) - transaction_merge_and_delete_job(tr, j, j->unit->job, t); - assert(!j->transaction_next); assert(!j->transaction_prev); } @@ -287,8 +277,8 @@ static void transaction_drop_redundant(Transaction *tr) { LIST_FOREACH(transaction, k, j) { - if (!job_is_anchor(k) && - (k->installed || job_type_is_redundant(k->type, unit_active_state(k->unit))) && + if (tr->anchor_job != k && + job_type_is_redundant(k->type, unit_active_state(k->unit)) && (!k->unit->job || !job_type_is_conflicting(k->type, k->unit->job->type))) continue; @@ -358,7 +348,6 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi log_info("Walked on cycle path to %s/%s", k->unit->id, job_type_to_string(k->type)); if (!delete && - !k->installed && !unit_matters_to_anchor(k->unit, k)) { /* Ok, we can drop this one, so let's * do so. */ @@ -454,7 +443,7 @@ static void transaction_collect_garbage(Transaction *tr) { again = false; HASHMAP_FOREACH(j, tr->jobs, i) { - if (j->object_list) { + if (tr->anchor_job == j || j->object_list) { /* log_debug("Keeping job %s/%s because of %s/%s", */ /* j->unit->id, job_type_to_string(j->type), */ /* j->object_list->subject ? j->object_list->subject->unit->id : "root", */ @@ -487,7 +476,6 @@ static int transaction_is_destructive(Transaction *tr, DBusError *e) { assert(!j->transaction_next); if (j->unit->job && - j->unit->job != j && !job_type_is_superset(j->type, j->unit->job->type)) { dbus_set_error(e, BUS_ERROR_TRANSACTION_IS_DESTRUCTIVE, "Transaction is destructive."); @@ -585,59 +573,38 @@ static int transaction_apply(Transaction *tr, Manager *m, JobMode mode) { assert(!j->transaction_prev); assert(!j->transaction_next); - if (j->installed) - continue; - r = hashmap_put(m->jobs, UINT32_TO_PTR(j->id), j); if (r < 0) goto rollback; } while ((j = hashmap_steal_first(tr->jobs))) { - Job *uj; - if (j->installed) { - /* log_debug("Skipping already installed job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id); */ - continue; - } - - uj = j->unit->job; - if (uj) { - job_uninstall(uj); - job_free(uj); - } - - j->unit->job = j; - j->installed = true; - m->n_installed_jobs ++; - - /* We're fully installed. Now let's free data we don't - * need anymore. */ - - assert(!j->transaction_next); - assert(!j->transaction_prev); + Job *installed_job; /* Clean the job dependencies */ transaction_unlink_job(tr, j, false); + installed_job = job_install(j); + if (installed_job != j) { + /* j has been merged into a previously installed job */ + if (tr->anchor_job == j) + tr->anchor_job = installed_job; + hashmap_remove(m->jobs, UINT32_TO_PTR(j->id)); + job_free(j); + j = installed_job; + } + job_add_to_run_queue(j); job_add_to_dbus_queue(j); job_start_timer(j); - - log_debug("Installed new job %s/%s as %u", j->unit->id, job_type_to_string(j->type), (unsigned) j->id); } - assert(!tr->anchor); - return 0; rollback: - HASHMAP_FOREACH(j, tr->jobs, i) { - if (j->installed) - continue; - + HASHMAP_FOREACH(j, tr->jobs, i) hashmap_remove(m->jobs, UINT32_TO_PTR(j->id)); - } return r; } @@ -726,7 +693,6 @@ int transaction_activate(Transaction *tr, Manager *m, JobMode mode, DBusError *e } assert(hashmap_isempty(tr->jobs)); - assert(!tr->anchor); return 0; } @@ -778,12 +744,6 @@ static Job* transaction_add_one_job(Transaction *tr, JobType type, Unit *unit, b return j; } -static void transaction_job_dependency_free(Transaction *tr, JobDependency *l) { - if (!l->subject) - LIST_REMOVE(JobDependency, subject, tr->anchor, l); - job_dependency_free(l); -} - static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependencies) { assert(tr); assert(j); @@ -801,12 +761,12 @@ static void transaction_unlink_job(Transaction *tr, Job *j, bool delete_dependen j->transaction_prev = j->transaction_next = NULL; while (j->subject_list) - transaction_job_dependency_free(tr, j->subject_list); + job_dependency_free(j->subject_list); while (j->object_list) { Job *other = j->object_list->matters ? j->object_list->subject : NULL; - transaction_job_dependency_free(tr, j->object_list); + job_dependency_free(j->object_list); if (other && delete_dependencies) { log_debug("Deleting job %s/%s as dependency of job %s/%s", @@ -829,7 +789,6 @@ int transaction_add_job_and_dependencies( bool ignore_order, DBusError *e) { Job *ret; - JobDependency *l; Iterator i; Unit *dep; int r; @@ -879,17 +838,14 @@ int transaction_add_job_and_dependencies( ret->ignore_order = ret->ignore_order || ignore_order; /* Then, add a link to the job. */ - l = job_dependency_new(by, ret, matters, conflicts); - if (!l) - return -ENOMEM; - - /* If the link has no subject job, it's the anchor link. */ - if (!by) { - LIST_PREPEND(JobDependency, subject, tr->anchor, l); + if (by) { + if (!job_dependency_new(by, ret, matters, conflicts)) + return -ENOMEM; + } else { + /* If the job has no parent job, it is the anchor job. */ assert(!tr->anchor_job); tr->anchor_job = ret; } - if (is_new && !ignore_requirements) { Set *following; @@ -910,7 +866,7 @@ int transaction_add_job_and_dependencies( } /* Finally, recursively add in all dependencies. */ - if (type == JOB_START || type == JOB_RELOAD_OR_START) { + if (type == JOB_START || type == JOB_RELOAD_OR_START || type == JOB_RESTART) { SET_FOREACH(dep, ret->unit->dependencies[UNIT_REQUIRES], i) { r = transaction_add_job_and_dependencies(tr, JOB_START, dep, ret, true, override, false, false, ignore_order, e); if (r < 0) {