X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=name.c;h=ace552975316703d2c2b48cfe1fcced4f5075da2;hb=ceed357001a7543c62468c5b943cf80c2a644252;hp=f29ce2298bbf3f73d2f203deb4b3f22cd71b5c06;hpb=87d1515de5ae611e95144def9ef4b2c0c933f6fe;p=elogind.git diff --git a/name.c b/name.c index f29ce2298..ace552975 100644 --- a/name.c +++ b/name.c @@ -80,31 +80,56 @@ Name *name_new(Manager *m) { return n; } +/* FIXME: Does not rollback on failure! */ +int name_link_names(Name *n, bool replace) { + 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 (replace) { + if ((r = hashmap_replace(n->meta.manager->names, t, n)) < 0) + return r; + } else { + if ((r = hashmap_put(n->meta.manager->names, t, n)) < 0) + 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, false) < 0)) { + char *t; + void *state; - n->meta.linked = true; + /* Rollback the registered names */ + SET_FOREACH(t, n->meta.names, state) + hashmap_remove_value(n->meta.manager->names, t, n); - 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) { @@ -112,7 +137,6 @@ static void bidi_set_free(Name *name, Set *s) { Name *other; assert(name); - assert(s); /* Frees the set and makes sure we are dropped from the * inverse pointers */ @@ -135,11 +159,11 @@ 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) - assert_se(hashmap_remove(name->meta.manager->names, t) == name); + hashmap_remove_value(name->meta.manager->names, t, name); if (name->meta.state == NAME_STUB) LIST_REMOVE(Meta, name->meta.manager->load_queue, &name->meta); @@ -159,7 +183,7 @@ void name_free(Name *name) { Socket *s = SOCKET(name); for (i = 0; i < s->n_fds; i++) - nointr_close(s->fds[i]); + close_nointr(s->fds[i]); break; } @@ -280,6 +304,7 @@ static int ensure_in_set(Set **s, void *data) { return 0; } +/* FIXME: Does not rollback on failure! */ int name_augment(Name *n) { int r; void* state; @@ -287,7 +312,8 @@ int name_augment(Name *n) { assert(n); - /* Adds in the missing links to make all dependencies bidirectional */ + /* Adds in the missing links to make all dependencies + * bidirectional. */ SET_FOREACH(other, n->meta.dependencies[NAME_BEFORE], state) if ((r = ensure_in_set(&other->meta.dependencies[NAME_AFTER], n) < 0)) @@ -334,15 +360,18 @@ static int ensure_merge(Set **s, Set *other) { return 0; } +/* FIXME: Does not rollback on failure! */ int name_merge(Name *name, Name *other) { int r; NameDependency d; assert(name); assert(other); - assert(name->meta.manager == other->meta.manager); + /* This merges 'other' into 'name'. FIXME: This does not + * rollback on failure. */ + if (name->meta.type != other->meta.type) return -EINVAL; @@ -358,5 +387,101 @@ int name_merge(Name *name, Name *other) { if ((r = ensure_merge(&name->meta.dependencies[d], other->meta.dependencies[d])) < 0) return r; + /* Hookup new deps and names */ + if (name->meta.linked) { + if ((r = name_augment(name)) < 0) + return r; + + if ((r = name_link_names(name, true)) < 0) + return r; + } + return 0; } + +const char* name_id(Name *n) { + assert(n); + + return set_first(n->meta.names); +} + +void name_dump(Name *n, FILE *f, const char *prefix) { + + static const char* const state_table[_NAME_STATE_MAX] = { + [NAME_STUB] = "stub", + [NAME_LOADED] = "loaded", + [NAME_FAILED] = "failed" + }; + + static const char* const socket_state_table[_SOCKET_STATE_MAX] = { + [SOCKET_DEAD] = "dead", + [SOCKET_BEFORE] = "before", + [SOCKET_START_PRE] = "start-pre", + [SOCKET_START] = "start", + [SOCKET_START_POST] = "start-post", + [SOCKET_LISTENING] = "listening", + [SOCKET_RUNNING] = "running", + [SOCKET_STOP_PRE] = "stop-pre", + [SOCKET_STOP] = "stop", + [SOCKET_STOP_POST] = "stop-post", + [SOCKET_MAINTAINANCE] = "maintainance" + }; + + void *state; + char *t; + + assert(n); + + if (!prefix) + prefix = ""; + + fprintf(f, + "%sName %s:\n" + "%s\tDescription: %s\n" + "%s\tName State: %s\n", + prefix, name_id(n), + prefix, n->meta.description ? n->meta.description : name_id(n), + prefix, state_table[n->meta.state]); + + fprintf(f, "%s\tNames: ", prefix); + SET_FOREACH(t, n->meta.names, state) + fprintf(f, "%s ", t); + fprintf(f, "\n"); + + switch (n->meta.type) { + case NAME_SOCKET: { + int r; + char *s = NULL; + const char *t; + + if ((r = address_print(&n->socket.address, &s)) < 0) + t = strerror(-r); + else + t = s; + + fprintf(f, + "%s\tAddress: %s\n" + "%s\tSocket State: %s\n", + prefix, t, + prefix, socket_state_table[n->socket.state]); + + free(s); + break; + } + + default: + ; + } + + if (n->meta.job) { + char *p; + + if (asprintf(&p, "%s\t", prefix) >= 0) + prefix = p; + else + p = NULL; + + job_dump(n->meta.job, f, prefix); + free(p); + } +}