#include "strv.h"
#include "load-fragment.h"
#include "load-dropin.h"
+#include "log.h"
const NameVTable * const name_vtable[_NAME_TYPE_MAX] = {
[NAME_SERVICE] = &service_vtable,
[NAME_TIMER] = &timer_vtable,
[NAME_SOCKET] = &socket_vtable,
- [NAME_MILESTONE] = &milestone_vtable,
+ [NAME_TARGET] = &target_vtable,
[NAME_DEVICE] = &device_vtable,
[NAME_MOUNT] = &mount_vtable,
[NAME_AUTOMOUNT] = &automount_vtable,
n->meta.manager = m;
n->meta.type = _NAME_TYPE_INVALID;
- /* We don't link the name here, that is left for name_link() */
-
return n;
}
return r;
}
+ if ((r = hashmap_put(n->meta.manager->names, s, n)) < 0) {
+ set_remove(n->meta.names, s);
+ free(s);
+ return r;
+ }
+
n->meta.type = t;
if (!n->meta.id)
return 0;
}
-/* FIXME: Does not rollback on failure! */
-int name_link_names(Name *n, bool replace) {
- char *t;
- Iterator i;
- int r;
-
- assert(n);
-
- if (!n->meta.linked)
- return 0;
-
- /* Link all names that aren't linked yet. */
-
- SET_FOREACH(t, n->meta.names, i)
- if (replace) {
- if ((r = hashmap_replace(n->meta.manager->names, t, n)) < 0)
- return r;
- } else {
- if ((r = hashmap_put(n->meta.manager->names, t, n)) < 0)
- return r;
- }
-
- return 0;
-}
-
-int name_link(Name *n) {
- int r;
-
+void name_add_to_load_queue(Name *n) {
assert(n);
- assert(!set_isempty(n->meta.names));
- assert(!n->meta.linked);
- if ((r = name_sanitize(n)) < 0)
- return r;
-
- n->meta.linked = true;
-
- if ((r = name_link_names(n, false)) < 0) {
- char *t;
- Iterator i;
-
- /* Rollback the registered names */
- SET_FOREACH(t, n->meta.names, i)
- hashmap_remove_value(n->meta.manager->names, t, n);
-
- n->meta.linked = false;
- return r;
- }
-
- if (n->meta.load_state == NAME_STUB) {
- LIST_PREPEND(Meta, load_queue, n->meta.manager->load_queue, &n->meta);
- n->meta.in_load_queue = true;
- }
+ if (n->meta.load_state != NAME_STUB || n->meta.in_load_queue)
+ return;
- return 0;
+ LIST_PREPEND(Meta, load_queue, n->meta.manager->load_queue, &n->meta);
+ n->meta.in_load_queue = true;
}
static void bidi_set_free(Name *name, Set *s) {
void name_free(Name *name) {
NameDependency d;
+ Iterator i;
char *t;
assert(name);
/* Detach from next 'bigger' objects */
- if (name->meta.linked) {
- char *t;
- Iterator i;
- SET_FOREACH(t, name->meta.names, i)
- hashmap_remove_value(name->meta.manager->names, t, name);
+ SET_FOREACH(t, name->meta.names, i)
+ hashmap_remove_value(name->meta.manager->names, t, name);
- if (name->meta.in_load_queue)
- LIST_REMOVE(Meta, load_queue, name->meta.manager->load_queue, &name->meta);
- }
+ if (name->meta.in_load_queue)
+ LIST_REMOVE(Meta, load_queue, name->meta.manager->load_queue, &name->meta);
+
+ if (name->meta.load_state == NAME_LOADED)
+ if (NAME_VTABLE(name)->done)
+ NAME_VTABLE(name)->done(name);
/* Free data and next 'smaller' objects */
if (name->meta.job)
for (d = 0; d < _NAME_DEPENDENCY_MAX; d++)
bidi_set_free(name, name->meta.dependencies[d]);
- if (NAME_VTABLE(name)->done)
- NAME_VTABLE(name)->done(name);
-
free(name->meta.description);
while ((t = set_steal_first(name->meta.names)))
return NAME_VTABLE(name)->active_state(name);
}
-static int ensure_in_set(Set **s, void *data) {
- int r;
-
- assert(s);
- assert(data);
-
- if ((r = set_ensure_allocated(s, trivial_hash_func, trivial_compare_func)) < 0)
- return r;
-
- if ((r = set_put(*s, data)) < 0)
- return r;
-
- return 0;
-}
-
static int ensure_merge(Set **s, Set *other) {
if (!other)
/* Merge dependencies */
for (d = 0; d < _NAME_DEPENDENCY_MAX; d++)
+ /* fixme, the inverse mapping is missing */
if ((r = ensure_merge(&name->meta.dependencies[d], other->meta.dependencies[d])) < 0)
return r;
- /* Hookup new deps and names */
- if (name->meta.linked) {
- if ((r = name_sanitize(name)) < 0)
- return r;
-
- if ((r = name_link_names(name, true)) < 0)
- return r;
- }
-
return 0;
}
-/* FIXME: Does not rollback on failure! */
-static int augment(Name *n) {
- int r;
- Iterator i;
- Name *other;
-
- assert(n);
-
- /* Adds in the missing links to make all dependencies
- * bidirectional. */
-
- SET_FOREACH(other, n->meta.dependencies[NAME_BEFORE], i)
- if ((r = ensure_in_set(&other->meta.dependencies[NAME_AFTER], n)) < 0)
- return r;
- SET_FOREACH(other, n->meta.dependencies[NAME_AFTER], i)
- if ((r = ensure_in_set(&other->meta.dependencies[NAME_BEFORE], n)) < 0)
- return r;
-
- SET_FOREACH(other, n->meta.dependencies[NAME_CONFLICTS], i)
- if ((r = ensure_in_set(&other->meta.dependencies[NAME_CONFLICTS], n)) < 0)
- return r;
-
- SET_FOREACH(other, n->meta.dependencies[NAME_REQUIRES], i)
- if ((r = ensure_in_set(&other->meta.dependencies[NAME_REQUIRED_BY], n)) < 0)
- return r;
- SET_FOREACH(other, n->meta.dependencies[NAME_REQUISITE], i)
- if ((r = ensure_in_set(&other->meta.dependencies[NAME_REQUIRED_BY], n)) < 0)
- return r;
-
- SET_FOREACH(other, n->meta.dependencies[NAME_SOFT_REQUIRES], i)
- if ((r = ensure_in_set(&other->meta.dependencies[NAME_SOFT_REQUIRED_BY], n)) < 0)
- return r;
-
- SET_FOREACH(other, n->meta.dependencies[NAME_WANTS], i)
- if ((r = ensure_in_set(&other->meta.dependencies[NAME_WANTED_BY], n)) < 0)
- return r;
-
- return 0;
-}
-
-int name_sanitize(Name *n) {
- NameDependency d;
-
- assert(n);
-
- /* Remove loops */
- for (d = 0; d < _NAME_DEPENDENCY_MAX; d++)
- set_remove(n->meta.dependencies[d], n);
-
- return augment(n);
-}
-
const char* name_id(Name *n) {
assert(n);
char *t;
NameDependency d;
Iterator i;
+ char *prefix2;
assert(n);
if (!prefix)
prefix = "";
+ prefix2 = strappend(prefix, "\t");
+ if (!prefix2)
+ prefix2 = "";
fprintf(f,
- "%sName %s:\n"
+ "%s→ Name %s:\n"
"%s\tDescription: %s\n"
"%s\tName Load State: %s\n"
"%s\tName Active State: %s\n",
}
if (NAME_VTABLE(n)->dump)
- NAME_VTABLE(n)->dump(n, f, prefix);
-
- if (n->meta.job) {
- char *p;
+ NAME_VTABLE(n)->dump(n, f, prefix2);
- if (asprintf(&p, "%s\t", prefix) >= 0)
- prefix = p;
- else
- p = NULL;
+ if (n->meta.job)
+ job_dump(n->meta.job, f, prefix2);
- job_dump(n->meta.job, f, prefix);
- free(p);
- }
+ free(prefix2);
}
static int verify_type(Name *name) {
if ((r = NAME_VTABLE(name)->init(name)) < 0)
goto fail;
- if ((r = name_sanitize(name)) < 0)
- goto fail;
-
- if ((r = name_link_names(name, false)) < 0)
- goto fail;
-
name->meta.load_state = NAME_LOADED;
return 0;
return NULL;
memcpy(n, t, a);
- memcpy(n+a, t, b+1);
+ memcpy(n+a, suffix, b+1);
return n;
}
assert_not_reached("Invalid job type");
}
}
+
+int name_add_dependency(Name *n, NameDependency d, Name *other) {
+
+ static const NameDependency inverse_table[_NAME_DEPENDENCY_MAX] = {
+ [NAME_REQUIRES] = NAME_REQUIRED_BY,
+ [NAME_SOFT_REQUIRES] = NAME_SOFT_REQUIRED_BY,
+ [NAME_WANTS] = NAME_WANTED_BY,
+ [NAME_REQUISITE] = NAME_REQUIRED_BY,
+ [NAME_SOFT_REQUISITE] = NAME_SOFT_REQUIRED_BY,
+ [NAME_REQUIRED_BY] = _NAME_DEPENDENCY_INVALID,
+ [NAME_SOFT_REQUIRED_BY] = _NAME_DEPENDENCY_INVALID,
+ [NAME_WANTED_BY] = _NAME_DEPENDENCY_INVALID,
+ [NAME_CONFLICTS] = NAME_CONFLICTS,
+ [NAME_BEFORE] = NAME_AFTER,
+ [NAME_AFTER] = NAME_BEFORE
+ };
+ int r;
+
+ assert(n);
+ assert(d >= 0 && d < _NAME_DEPENDENCY_MAX);
+ assert(inverse_table[d] != _NAME_DEPENDENCY_INVALID);
+ assert(other);
+
+ if (n == other)
+ return 0;
+
+ if ((r = set_ensure_allocated(&n->meta.dependencies[d], trivial_hash_func, trivial_compare_func)) < 0)
+ return r;
+
+ if ((r = set_ensure_allocated(&other->meta.dependencies[inverse_table[d]], trivial_hash_func, trivial_compare_func)) < 0)
+ return r;
+
+ if ((r = set_put(n->meta.dependencies[d], other)) < 0)
+ return r;
+
+ if ((r = set_put(other->meta.dependencies[inverse_table[d]], n)) < 0) {
+ set_remove(n->meta.dependencies[d], other);
+ return r;
+ }
+
+ return 0;
+}