chiark / gitweb /
first try at implementing dependency loader
[elogind.git] / manager.c
index d6bc35a289d04034f8fe275a1400f0b5ebd20184..0ad60b2b0bd85dea191782aaf718ff73f21c3304 100644 (file)
--- a/manager.c
+++ b/manager.c
@@ -2,11 +2,13 @@
 
 #include <assert.h>
 #include <errno.h>
+#include <string.h>
 
 #include "manager.h"
 #include "hashmap.h"
 #include "macro.h"
 #include "strv.h"
+#include "load-fragment.h"
 
 Manager* manager_new(void) {
         Manager *m;
@@ -90,28 +92,28 @@ int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_r
                 goto fail;
 
         if (type == JOB_START || type == JOB_VERIFY_STARTED || type == JOB_RESTART_FINISH) {
-                SET_FOREACH(dep, ret->name->meta.requires, state)
+                SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUIRES], state)
                         if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
                                 goto fail;
-                SET_FOREACH(dep, ret->name->meta.soft_requires, state)
+                SET_FOREACH(dep, ret->name->meta.dependencies[NAME_SOFT_REQUIRES], state)
                         if ((r = manager_add_job(m, type, dep, JOB_FAIL, NULL)) < 0)
                                 goto fail;
-                SET_FOREACH(dep, ret->name->meta.wants, state)
+                SET_FOREACH(dep, ret->name->meta.dependencies[NAME_WANTS], state)
                         if ((r = manager_add_job(m, type, dep, JOB_FAIL, NULL)) < 0)
                                 goto fail;
-                SET_FOREACH(dep, ret->name->meta.requisite, state)
+                SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUISITE], state)
                         if ((r = manager_add_job(m, JOB_VERIFY_STARTED, dep, mode, NULL)) < 0)
                                 goto fail;
-                SET_FOREACH(dep, ret->name->meta.soft_requisite, state)
+                SET_FOREACH(dep, ret->name->meta.dependencies[NAME_SOFT_REQUISITE], state)
                         if ((r = manager_add_job(m, JOB_VERIFY_STARTED, dep, JOB_FAIL, NULL)) < 0)
                                 goto fail;
-                SET_FOREACH(dep, ret->name->meta.conflicts, state)
+                SET_FOREACH(dep, ret->name->meta.dependencies[NAME_CONFLICTS], state)
                         if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
                                 goto fail;
 
         } else if (type == JOB_STOP || type == JOB_RESTART || type == JOB_TRY_RESTART) {
 
-                SET_FOREACH(dep, ret->name->meta.required_by, state)
+                SET_FOREACH(dep, ret->name->meta.dependencies[NAME_REQUIRED_BY], state)
                         if ((r = manager_add_job(m, type, dep, mode, NULL)) < 0)
                                 goto fail;
         }
@@ -141,17 +143,18 @@ Name *manager_get_name(Manager *m, const char *name) {
         return hashmap_get(m->names, name);
 }
 
-static int detect_type(Name *name) {
-        char **n;
+static int verify_type(Name *name) {
+        char *n;
+        void *state;
 
         assert(name);
 
-        name->meta.type = _NAME_TYPE_INVALID;
+        /* Checks that all aliases of this name have the same and valid type */
 
-        STRV_FOREACH(n, name->meta.names) {
+        SET_FOREACH(n, name->meta.names, state) {
                 NameType t;
 
-                if ((t = name_type_from_string(*n)) == _NAME_TYPE_INVALID)
+                if ((t = name_type_from_string(n)) == _NAME_TYPE_INVALID)
                         return -EINVAL;
 
                 if (name->meta.type == _NAME_TYPE_INVALID) {
@@ -163,30 +166,26 @@ static int detect_type(Name *name) {
                         return -EINVAL;
         }
 
-        return 0;
-}
-
-static int fragment_load(Name *n) {
-        assert(n);
-
-        /*... */
+        if (name->meta.type == _NAME_TYPE_INVALID)
+                return -EINVAL;
 
         return 0;
 }
 
-static int sysv_load(Service *s) {
+static int service_load_sysv(Service *s) {
         assert(s);
 
-        /*... */
+        /* Load service data from SysV init scripts, preferably with
+         * LSB headers ... */
 
         return 0;
 }
 
-static int fstab_load(Name *n) {
+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;
 }
@@ -194,7 +193,15 @@ static int fstab_load(Name *n) {
 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;
 }
@@ -207,24 +214,24 @@ static int load(Name *name) {
         if (name->meta.state != NAME_STUB)
                 return 0;
 
-        if ((r = detect_type(name)) < 0)
+        if ((r = verify_type(name)) < 0)
                 return r;
 
         if (name->meta.type == NAME_SERVICE) {
 
                 /* Load a .service file */
-                if ((r = fragment_load(name)) == 0)
+                if ((r = name_load_fragment(name)) == 0)
                         goto finish;
 
                 /* Load a classic init script */
                 if (r == -ENOENT)
-                        if ((r = sysv_load(SERVICE(name))) == 0)
+                        if ((r = service_load_sysv(SERVICE(name))) == 0)
                                 goto finish;
 
         } else if (name->meta.type == NAME_MOUNT ||
                    name->meta.type == NAME_AUTOMOUNT) {
 
-                if ((r = fstab_load(name)) == 0)
+                if ((r = name_load_fstab(name)) == 0)
                         goto finish;
 
         } else if (name->meta.type == NAME_SNAPSHOT) {
@@ -233,7 +240,7 @@ static int load(Name *name) {
                         goto finish;
 
         } else {
-                if ((r = fragment_load(name)) == 0)
+                if ((r = name_load_fragment(name)) == 0)
                         goto finish;
         }
 
@@ -241,6 +248,9 @@ static int load(Name *name) {
         return r;
 
 finish:
+        if ((r = name_load_dropin(name)) < 0)
+                return r;
+
         name->meta.state = NAME_LOADED;
         return 0;
 }
@@ -250,6 +260,12 @@ static int dispatch_load_queue(Manager *m) {
 
         assert(m);
 
+        /* Make sure we are not run recursively */
+        if (m->dispatching_load_queue)
+                return 0;
+
+        m->dispatching_load_queue = true;
+
         /* Dispatches the load queue. Takes a name from the queue and
          * tries to load its data until the queue is empty */
 
@@ -258,22 +274,26 @@ static int dispatch_load_queue(Manager *m) {
                 LIST_REMOVE(Meta, m->load_queue, meta);
         }
 
+        m->dispatching_load_queue = false;
+
         return 0;
 }
 
-
-
 int manager_load_name(Manager *m, const char *name, Name **_ret) {
         Name *ret;
         NameType t;
         int r;
+        char *n;
 
         assert(m);
         assert(name);
         assert(_ret);
-/* This will load the service information files, but not actually
- * start any services or anything */
 
+        if (!name_is_valid(name))
+                return -EINVAL;
+
+        /* This will load the service information files, but not actually
+         * start any services or anything */
 
         if ((ret = manager_get_name(m, name)))
                 goto finish;
@@ -286,8 +306,14 @@ int manager_load_name(Manager *m, const char *name, Name **_ret) {
 
         ret->meta.type = t;
 
-        if (!(ret->meta.names = strv_new(name, NULL))) {
+        if (!(n = strdup(name))) {
+                name_free(ret);
+                return -ENOMEM;
+        }
+
+        if (set_put(ret->meta.names, n) < 0) {
                 name_free(ret);
+                free(n);
                 return -ENOMEM;
         }