mirror of
https://github.com/systemd/systemd.git
synced 2024-11-27 20:23:36 +08:00
first try at implementing job creation
This commit is contained in:
parent
42f4e3c441
commit
11dd41ce4b
@ -1,3 +1,4 @@
|
||||
[Meta]
|
||||
Wants=postfix.socket
|
||||
Names=multiuser.milestone
|
||||
Wants=postfix.socket syslog.socket
|
||||
Description=Default Milestone
|
||||
|
11
hashmap.c
11
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);
|
||||
|
@ -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
23
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],
|
||||
|
1
job.h
1
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);
|
||||
|
||||
|
@ -111,6 +111,8 @@ static int config_parse_names(
|
||||
free(t);
|
||||
return r;
|
||||
}
|
||||
|
||||
t = NULL;
|
||||
}
|
||||
|
||||
free(t);
|
||||
|
11
main.c
11
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;
|
||||
|
||||
|
74
manager.c
74
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);
|
||||
}
|
||||
|
@ -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
76
name.c
@ -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
1
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);
|
||||
|
@ -1,5 +1,5 @@
|
||||
[Meta]
|
||||
Description=Postfix Listening Socket
|
||||
Description=Postfix SMTP Socket
|
||||
|
||||
[Socket]
|
||||
Listen=25
|
||||
|
4
set.c
4
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));
|
||||
}
|
||||
|
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_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);
|
||||
|
@ -1,2 +1,6 @@
|
||||
[Meta]
|
||||
Description=Syslog Socket
|
||||
|
||||
[Socket]
|
||||
Listen=/dev/log
|
||||
Type=dgram
|
||||
|
Loading…
Reference in New Issue
Block a user