summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--default.milestone3
-rw-r--r--hashmap.c11
-rw-r--r--hashmap.h4
-rw-r--r--job.c23
-rw-r--r--job.h1
-rw-r--r--load-fragment.c2
-rw-r--r--main.c11
-rw-r--r--manager.c74
-rw-r--r--manager.h2
-rw-r--r--name.c74
-rw-r--r--name.h1
-rw-r--r--postfix.socket2
-rw-r--r--set.c4
-rw-r--r--set.h1
-rw-r--r--syslog.socket4
15 files changed, 166 insertions, 51 deletions
diff --git a/default.milestone b/default.milestone
index 48f117139b..c20a10e91b 100644
--- a/default.milestone
+++ b/default.milestone
@@ -1,3 +1,4 @@
[Meta]
-Wants=postfix.socket
+Names=multiuser.milestone
+Wants=postfix.socket syslog.socket
Description=Default Milestone
diff --git a/hashmap.c b/hashmap.c
index 4db61732fa..c55a07a884 100644
--- 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);
diff --git a/hashmap.h b/hashmap.h
index e3b9d9aa30..91d8b46dba 100644
--- 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 2cf8be5330..2f7912d262 100644
--- 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 0fc6fec462..0cb0a6e812 100644
--- 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);
diff --git a/load-fragment.c b/load-fragment.c
index d6b5e2f397..05a7114b44 100644
--- a/load-fragment.c
+++ b/load-fragment.c
@@ -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 f19fb6b5cd..a5c169454e 100644
--- 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;
diff --git a/manager.c b/manager.c
index 86ed086eb3..d2708aacf3 100644
--- 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);
}
diff --git a/manager.h b/manager.h
index c08f3ccde5..3ee3b0ac59 100644
--- 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 cbd847a916..0ef7a77ff8 100644
--- 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 0ed1056595..67ca6f10ef 100644
--- 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);
diff --git a/postfix.socket b/postfix.socket
index da5b09312b..8f9c0e8aa1 100644
--- a/postfix.socket
+++ b/postfix.socket
@@ -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 21a1739b03..74137b775f 100644
--- 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 a2e405941c..b206ba80f6 100644
--- 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);
diff --git a/syslog.socket b/syslog.socket
index 3d5fa818af..b599762e7c 100644
--- a/syslog.socket
+++ b/syslog.socket
@@ -1,2 +1,6 @@
+[Meta]
+Description=Syslog Socket
+
[Socket]
Listen=/dev/log
+Type=dgram