chiark / gitweb /
first try at implementing job creation
authorLennart Poettering <lennart@poettering.net>
Tue, 19 Jan 2010 03:15:20 +0000 (04:15 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 19 Jan 2010 03:15:20 +0000 (04:15 +0100)
15 files changed:
default.milestone
hashmap.c
hashmap.h
job.c
job.h
load-fragment.c
main.c
manager.c
manager.h
name.c
name.h
postfix.socket
set.c
set.h
syslog.socket

index 48f1171..c20a10e 100644 (file)
@@ -1,3 +1,4 @@
 [Meta]
-Wants=postfix.socket
+Names=multiuser.milestone
+Wants=postfix.socket syslog.socket
 Description=Default Milestone
index 4db6173..c55a07a 100644 (file)
--- a/hashmap.c
+++ b/hashmap.c
@@ -106,12 +106,19 @@ void hashmap_free(Hashmap*h) {
         if (!h)
                 return;
 
-        while (h->iterate_list_head)
-                remove_entry(h, h->iterate_list_head);
+        hashmap_clear(h);
 
         free(h);
 }
 
+void hashmap_clear(Hashmap *h) {
+        if (!h)
+                return;
+
+        while (h->iterate_list_head)
+                remove_entry(h, h->iterate_list_head);
+}
+
 static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) {
         struct hashmap_entry *e;
         assert(h);
index e3b9d9a..91d8b46 100644 (file)
--- a/hashmap.h
+++ b/hashmap.h
@@ -37,6 +37,7 @@ bool hashmap_isempty(Hashmap *h);
 void *hashmap_iterate(Hashmap *h, void **state, const void **key);
 void *hashmap_iterate_backwards(Hashmap *h, void **state, const void **key);
 
+void hashmap_clear(Hashmap *h);
 void *hashmap_steal_first(Hashmap *h);
 void* hashmap_first(Hashmap *h);
 void* hashmap_last(Hashmap *h);
@@ -44,6 +45,9 @@ void* hashmap_last(Hashmap *h);
 #define HASHMAP_FOREACH(e, h, state) \
         for ((state) = NULL, (e) = hashmap_iterate((h), &(state), NULL); (e); (e) = hashmap_iterate((h), &(state), NULL))
 
+#define HASHMAP_FOREACH_KEY(e, k, h, state) \
+        for ((state) = NULL, (e) = hashmap_iterate((h), &(state), (const void**) &(k)); (e); (e) = hashmap_iterate((h), &(state), (const void**) &(k)))
+
 #define HASHMAP_FOREACH_BACKWARDS(e, h, state) \
         for ((state) = NULL, (e) = hashmap_iterate_backwards((h), &(state), NULL); (e); (e) = hashmap_iterate_backwards((h), &(state), NULL))
 
diff --git a/job.c b/job.c
index 2cf8be5..2f7912d 100644 (file)
--- a/job.c
+++ b/job.c
@@ -25,31 +25,14 @@ Job* job_new(Manager *m, JobType type, Name *name) {
         return j;
 }
 
-int job_link(Job *j) {
-        int r;
-
-        assert(j);
-        assert(!j->linked);
-
-        if ((r = hashmap_put(j->manager->jobs, UINT32_TO_PTR(j->id), j)) < 0)
-                return r;
-
-        j->name->meta.job = j;
-
-        j->linked = true;
-
-        return 0;
-}
-
 void job_free(Job *j) {
         assert(j);
 
         /* Detach from next 'bigger' objects */
 
         if (j->linked) {
-                assert(j->name);
-                assert(j->name->meta.job == j);
-                j->name->meta.job = NULL;
+                if (j->name->meta.job == j)
+                        j->name->meta.job = NULL;
 
                 hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
         }
@@ -82,7 +65,7 @@ void job_dump(Job *j, FILE*f) {
         assert(j);
         assert(f);
 
-        fprintf(f, "Job %u (%s) →%s in state %s\n",
+        fprintf(f, "Job %u (%s) → %s in state %s\n",
                 j->id,
                 name_id(j->name),
                 job_type_table[j->type],
diff --git a/job.h b/job.h
index 0fc6fec..0cb0a6e 100644 (file)
--- a/job.h
+++ b/job.h
@@ -51,7 +51,6 @@ struct Job {
 };
 
 Job* job_new(Manager *m, JobType type, Name *name);
-int job_link(Job *job);
 void job_free(Job *job);
 void job_dump(Job *j, FILE*f);
 
index d6b5e2f..05a7114 100644 (file)
@@ -111,6 +111,8 @@ static int config_parse_names(
                                 free(t);
                                 return r;
                         }
+
+                        t = NULL;
                 }
 
                 free(t);
diff --git a/main.c b/main.c
index f19fb6b..a5c1694 100644 (file)
--- a/main.c
+++ b/main.c
@@ -23,12 +23,13 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
-        manager_dump_names(m, stdout);
 
-        /* if ((r = manager_add_job(m, JOB_START, milestone, JOB_REPLACE, &job)) < 0) { */
-        /*         fprintf(stderr, "Failed to start default milestone: %s\n", strerror(-r)); */
-        /*         goto finish; */
-        /* } */
+        if ((r = manager_add_job(m, JOB_START, milestone, JOB_REPLACE, &job)) < 0) {
+                fprintf(stderr, "Failed to start default milestone: %s\n", strerror(-r));
+                goto finish;
+        }
+
+        manager_dump_names(m, stdout);
 
         retval = 0;
 
index 86ed086..d2708aa 100644 (file)
--- 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);
 }
index c08f3cc..3ee3b0a 100644 (file)
--- a/manager.h
+++ b/manager.h
@@ -34,6 +34,8 @@ struct Manager {
         Set *jobs_to_remove;
 
         bool dispatching_load_queue:1;
+
+        unsigned n_dependency_depth;
 };
 
 Manager* manager_new(void);
diff --git a/name.c b/name.c
index cbd847a..0ef7a77 100644 (file)
--- a/name.c
+++ b/name.c
@@ -80,31 +80,55 @@ Name *name_new(Manager *m) {
         return n;
 }
 
+int name_link_names(Name *n) {
+        char *t;
+        void *state;
+        int r;
+
+        assert(n);
+
+        if (!n->meta.linked)
+                return 0;
+
+        /* Link all names that aren't linked yet */
+
+        SET_FOREACH(t, n->meta.names, state)
+                if ((r = hashmap_put(n->meta.manager->names, t, n)) < 0) {
+
+                        if (r == -EEXIST && hashmap_get(n->meta.manager->names, t) == n)
+                                continue;
+
+                        return r;
+                }
+
+        return 0;
+}
+
 int name_link(Name *n) {
-        char **t;
         int r;
-        void *state;
 
         assert(n);
         assert(!set_isempty(n->meta.names));
         assert(!n->meta.linked);
 
-        SET_FOREACH(t, n->meta.names, state)
-                if ((r = hashmap_put(n->meta.manager->names, t, n)) < 0)
-                        goto fail;
+        n->meta.linked = true;
 
-        if (n->meta.state == NAME_STUB)
-                LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
+        if ((r = name_link_names(n) < 0)) {
+                char *t;
+                void *state;
 
-        n->meta.linked = true;
+                /* Rollback the registered names */
+                SET_FOREACH(t, n->meta.names, state)
+                        hashmap_remove(n->meta.manager->names, t);
 
-        return 0;
+                n->meta.linked = false;
+                return r;
+        }
 
-fail:
-        SET_FOREACH(t, n->meta.names, state)
-                assert_se(hashmap_remove(n->meta.manager->names, t) == n);
+        if (n->meta.state == NAME_STUB)
+                LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
 
-        return r;
+        return 0;
 }
 
 static void bidi_set_free(Name *name, Set *s) {
@@ -134,7 +158,7 @@ void name_free(Name *name) {
 
         /* Detach from next 'bigger' objects */
         if (name->meta.linked) {
-                char **t;
+                char *t;
                 void *state;
 
                 SET_FOREACH(t, name->meta.names, state)
@@ -357,6 +381,10 @@ int name_merge(Name *name, Name *other) {
                 if ((r = ensure_merge(&name->meta.dependencies[d], other->meta.dependencies[d])) < 0)
                         return r;
 
+        if (name->meta.linked)
+                if ((r = name_link_names(name)) < 0)
+                        return r;
+
         return 0;
 }
 
@@ -388,14 +416,24 @@ void name_dump(Name *n, FILE *f) {
                 [SOCKET_MAINTAINANCE] = "maintainance"
         };
 
+        void *state;
+        char *t;
+
         assert(n);
 
-        fprintf(stderr,
-                "Name %s (\"%s\") in state %s\n",
+        fprintf(f,
+                "Name %s\n"
+                "\tDescription: %s\n"
+                "\tState: %s\n",
                 name_id(n),
                 n->meta.description ? n->meta.description : name_id(n),
                 state_table[n->meta.state]);
 
+        fprintf(f, "\tNames: ");
+        SET_FOREACH(t, n->meta.names, state)
+                fprintf(f, "%s ", t);
+        fprintf(f, "\n");
+
         switch (n->meta.type) {
                 case NAME_SOCKET: {
                         int r;
@@ -407,7 +445,7 @@ void name_dump(Name *n, FILE *f) {
                         else
                                 t = s;
 
-                        fprintf(stderr, "\t%s in state %s\n", t, socket_state_table[n->socket.state]);
+                        fprintf(f, "\t%s in state %s\n", t, socket_state_table[n->socket.state]);
                         free(s);
                         break;
                 }
@@ -417,7 +455,7 @@ void name_dump(Name *n, FILE *f) {
         }
 
         if (n->meta.job) {
-                fprintf(f, "\t▶ ");
+                fprintf(f, "\t");
                 job_dump(n->meta.job, f);
         }
 }
diff --git a/name.h b/name.h
index 0ed1056..67ca6f1 100644 (file)
--- a/name.h
+++ b/name.h
@@ -279,6 +279,7 @@ bool name_is_valid(const char *n);
 Name *name_new(Manager *m);
 void name_free(Name *name);
 int name_link(Name *name);
+int name_link_names(Name *name);
 int name_merge(Name *name, Name *other);
 int name_augment(Name *n);
 const char* name_id(Name *n);
index da5b093..8f9c0e8 100644 (file)
@@ -1,5 +1,5 @@
 [Meta]
-Description=Postfix Listening Socket
+Description=Postfix SMTP Socket
 
 [Socket]
 Listen=25
diff --git a/set.c b/set.c
index 21a1739..74137b7 100644 (file)
--- a/set.c
+++ b/set.c
@@ -69,3 +69,7 @@ int set_merge(Set *s, Set *other) {
 Set* set_copy(Set *s) {
         return MAKE_SET(hashmap_copy(MAKE_HASHMAP(s)));
 }
+
+void set_clear(Set *s) {
+        hashmap_clear(MAKE_HASHMAP(s));
+}
diff --git a/set.h b/set.h
index a2e4059..b206ba8 100644 (file)
--- a/set.h
+++ b/set.h
@@ -29,6 +29,7 @@ bool set_isempty(Set *s);
 void *set_iterate(Set *s, void **state);
 void *set_iterate_backwards(Set *s, void **state);
 
+void set_clear(Set *s);
 void *set_steal_first(Set *s);
 void* set_first(Set *s);
 void* set_last(Set *s);
index 3d5fa81..b599762 100644 (file)
@@ -1,2 +1,6 @@
+[Meta]
+Description=Syslog Socket
+
 [Socket]
 Listen=/dev/log
+Type=dgram