diff options
author | Laurent Bercot <ska-skaware@skarnet.org> | 2021-03-28 01:50:36 +0000 |
---|---|---|
committer | Laurent Bercot <ska-skaware@skarnet.org> | 2021-03-28 01:50:36 +0000 |
commit | e2959c22c7309836d6f5dba2f0db7b293b860ad8 (patch) | |
tree | a26cefd2a36f6682e302bed8840642da0c6c64a8 /src/server/ep.c | |
parent | ba3bcbb86ea0177349bcd021559347248d6ab10a (diff) | |
download | s6-rc-e2959c22c7309836d6f5dba2f0db7b293b860ad8.tar.xz |
A few pieces of the future s6-rcd server
Diffstat (limited to 'src/server/ep.c')
-rw-r--r-- | src/server/ep.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/server/ep.c b/src/server/ep.c new file mode 100644 index 0000000..2fa0c0e --- /dev/null +++ b/src/server/ep.c @@ -0,0 +1,128 @@ +/* ISC license. */ + +#include <stdint.h> +#include <string.h> +#include <errno.h> + +#include <skalibs/strerr2.h> +#include <skalibs/genalloc.h> +#include <skalibs/gensetdyn.h> +#include <skalibs/avltree.h> + +#include <s6-rc/event.h> +#include "ep.h" + +typedef struct epelem_s epelem_t, *epelem_t_ref ; +struct epelem_s +{ + uint32_t owner ; + ep_func_t_ref f ; + void *aux ; +} ; +#define EPELEM_ZERO { .owner = 0, .f = 0, .aux = 0 } + +typedef struct eplist_s eplist_t, *eplist_t_ref ; +struct eplist_s +{ + char const *name ; + genalloc list ; /* epelem_t */ +} ; +#define EPLIST_ZERO { .name = 0, .list = GENALLOC_ZERO } + +typedef struct epset_s epset_t, *epset_t_ref ; +struct epset_s +{ + gensetdyn data ; /* eplist_t */ + avltree map ; +} ; +#define EPSET_ZERO { .data = GENSETDYN_ZERO, .map = AVLTREE_ZERO } + +static void *epset_dtok (uint32_t d, void *x) +{ + return (void *)&GENSETDYN_P(eplist_t, (gensetdyn *)x, d)->name ; +} + +static int epset_cmp (void const *a, void const *b, void *x) +{ + (void)x ; + return strcmp((char const *)a, (char const *)b) ; +} + +static epset_t ep[EVENTTYPE_PHAIL] = +{ + { .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[0].data) }, + { .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[1].data) }, + { .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[2].data) }, + { .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[3].data) }, + { .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[4].data) }, + { .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[5].data) }, + { .data = GENSETDYN_ZERO, .map = AVLTREE_INIT(8, 3, 8, &epset_dtok, &epset_cmp, &ep[6].data) }, +} ; + +static void eplist_free (void *p) +{ + eplist_t *x = p ; + genalloc_free(epelem_t, &x->list) ; +} + +void ep_free () +{ + for (s6rc_eventtype_t i = 0 ; i < S6RC_EVENTTYPE_PHAIL ; i++) + { + avltree_free(&ep[i].map) ; + gensetdyn_deepfree(&ep[i].data, &eplist_free) ; + avltree_init(&ep[i].map, 8, 3, 8, &epset_dtok, &epset_cmp, &ep[i].data) ; + } +} + +int ep_add (uint8_t type, char const *name, uint32_t owner, ep_func_t_ref f, void *aux) +{ + epelem_t ee = { .owner = owner, .f = f, .aux = aux } ; + uint32_t d ; + if (type >= S6RC_EVENTTYPE_PHAIL) return (errno = EINVAL, 0) ; + if (!avltree_search(&ep[type].map, name, &d)) + { + eplist_t newlist = { .name = name, .list = GENALLOC_ZERO } ; + if (!gensetdyn_new(&ep[type].data, &d)) return 0 ; + *GENSETDYN_P(eplist_t, &ep[type].data, d) = newlist ; + if (!avltree_insert(&ep[type].map, d)) + { + gensetdyn_delete(&ep[type].data, d) ; + return 0 ; + } + } + return genalloc_catb(epelem_t, &GENSETDYN_P(eplist_t, &ep[type].data, d)->list, &ee) ; +} + +void ep_delete (uint8_t type, char const *name, uint32_t owner, ep_func_t_ref f, void *aux) +{ + uint32_t d ; + if (type >= S6RC_EVENTTYPE_PHAIL) return ; + if (!avltree_search(&ep[type].map, name, &d)) return ; + + epelem_t ee = { .owner = owner, .f = f, .aux = aux } ; + genalloc *g = &GENSETDYN_P(eplist_t, &ep[type].data, d)->list ; + epelem_t *list = genalloc_s(epelem_t, g) ; + size_t n = genalloc_len(epelem_t, g) ; + size_t i = 0 ; + for (; i < n ; i++) if (list == ee) break ; + if (i < n) list[i] = list[--n] ; + if (!n) + { + genalloc_free(epelem_t, g) ; + avltree_delete(&ep[type].map, name) ; + gensetdyn_delete(eplist_t, &ep[type].data, d) ; + } +} + +void ep_run (s6rc_event_t const *ev) +{ + uint32_t d ; + if (!avltree_search(&ep[ev->type].map, ev->name, &d)) return ; + + genalloc *g = &GENSETDYN_P(eplist_t, &ep[ev->type].data, d)->list ; + epelem_t const *list = genalloc_s(epelem_t, g) ; + size_t n = genalloc_len(epelem_t, g) ; + for (size_t i = 0 ; i < n ; i++) + (*list[i].f)(ev, list[i].owner, list[i].aux) ; +} |