X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=manager.c;h=da2d4334746881728ebebdb3d77c1fb5efd510d7;hp=170ea84344f82bd6363ca8f62983f67707fe1fa7;hb=9ea024f6b5a9626ddabeb4c4d4385481b52d211e;hpb=cea8e32e3fc57569094e2ddf4167f2a9864fc3a4 diff --git a/manager.c b/manager.c index 170ea8434..da2d43347 100644 --- a/manager.c +++ b/manager.c @@ -8,7 +8,7 @@ #include "hashmap.h" #include "macro.h" #include "strv.h" -#include "load-fragment.h" +#include "log.h" Manager* manager_new(void) { Manager *m; @@ -51,6 +51,16 @@ void manager_free(Manager *m) { free(m); } +static void transaction_delete_job(Manager *m, Job *j) { + assert(m); + assert(j); + + manager_transaction_unlink_job(m, j); + + if (!j->linked) + job_free(j); +} + static void transaction_abort(Manager *m) { Job *j; @@ -58,7 +68,7 @@ static void transaction_abort(Manager *m) { while ((j = hashmap_first(m->transaction_jobs))) if (j->linked) - manager_transaction_delete_job(m, j); + transaction_delete_job(m, j); else job_free(j); @@ -122,7 +132,7 @@ static int types_merge(JobType *a, JobType b) { return -EEXIST; } -static void manager_merge_and_delete_prospective_job(Manager *m, Job *j, Job *other, JobType t) { +static void transaction_merge_and_delete_job(Manager *m, Job *j, Job *other, JobType t) { JobDependency *l, *last; assert(j); @@ -167,11 +177,10 @@ static void manager_merge_and_delete_prospective_job(Manager *m, Job *j, Job *ot j->object_list = other->object_list; } - /* Kill the other job */ other->subject_list = NULL; other->object_list = NULL; - manager_transaction_delete_job(m, other); + transaction_delete_job(m, other); } static int transaction_merge_jobs(Manager *m) { @@ -191,17 +200,17 @@ static int transaction_merge_jobs(Manager *m) { while ((k = j->transaction_next)) { if (j->linked) { - manager_merge_and_delete_prospective_job(m, k, j, t); + transaction_merge_and_delete_job(m, k, j, t); j = k; } else - manager_merge_and_delete_prospective_job(m, j, k, t); + transaction_merge_and_delete_job(m, j, k, t); } assert(!j->transaction_next); assert(!j->transaction_prev); } - return r; + return 0; } static int transaction_verify_order_one(Manager *m, Job *j, Job *from, unsigned generation) { @@ -212,22 +221,23 @@ static int transaction_verify_order_one(Manager *m, Job *j, Job *from, unsigned assert(m); assert(j); - /* Did we find a loop? */ + /* Did we find a cycle? */ if (j->marker && j->generation == generation) { Job *k; /* So, we already have been here. We have a - * loop. Let's try to break it. We go backwards in our + * cycle. Let's try to break it. We go backwards in our * path and try to find a suitable job to remove. */ for (k = from; k; k = (k->generation == generation ? k->marker : NULL)) { if (!k->matters_to_anchor) { - manager_transaction_delete_job(m, k); + log_debug("Breaking order cycle by deleting job %s", name_id(k->name)); + transaction_delete_job(m, k); return -EAGAIN; } /* Check if this in fact was the beginning of - * the loop */ + * the cycle */ if (k == j) break; } @@ -275,7 +285,7 @@ static int transaction_verify_order(Manager *m, unsigned *generation) { if ((r = transaction_verify_order_one(m, j, NULL, (*generation)++)) < 0) { - /* There was a loop, but it was fixed, + /* There was a cycleq, but it was fixed, * we need to restart our algorithm */ if (r == -EAGAIN) { again = true; @@ -305,7 +315,9 @@ static void transaction_collect_garbage(Manager *m) { if (j->object_list) continue; - manager_transaction_delete_job(m, j); + log_debug("Garbage collecting job %s", name_id(j->name)); + + transaction_delete_job(m, j); again = true; break; } @@ -469,7 +481,7 @@ static Job* transaction_add_one_job(Manager *m, JobType type, Name *name, bool * return j; } -void manager_transaction_delete_job(Manager *m, Job *j) { +void manager_transaction_unlink_job(Manager *m, Job *j) { assert(m); assert(j); @@ -487,8 +499,17 @@ void manager_transaction_delete_job(Manager *m, Job *j) { while (j->subject_list) job_dependency_free(j->subject_list); - while (j->object_list) + + while (j->object_list) { + Job *other = j->object_list->matters ? j->object_list->subject : NULL; + job_dependency_free(j->object_list); + + if (other) { + log_debug("Deleting job %s as dependency of job %s", name_id(other->name), name_id(j->name)); + transaction_delete_job(m, other); + } + } } static int transaction_add_job_and_dependencies(Manager *m, JobType type, Name *name, Job *by, bool matters, bool force, Job **_ret) { @@ -502,6 +523,9 @@ static int transaction_add_job_and_dependencies(Manager *m, JobType type, Name * assert(type < _JOB_TYPE_MAX); assert(name); + if (name->meta.state != NAME_LOADED) + return -EINVAL; + /* First add the job. */ if (!(ret = transaction_add_one_job(m, type, name, &is_new))) return -ENOMEM; @@ -584,121 +608,6 @@ Name *manager_get_name(Manager *m, const char *name) { return hashmap_get(m->names, name); } -static int verify_type(Name *name) { - char *n; - void *state; - - assert(name); - - /* Checks that all aliases of this name have the same and valid type */ - - SET_FOREACH(n, name->meta.names, state) { - NameType t; - - if ((t = name_type_from_string(n)) == _NAME_TYPE_INVALID) - return -EINVAL; - - if (name->meta.type == _NAME_TYPE_INVALID) { - name->meta.type = t; - continue; - } - - if (name->meta.type != t) - return -EINVAL; - } - - if (name->meta.type == _NAME_TYPE_INVALID) - return -EINVAL; - - return 0; -} - -static int service_load_sysv(Service *s) { - assert(s); - - /* Load service data from SysV init scripts, preferably with - * LSB headers ... */ - - return 0; -} - -static int name_load_fstab(Name *n) { - assert(n); - assert(n->meta.type == NAME_MOUNT || n->meta.type == NAME_AUTOMOUNT); - - /* Load mount data from /etc/fstab */ - - return 0; -} - -static int snapshot_load(Snapshot *s) { - assert(s); - - /* Load snapshots from disk */ - - return 0; -} - -static int name_load_dropin(Name *n) { - assert(n); - - /* Load dependencies from drop-in directories */ - - return 0; -} - -static int load(Name *name) { - int r; - - assert(name); - - if (name->meta.state != NAME_STUB) - return 0; - - if ((r = verify_type(name)) < 0) - return r; - - if (name->meta.type == NAME_SERVICE) { - - /* Load a .service file */ - if ((r = name_load_fragment(name)) == 0) - goto finish; - - /* Load a classic init script */ - if (r == -ENOENT) - if ((r = service_load_sysv(SERVICE(name))) == 0) - goto finish; - - } else if (name->meta.type == NAME_MOUNT || - name->meta.type == NAME_AUTOMOUNT) { - - if ((r = name_load_fstab(name)) == 0) - goto finish; - - } else if (name->meta.type == NAME_SNAPSHOT) { - - if ((r = snapshot_load(SNAPSHOT(name))) == 0) - goto finish; - - } else { - if ((r = name_load_fragment(name)) == 0) - goto finish; - } - - name->meta.state = NAME_FAILED; - return r; - -finish: - if ((r = name_load_dropin(name)) < 0) - return r; - - if ((r = name_link_names(name, true)) < 0) - return r; - - name->meta.state = NAME_LOADED; - return 0; -} - static int dispatch_load_queue(Manager *m) { Meta *meta; @@ -714,7 +623,7 @@ static int dispatch_load_queue(Manager *m) { * tries to load its data until the queue is empty */ while ((meta = m->load_queue)) { - load(NAME(meta)); + name_load(NAME(meta)); LIST_REMOVE(Meta, m->load_queue, meta); } @@ -801,3 +710,14 @@ void manager_dump_names(Manager *s, FILE *f, const char *prefix) { if (name_id(n) == t) name_dump(n, f, prefix); } + +void manager_clear_jobs(Manager *m) { + Job *j; + + assert(m); + + transaction_abort(m); + + while ((j = hashmap_first(m->jobs))) + job_free(j); +}