core: add internal API to remove dependencies again, based on dependency mask

let's make use of the dependency mask, and add internal API to remove
dependencies ago, based on bits in the dependency mask.
This commit is contained in:
Lennart Poettering 2017-10-26 16:39:35 +02:00
parent 2651d03751
commit c999cf385a
3 changed files with 98 additions and 0 deletions

View File

@ -4831,3 +4831,72 @@ int unit_fork_helper_process(Unit *u, pid_t *ret) {
*ret = pid;
return 1;
}
static void unit_update_dependency_mask(Unit *u, UnitDependency d, Unit *other, UnitDependencyInfo di) {
assert(u);
assert(d >= 0);
assert(d < _UNIT_DEPENDENCY_MAX);
assert(other);
if (di.origin_mask == 0 && di.destination_mask == 0) {
/* No bit set anymore, let's drop the whole entry */
assert_se(hashmap_remove(u->dependencies[d], other));
log_unit_debug(u, "%s lost dependency %s=%s", u->id, unit_dependency_to_string(d), other->id);
} else
/* Mask was reduced, let's update the entry */
assert_se(hashmap_update(u->dependencies[d], other, di.data) == 0);
}
void unit_remove_dependencies(Unit *u, UnitDependencyMask mask) {
UnitDependency d;
assert(u);
/* Removes all dependencies u has on other units marked for ownership by 'mask'. */
if (mask == 0)
return;
for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) {
bool done;
do {
UnitDependencyInfo di;
Unit *other;
Iterator i;
done = true;
HASHMAP_FOREACH_KEY(di.data, other, u->dependencies[d], i) {
UnitDependency q;
if ((di.origin_mask & ~mask) == di.origin_mask)
continue;
di.origin_mask &= ~mask;
unit_update_dependency_mask(u, d, other, di);
/* We updated the dependency from our unit to the other unit now. But most dependencies
* imply a reverse dependency. Hence, let's delete that one too. For that we go through
* all dependency types on the other unit and delete all those which point to us and
* have the right mask set. */
for (q = 0; q < _UNIT_DEPENDENCY_MAX; q++) {
UnitDependencyInfo dj;
dj.data = hashmap_get(other->dependencies[q], u);
if ((dj.destination_mask & ~mask) == dj.destination_mask)
continue;
dj.destination_mask &= ~mask;
unit_update_dependency_mask(other, q, u, dj);
}
unit_add_to_gc_queue(other);
done = false;
break;
}
} while (!done);
}
}

View File

@ -740,6 +740,8 @@ void unit_set_exec_params(Unit *s, ExecParameters *p);
int unit_fork_helper_process(Unit *u, pid_t *ret);
void unit_remove_dependencies(Unit *u, UnitDependencyMask mask);
/* Macros which append UNIT= or USER_UNIT= to the message */
#define log_unit_full(unit, level, error, ...) \

View File

@ -115,6 +115,33 @@ int main(int argc, char *argv[]) {
assert_se(manager_add_job(m, JOB_START, h, JOB_FAIL, NULL, &j) == 0);
manager_dump_jobs(m, stdout, "\t");
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b));
assert_se(!hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c));
assert_se(!hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
assert_se(unit_add_dependency(a, UNIT_PROPAGATES_RELOAD_TO, b, true, UNIT_DEPENDENCY_UDEV) == 0);
assert_se(unit_add_dependency(a, UNIT_PROPAGATES_RELOAD_TO, c, true, UNIT_DEPENDENCY_PROC_SWAP) == 0);
assert_se(hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b));
assert_se(hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
assert_se(hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c));
assert_se(hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
unit_remove_dependencies(a, UNIT_DEPENDENCY_UDEV);
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b));
assert_se(!hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
assert_se(hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c));
assert_se(hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
unit_remove_dependencies(a, UNIT_DEPENDENCY_PROC_SWAP);
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], b));
assert_se(!hashmap_get(b->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
assert_se(!hashmap_get(a->dependencies[UNIT_PROPAGATES_RELOAD_TO], c));
assert_se(!hashmap_get(c->dependencies[UNIT_RELOAD_PROPAGATED_FROM], a));
manager_free(m);
return 0;