first try at implementing job creation

This commit is contained in:
Lennart Poettering 2010-01-19 04:15:20 +01:00
parent 42f4e3c441
commit 11dd41ce4b
15 changed files with 167 additions and 52 deletions

View File

@ -1,3 +1,4 @@
[Meta]
Wants=postfix.socket
Names=multiuser.milestone
Wants=postfix.socket syslog.socket
Description=Default Milestone

View File

@ -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);

View File

@ -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))

23
job.c
View File

@ -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],

1
job.h
View File

@ -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);

View File

@ -111,6 +111,8 @@ static int config_parse_names(
free(t);
return r;
}
t = NULL;
}
free(t);

11
main.c
View File

@ -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;

View File

@ -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);
}

View File

@ -34,6 +34,8 @@ struct Manager {
Set *jobs_to_remove;
bool dispatching_load_queue:1;
unsigned n_dependency_depth;
};
Manager* manager_new(void);

76
name.c
View File

@ -80,31 +80,55 @@ Name *name_new(Manager *m) {
return n;
}
int name_link(Name *n) {
char **t;
int r;
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) {
int r;
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 ((r = name_link_names(n) < 0)) {
char *t;
void *state;
/* Rollback the registered names */
SET_FOREACH(t, n->meta.names, state)
hashmap_remove(n->meta.manager->names, t);
n->meta.linked = false;
return r;
}
if (n->meta.state == NAME_STUB)
LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
n->meta.linked = true;
return 0;
fail:
SET_FOREACH(t, n->meta.names, state)
assert_se(hashmap_remove(n->meta.manager->names, t) == n);
return r;
}
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);
}
}

1
name.h
View File

@ -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);

View File

@ -1,5 +1,5 @@
[Meta]
Description=Postfix Listening Socket
Description=Postfix SMTP Socket
[Socket]
Listen=25

4
set.c
View File

@ -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));
}

1
set.h
View File

@ -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);

View File

@ -1,2 +1,6 @@
[Meta]
Description=Syslog Socket
[Socket]
Listen=/dev/log
Type=dgram