chiark / gitweb /
get rid of 'linked' notion for objects
[elogind.git] / name.c
diff --git a/name.c b/name.c
index dae2a3f4f025df344a5538c099e5db86b2d30e79..e88dc85839a4e5b5fa5d2d05decf9be158f00e08 100644 (file)
--- a/name.c
+++ b/name.c
 #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,
@@ -82,8 +83,6 @@ Name *name_new(Manager *m) {
         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;
 }
 
@@ -109,6 +108,12 @@ int name_add_name(Name *n, const char *text) {
                 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)
@@ -117,61 +122,14 @@ int name_add_name(Name *n, const char *text) {
         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) {
@@ -195,21 +153,22 @@ 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)
@@ -218,9 +177,6 @@ void name_free(Name *name) {
         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)))
@@ -239,21 +195,6 @@ NameActiveState name_active_state(Name *name) {
         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)
@@ -292,73 +233,13 @@ int name_merge(Name *name, Name *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);
 
@@ -409,14 +290,18 @@ void name_dump(Name *n, FILE *f, const char *prefix) {
         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",
@@ -439,19 +324,12 @@ void name_dump(Name *n, FILE *f, const char *prefix) {
         }
 
         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) {
@@ -520,12 +398,6 @@ int name_load(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;
 
@@ -890,7 +762,7 @@ char *name_change_suffix(const char *t, const char *suffix) {
                 return NULL;
 
         memcpy(n, t, a);
-        memcpy(n+a, t, b+1);
+        memcpy(n+a, suffix, b+1);
 
         return n;
 }
@@ -919,3 +791,45 @@ bool name_job_is_applicable(Name *n, JobType j) {
                         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;
+}