first try at implementing job creation
This commit is contained in:
parent
42f4e3c441
commit
11dd41ce4b
|
@ -1,3 +1,4 @@
|
||||||
[Meta]
|
[Meta]
|
||||||
Wants=postfix.socket
|
Names=multiuser.milestone
|
||||||
|
Wants=postfix.socket syslog.socket
|
||||||
Description=Default Milestone
|
Description=Default Milestone
|
||||||
|
|
11
hashmap.c
11
hashmap.c
|
@ -106,12 +106,19 @@ void hashmap_free(Hashmap*h) {
|
||||||
if (!h)
|
if (!h)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while (h->iterate_list_head)
|
hashmap_clear(h);
|
||||||
remove_entry(h, h->iterate_list_head);
|
|
||||||
|
|
||||||
free(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) {
|
static struct hashmap_entry *hash_scan(Hashmap *h, unsigned hash, const void *key) {
|
||||||
struct hashmap_entry *e;
|
struct hashmap_entry *e;
|
||||||
assert(h);
|
assert(h);
|
||||||
|
|
|
@ -37,6 +37,7 @@ bool hashmap_isempty(Hashmap *h);
|
||||||
void *hashmap_iterate(Hashmap *h, void **state, const void **key);
|
void *hashmap_iterate(Hashmap *h, void **state, const void **key);
|
||||||
void *hashmap_iterate_backwards(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_steal_first(Hashmap *h);
|
||||||
void* hashmap_first(Hashmap *h);
|
void* hashmap_first(Hashmap *h);
|
||||||
void* hashmap_last(Hashmap *h);
|
void* hashmap_last(Hashmap *h);
|
||||||
|
@ -44,6 +45,9 @@ void* hashmap_last(Hashmap *h);
|
||||||
#define HASHMAP_FOREACH(e, h, state) \
|
#define HASHMAP_FOREACH(e, h, state) \
|
||||||
for ((state) = NULL, (e) = hashmap_iterate((h), &(state), NULL); (e); (e) = hashmap_iterate((h), &(state), NULL))
|
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) \
|
#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))
|
for ((state) = NULL, (e) = hashmap_iterate_backwards((h), &(state), NULL); (e); (e) = hashmap_iterate_backwards((h), &(state), NULL))
|
||||||
|
|
||||||
|
|
23
job.c
23
job.c
|
@ -25,31 +25,14 @@ Job* job_new(Manager *m, JobType type, Name *name) {
|
||||||
return j;
|
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) {
|
void job_free(Job *j) {
|
||||||
assert(j);
|
assert(j);
|
||||||
|
|
||||||
/* Detach from next 'bigger' objects */
|
/* Detach from next 'bigger' objects */
|
||||||
|
|
||||||
if (j->linked) {
|
if (j->linked) {
|
||||||
assert(j->name);
|
if (j->name->meta.job == j)
|
||||||
assert(j->name->meta.job == j);
|
j->name->meta.job = NULL;
|
||||||
j->name->meta.job = NULL;
|
|
||||||
|
|
||||||
hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
|
hashmap_remove(j->manager->jobs, UINT32_TO_PTR(j->id));
|
||||||
}
|
}
|
||||||
|
@ -82,7 +65,7 @@ void job_dump(Job *j, FILE*f) {
|
||||||
assert(j);
|
assert(j);
|
||||||
assert(f);
|
assert(f);
|
||||||
|
|
||||||
fprintf(f, "Job %u (%s) →%s in state %s\n",
|
fprintf(f, "Job %u (%s) → %s in state %s\n",
|
||||||
j->id,
|
j->id,
|
||||||
name_id(j->name),
|
name_id(j->name),
|
||||||
job_type_table[j->type],
|
job_type_table[j->type],
|
||||||
|
|
1
job.h
1
job.h
|
@ -51,7 +51,6 @@ struct Job {
|
||||||
};
|
};
|
||||||
|
|
||||||
Job* job_new(Manager *m, JobType type, Name *name);
|
Job* job_new(Manager *m, JobType type, Name *name);
|
||||||
int job_link(Job *job);
|
|
||||||
void job_free(Job *job);
|
void job_free(Job *job);
|
||||||
void job_dump(Job *j, FILE*f);
|
void job_dump(Job *j, FILE*f);
|
||||||
|
|
||||||
|
|
|
@ -111,6 +111,8 @@ static int config_parse_names(
|
||||||
free(t);
|
free(t);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
t = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(t);
|
free(t);
|
||||||
|
|
11
main.c
11
main.c
|
@ -23,12 +23,13 @@ int main(int argc, char *argv[]) {
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
manager_dump_names(m, stdout);
|
|
||||||
|
|
||||||
/* if ((r = manager_add_job(m, JOB_START, milestone, JOB_REPLACE, &job)) < 0) { */
|
if ((r = manager_add_job(m, JOB_START, milestone, JOB_REPLACE, &job)) < 0) {
|
||||||
/* fprintf(stderr, "Failed to start default milestone: %s\n", strerror(-r)); */
|
fprintf(stderr, "Failed to start default milestone: %s\n", strerror(-r));
|
||||||
/* goto finish; */
|
goto finish;
|
||||||
/* } */
|
}
|
||||||
|
|
||||||
|
manager_dump_names(m, stdout);
|
||||||
|
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
||||||
|
|
74
manager.c
74
manager.c
|
@ -54,6 +54,58 @@ void manager_free(Manager *m) {
|
||||||
free(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) {
|
int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_ret) {
|
||||||
Job *ret, *other;
|
Job *ret, *other;
|
||||||
void *state;
|
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(type < _JOB_TYPE_MAX);
|
||||||
assert(name);
|
assert(name);
|
||||||
assert(mode < _JOB_MODE_MAX);
|
assert(mode < _JOB_MODE_MAX);
|
||||||
assert(_ret);
|
|
||||||
|
|
||||||
/* Check for conflicts, first against the jobs we shall
|
/* Check for conflicts, first against the jobs we shall
|
||||||
* create */
|
* 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)))
|
if (!(ret = job_new(m, type, name)))
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
m->n_dependency_depth ++;
|
||||||
|
|
||||||
if ((r = hashmap_put(m->jobs_to_add, name, ret)) < 0)
|
if ((r = hashmap_put(m->jobs_to_add, name, ret)) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
@ -118,6 +171,13 @@ int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_r
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (--m->n_dependency_depth <= 0)
|
||||||
|
if ((r = transaction_activate(m)) < 0) {
|
||||||
|
transaction_abort(m);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (_ret)
|
if (_ret)
|
||||||
*_ret = ret;
|
*_ret = ret;
|
||||||
|
|
||||||
|
@ -126,6 +186,9 @@ int manager_add_job(Manager *m, JobType type, Name *name, JobMode mode, Job **_r
|
||||||
fail:
|
fail:
|
||||||
job_free(ret);
|
job_free(ret);
|
||||||
|
|
||||||
|
if (--m->n_dependency_depth <= 0)
|
||||||
|
transaction_abort(m);
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,6 +314,9 @@ finish:
|
||||||
if ((r = name_load_dropin(name)) < 0)
|
if ((r = name_load_dropin(name)) < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if ((r = name_link_names(name)) < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
name->meta.state = NAME_LOADED;
|
name->meta.state = NAME_LOADED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -348,10 +414,12 @@ void manager_dump_jobs(Manager *s, FILE *f) {
|
||||||
void manager_dump_names(Manager *s, FILE *f) {
|
void manager_dump_names(Manager *s, FILE *f) {
|
||||||
void *state;
|
void *state;
|
||||||
Name *n;
|
Name *n;
|
||||||
|
const char *t;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
assert(f);
|
assert(f);
|
||||||
|
|
||||||
HASHMAP_FOREACH(n, s->names, state)
|
HASHMAP_FOREACH_KEY(n, t, s->names, state)
|
||||||
name_dump(n, f);
|
if (name_id(n) == t)
|
||||||
|
name_dump(n, f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,8 @@ struct Manager {
|
||||||
Set *jobs_to_remove;
|
Set *jobs_to_remove;
|
||||||
|
|
||||||
bool dispatching_load_queue:1;
|
bool dispatching_load_queue:1;
|
||||||
|
|
||||||
|
unsigned n_dependency_depth;
|
||||||
};
|
};
|
||||||
|
|
||||||
Manager* manager_new(void);
|
Manager* manager_new(void);
|
||||||
|
|
76
name.c
76
name.c
|
@ -80,31 +80,55 @@ Name *name_new(Manager *m) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int name_link(Name *n) {
|
int name_link_names(Name *n) {
|
||||||
char **t;
|
char *t;
|
||||||
int r;
|
|
||||||
void *state;
|
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(n);
|
||||||
assert(!set_isempty(n->meta.names));
|
assert(!set_isempty(n->meta.names));
|
||||||
assert(!n->meta.linked);
|
assert(!n->meta.linked);
|
||||||
|
|
||||||
SET_FOREACH(t, n->meta.names, state)
|
n->meta.linked = true;
|
||||||
if ((r = hashmap_put(n->meta.manager->names, t, n)) < 0)
|
|
||||||
goto fail;
|
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)
|
if (n->meta.state == NAME_STUB)
|
||||||
LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
|
LIST_PREPEND(Meta, n->meta.manager->load_queue, &n->meta);
|
||||||
|
|
||||||
n->meta.linked = true;
|
|
||||||
|
|
||||||
return 0;
|
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) {
|
static void bidi_set_free(Name *name, Set *s) {
|
||||||
|
@ -134,7 +158,7 @@ void name_free(Name *name) {
|
||||||
|
|
||||||
/* Detach from next 'bigger' objects */
|
/* Detach from next 'bigger' objects */
|
||||||
if (name->meta.linked) {
|
if (name->meta.linked) {
|
||||||
char **t;
|
char *t;
|
||||||
void *state;
|
void *state;
|
||||||
|
|
||||||
SET_FOREACH(t, name->meta.names, 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)
|
if ((r = ensure_merge(&name->meta.dependencies[d], other->meta.dependencies[d])) < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if (name->meta.linked)
|
||||||
|
if ((r = name_link_names(name)) < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,14 +416,24 @@ void name_dump(Name *n, FILE *f) {
|
||||||
[SOCKET_MAINTAINANCE] = "maintainance"
|
[SOCKET_MAINTAINANCE] = "maintainance"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void *state;
|
||||||
|
char *t;
|
||||||
|
|
||||||
assert(n);
|
assert(n);
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(f,
|
||||||
"Name %s (\"%s\") in state %s\n",
|
"Name %s\n"
|
||||||
|
"\tDescription: %s\n"
|
||||||
|
"\tState: %s\n",
|
||||||
name_id(n),
|
name_id(n),
|
||||||
n->meta.description ? n->meta.description : name_id(n),
|
n->meta.description ? n->meta.description : name_id(n),
|
||||||
state_table[n->meta.state]);
|
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) {
|
switch (n->meta.type) {
|
||||||
case NAME_SOCKET: {
|
case NAME_SOCKET: {
|
||||||
int r;
|
int r;
|
||||||
|
@ -407,7 +445,7 @@ void name_dump(Name *n, FILE *f) {
|
||||||
else
|
else
|
||||||
t = s;
|
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);
|
free(s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -417,7 +455,7 @@ void name_dump(Name *n, FILE *f) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n->meta.job) {
|
if (n->meta.job) {
|
||||||
fprintf(f, "\t▶ ");
|
fprintf(f, "\t");
|
||||||
job_dump(n->meta.job, f);
|
job_dump(n->meta.job, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
name.h
1
name.h
|
@ -279,6 +279,7 @@ bool name_is_valid(const char *n);
|
||||||
Name *name_new(Manager *m);
|
Name *name_new(Manager *m);
|
||||||
void name_free(Name *name);
|
void name_free(Name *name);
|
||||||
int name_link(Name *name);
|
int name_link(Name *name);
|
||||||
|
int name_link_names(Name *name);
|
||||||
int name_merge(Name *name, Name *other);
|
int name_merge(Name *name, Name *other);
|
||||||
int name_augment(Name *n);
|
int name_augment(Name *n);
|
||||||
const char* name_id(Name *n);
|
const char* name_id(Name *n);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
[Meta]
|
[Meta]
|
||||||
Description=Postfix Listening Socket
|
Description=Postfix SMTP Socket
|
||||||
|
|
||||||
[Socket]
|
[Socket]
|
||||||
Listen=25
|
Listen=25
|
||||||
|
|
4
set.c
4
set.c
|
@ -69,3 +69,7 @@ int set_merge(Set *s, Set *other) {
|
||||||
Set* set_copy(Set *s) {
|
Set* set_copy(Set *s) {
|
||||||
return MAKE_SET(hashmap_copy(MAKE_HASHMAP(s)));
|
return MAKE_SET(hashmap_copy(MAKE_HASHMAP(s)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_clear(Set *s) {
|
||||||
|
hashmap_clear(MAKE_HASHMAP(s));
|
||||||
|
}
|
||||||
|
|
1
set.h
1
set.h
|
@ -29,6 +29,7 @@ bool set_isempty(Set *s);
|
||||||
void *set_iterate(Set *s, void **state);
|
void *set_iterate(Set *s, void **state);
|
||||||
void *set_iterate_backwards(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_steal_first(Set *s);
|
||||||
void* set_first(Set *s);
|
void* set_first(Set *s);
|
||||||
void* set_last(Set *s);
|
void* set_last(Set *s);
|
||||||
|
|
|
@ -1,2 +1,6 @@
|
||||||
|
[Meta]
|
||||||
|
Description=Syslog Socket
|
||||||
|
|
||||||
[Socket]
|
[Socket]
|
||||||
Listen=/dev/log
|
Listen=/dev/log
|
||||||
|
Type=dgram
|
||||||
|
|
Loading…
Reference in a new issue