X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=manager.c;h=d2708aacf3d788e7e8ff660ae8e67c8617916666;hp=86ed086eb31c3f48f586a9b38831f2dbcc7d5d2d;hb=11dd41ce4b465f6260ce68aa050a488f88f694eb;hpb=42f4e3c4413ad35e3815f25211fee95d775488a7 diff --git a/manager.c b/manager.c index 86ed086eb..d2708aacf 100644 --- a/manager.c +++ b/manager.c @@ -54,6 +54,58 @@ void manager_free(Manager *m) { free(m); } +static void transaction_abort(Manager *m) { + Job *j; + + assert(m); + assert(m->n_dependency_depth == 0); + + while ((j = hashmap_steal_first(m->jobs_to_add))) + job_free(j); + + set_clear(m->jobs_to_remove); +} + +static int transaction_activate(Manager *m) { + Job *j; + int r; + void *state; + + assert(m); + assert(m->n_dependency_depth == 0); + + /* This applies the changes recorded in jobs_to_add and + * jobs_to_remove to the actual list of jobs */ + + HASHMAP_FOREACH(j, m->jobs_to_add, state) { + assert(!j->linked); + + if ((r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j)) < 0) + goto rollback; + } + + /* all entries are now registered, now make sure the names + * know about that. */ + + while ((j = hashmap_steal_first(m->jobs_to_add))) { + j->name->meta.job = j; + j->linked = true; + } + + while ((j = set_steal_first(m->jobs_to_remove))) + job_free(j); + + return 0; + +rollback: + + HASHMAP_FOREACH(j, m->jobs_to_add, state) + hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id)); + + transaction_abort(m); + return r; +} + int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_ret) { Job *ret, *other; void *state; @@ -64,7 +116,6 @@ int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_r assert(type < _JOB_TYPE_MAX); assert(name); assert(mode < _JOB_MODE_MAX); - assert(_ret); /* Check for conflicts, first against the jobs we shall * create */ @@ -88,6 +139,8 @@ int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_r if (!(ret = job_new(m, type, name))) return -ENOMEM; + m->n_dependency_depth ++; + if ((r = hashmap_put(m->jobs_to_add, name, ret)) < 0) goto fail; @@ -118,6 +171,13 @@ int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_r goto fail; } + if (--m->n_dependency_depth <= 0) + if ((r = transaction_activate(m)) < 0) { + transaction_abort(m); + return r; + } + + if (_ret) *_ret = ret; @@ -126,6 +186,9 @@ int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_r fail: job_free(ret); + if (--m->n_dependency_depth <= 0) + transaction_abort(m); + return r; } @@ -251,6 +314,9 @@ finish: if ((r = name_load_dropin(name)) < 0) return r; + if ((r = name_link_names(name)) < 0) + return r; + name->meta.state = NAME_LOADED; return 0; } @@ -348,10 +414,12 @@ void manager_dump_jobs(Manager *s, FILE *f) { void manager_dump_names(Manager *s, FILE *f) { void *state; Name *n; + const char *t; assert(s); assert(f); - HASHMAP_FOREACH(n, s->names, state) - name_dump(n, f); + HASHMAP_FOREACH_KEY(n, t, s->names, state) + if (name_id(n) == t) + name_dump(n, f); }