From 0f1f51b5ad79f9b05afd508be76a03dbcafcb1c0 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Mon, 18 Dec 2017 17:50:02 +0100 Subject: [PATCH] Refactor, change from static array of svc_t to linked list Signed-off-by: Joachim Nilsson --- plugins/pidfile.c | 3 +- src/api.c | 9 +- src/cond-w.c | 3 +- src/inetd.c | 6 +- src/service.c | 6 +- src/svc.c | 225 +++++++++++++++++----------------------------- src/svc.h | 15 ++-- 7 files changed, 103 insertions(+), 164 deletions(-) diff --git a/plugins/pidfile.c b/plugins/pidfile.c index 971491a5..7c6827d3 100644 --- a/plugins/pidfile.c +++ b/plugins/pidfile.c @@ -95,14 +95,13 @@ static void pidfile_callback(void *arg, int fd, int events) static void pidfile_reconf(void *arg) { static char cond[MAX_COND_LEN]; - int pos; svc_t *svc; int restart = 0; do { restart = 0; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { mkcond(cond, sizeof(cond), svc->cmd); if (svc->state == SVC_RUNNING_STATE && !svc_is_changed(svc) && diff --git a/src/api.c b/src/api.c index c35e1000..617bad7b 100644 --- a/src/api.c +++ b/src/api.c @@ -225,6 +225,7 @@ static void send_svc(int sd, svc_t *svc) static void api_cb(uev_t *w, void *arg, int events) { int sd, lvl; + static svc_t *svc; struct init_request rq; sd = accept(w->fd, NULL, NULL); @@ -345,7 +346,13 @@ static void api_cb(uev_t *w, void *arg, int events) case INIT_CMD_SVC_ITER: _d("svc iter, first: %d", rq.runlevel); - send_svc(sd, svc_iterator(rq.runlevel)); + /* + * XXX: This severly limits the number of + * simultaneous client connections, but will + * have to do for now. + */ + svc = svc_iterator(rq.runlevel ? NULL : svc); + send_svc(sd, svc); goto leave; case INIT_CMD_SVC_QUERY: diff --git a/src/cond-w.c b/src/cond-w.c index c6aed182..758de5a3 100644 --- a/src/cond-w.c +++ b/src/cond-w.c @@ -88,11 +88,10 @@ static int svc_has_cond(svc_t *svc) static void cond_update(const char *name) { - int pos; svc_t *svc; _d("%s", name); - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (!svc_has_cond(svc) || !cond_affects(name, svc->cond)) continue; diff --git a/src/inetd.c b/src/inetd.c index e32fe19c..00a6face 100644 --- a/src/inetd.c +++ b/src/inetd.c @@ -225,11 +225,10 @@ static void socket_cb(uev_t *w, void *arg, int events) */ int inetd_check_loop(struct sockaddr *sa, socklen_t len, char *name) { - int pos; svc_t *svc; char pname[NI_MAXHOST]; - for (svc = svc_inetd_iterator(&pos, 1); svc; svc = svc_inetd_iterator(&pos, 0)) { + for (svc = svc_inetd_iterator(NULL); svc; svc = svc_inetd_iterator(svc)) { inetd_t *i = &svc->inetd; if (!i->builtin || i->type != SOCK_DGRAM) @@ -666,10 +665,9 @@ int inetd_filter_str(inetd_t *inetd, char *str, size_t len) svc_t *inetd_find_svc(char *path, char *service, char *proto) { - int pos; svc_t *svc; - for (svc = svc_inetd_iterator(&pos, 1); svc; svc = svc_inetd_iterator(&pos, 0)) { + for (svc = svc_inetd_iterator(NULL); svc; svc = svc_inetd_iterator(svc)) { if (strncmp(path, svc->cmd, strlen(svc->cmd))) continue; diff --git a/src/service.c b/src/service.c index dca11235..d8f03c8c 100644 --- a/src/service.c +++ b/src/service.c @@ -1023,10 +1023,9 @@ void service_step_all(int types) */ void service_runtask_clean(void) { - int pos; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (!svc_is_runtask(svc)) continue; @@ -1053,10 +1052,9 @@ void service_runtask_clean(void) */ int service_runtask_completed(int skip) { - int pos; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (!svc_is_runtask(svc)) continue; diff --git a/src/svc.c b/src/svc.c index 7d706ce7..e5bd5c64 100644 --- a/src/svc.c +++ b/src/svc.c @@ -27,6 +27,7 @@ #include #include #include +#include /* BSD sys/queue.h API */ #include "finit.h" #include "svc.h" @@ -35,21 +36,7 @@ /* Each svc_t needs a unique job# */ static int jobcounter = 1; -static svc_t *svc_list = NULL; - -static svc_t *__connect_shm(void) -{ - if (svc_list) - return svc_list; - - svc_list = calloc(MAX_NUM_SVC, sizeof(svc_t)); - if (!svc_list) { - warn("Failed allocating static list of services, error %d", errno); - abort(); - } - - return svc_list; -} +static TAILQ_HEAD(head, svc) svc_list = TAILQ_HEAD_INITIALIZER(svc_list); /** * svc_new - Create a new service @@ -62,11 +49,12 @@ static svc_t *__connect_shm(void) */ svc_t *svc_new(char *cmd, int id, int type) { - int i, pos, job = -1; - svc_t *svc, *list = __connect_shm(); + int job = -1; + char *desc; + svc_t *svc; /* Find first job n:o if registering multiple instances */ - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (!strcmp(svc->cmd, cmd)) { job = svc->job; break; @@ -75,32 +63,26 @@ svc_t *svc_new(char *cmd, int id, int type) if (job == -1) job = jobcounter++; - for (i = 0; i < MAX_NUM_SVC; i++) { - svc_t *svc = &list[i]; + svc = calloc(1, sizeof(*svc)); + if (!svc) + return NULL; - if (svc->type == SVC_TYPE_FREE) { - char *desc; + svc->type = type; + svc->job = job; + svc->id = id; + strlcpy(svc->cmd, cmd, sizeof(svc->cmd)); - memset(svc, 0, sizeof(*svc)); - svc->type = type; - svc->job = job; - svc->id = id; - strlcpy(svc->cmd, cmd, sizeof(svc->cmd)); + /* Default description, if missing */ + desc = rindex(cmd, '/'); + if (desc) + desc++; + else + desc = cmd; + strlcpy(svc->desc, desc, sizeof(svc->desc)); - /* Default description, if missing */ - desc = rindex(cmd, '/'); - if (desc) - desc++; - else - desc = cmd; - strlcpy(svc->desc, desc, sizeof(svc->desc)); + TAILQ_INSERT_TAIL(&svc_list, svc, link); - return svc; - } - } - - errno = ENOMEM; - return NULL; + return svc; } /** @@ -112,71 +94,45 @@ svc_t *svc_new(char *cmd, int id, int type) */ int svc_del(svc_t *svc) { - svc->type = SVC_TYPE_FREE; + TAILQ_REMOVE(&svc_list, svc, link); + memset(svc, 0, sizeof(*svc)); + free(svc); + return 0; } /** - * svc_iterator1 - Naive iterator over all registered services. - * @pos: Iterator variable, preserves state between calls - * @first: Get first &svc_t object, or next until end. + * svc_iterator - Naive iterator over all registered services. + * @iter: %NULL for first entry, use returned value for subsequent calls * * Returns: - * The first &svc_t when @first is set, otherwise the next &svc_t until - * the end when %NULL is returned. + * The first &svc_t when %NULL is given as argument, otherwise the next + * &svc_t until the end when %NULL is returned. */ -svc_t *svc_iterator1(int *pos, int first) +svc_t *svc_iterator(svc_t *iter) { - int i; - svc_t *list = __connect_shm(); - - if (first) - i = 0; - else - i = *(int *)pos; - - while (i < MAX_NUM_SVC) { - svc_t *svc = &list[i++]; - - if (svc->type != SVC_TYPE_FREE) { - *(int *)pos = i; - return svc; - } - } + if (!iter) + return TAILQ_FIRST(&svc_list); + if (iter && iter != TAILQ_END(&svc_list)) + return TAILQ_NEXT(iter, link); + return NULL; } -/** - * svc_iterator - Naive iterator over all registered services. - * @first: Get first &svc_t object, or next until end. - * - * Returns: - * The first &svc_t when @first is set, otherwise the next &svc_t until - * the end when %NULL is returned. - */ -svc_t *svc_iterator(int first) -{ - static int i; - - return svc_iterator1(&i, first); -} - - /** * svc_inetd_iterator - Naive iterator over all registered inetd services. - * @pos: Iterator variable, preserves state between calls - * @first: Get first &svc_t object, or next until end. + * @iter: %NULL for first entry, use returned value for subsequent calls * * Returns: - * The first inetd &svc_t when @first is set, otherwise the next - * inetd &svc_t until the end when %NULL is returned. + * The first inetd &svc_t when %NULL is given as argument, otherwise the + * next inetd &svc_t until the end when %NULL is returned. */ -svc_t *svc_inetd_iterator(int *pos, int first) +svc_t *svc_inetd_iterator(svc_t *iter) { svc_t *svc; - for (svc = svc_iterator1(pos, first); svc; svc = svc_iterator1(pos, 0)) { + for (svc = svc_iterator(iter); svc; svc = svc_iterator(svc)) { if (svc_is_inetd(svc)) return svc; } @@ -187,18 +143,18 @@ svc_t *svc_inetd_iterator(int *pos, int first) /** * svc_dynamic_iterator - Naive iterator over all registered dynamic services. - * @pos: Iterator variable, preserves state between calls - * @first: Get first &svc_t object, or next until end. + * @iter: %NULL for first entry, use returned value for subsequent calls * * Returns: - * The first dynamically loaded &svc_t when @first is set, otherwise the - * next dynamically loaded &svc_t until the end when %NULL is returned. + * The first dynamically loaded &svc_t when %NULL is given as argument, + * otherwise the next dynamically loaded &svc_t until the end when %NULL + * is returned. */ -svc_t *svc_dynamic_iterator(int *pos, int first) +svc_t *svc_dynamic_iterator(svc_t *iter) { svc_t *svc; - for (svc = svc_iterator1(pos, first); svc; svc = svc_iterator1(pos, 0)) { + for (svc = svc_iterator(iter); svc; svc = svc_iterator(svc)) { if (svc->mtime.tv_sec) return svc; } @@ -209,20 +165,19 @@ svc_t *svc_dynamic_iterator(int *pos, int first) /** * svc_named_iterator - Iterates over all instances of a service. - * @pos: Iterator variable, preserves state between calls - * @first: Get first &svc_t object, or next until end. - * @cmd: Service name to look for. + * @iter: %NULL for first entry, use returned value for subsequent calls + * @cmd: Service name to look for. * * Returns: - * The first matching &svc_t when @first is set, otherwise the next - * &svc_t instance with the same @cmd until the end when %NULL is + * The first matching &svc_t when %NULL is given as argument, otherwise + * the next &svc_t with the same @cmd name until the end when %NULL is * returned. */ -svc_t *svc_named_iterator(int *pos, int first, char *cmd) +svc_t *svc_named_iterator(svc_t *iter, char *cmd) { svc_t *svc; - for (svc = svc_iterator1(pos, first); svc; svc = svc_iterator1(pos, 0)) { + for (svc = svc_iterator(iter); svc; svc = svc_iterator(svc)) { char *name = basename(svc->cmd); if (!strncmp(name, cmd, strlen(name))) @@ -235,20 +190,19 @@ svc_t *svc_named_iterator(int *pos, int first, char *cmd) /** * svc_job_iterator - Iterates over all instances of a service. - * @pos: Iterator variable, preserves state between calls - * @first: Get first &svc_t object, or next until end. - * @job: Job to look for. + * @iter: %NULL for first entry, use returned value for subsequent calls + * @job: Job to look for. * * Returns: - * The first matching &svc_t when @first is set, otherwise the next - * &svc_t instance with the same @job until the end when %NULL is + * The first matching &svc_t when %NULL is given as argument, otherwise + * the next &svc_t with the same @job ID until the end when %NULL is * returned. */ -svc_t *svc_job_iterator(int *pos, int first, int job) +svc_t *svc_job_iterator(svc_t *iter, int job) { svc_t *svc; - for (svc = svc_iterator1(pos, first); svc; svc = svc_iterator1(pos, 0)) { + for (svc = svc_iterator(iter); svc; svc = svc_iterator(svc)) { if (svc->job == job) return svc; } @@ -263,13 +217,12 @@ svc_t *svc_job_iterator(int *pos, int first, int job) */ void svc_foreach(void (*cb)(svc_t *)) { - int pos; svc_t *svc; if (!cb) return; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) cb(svc); } @@ -280,13 +233,12 @@ void svc_foreach(void (*cb)(svc_t *)) */ void svc_foreach_dynamic(void (*cb)(svc_t *)) { - int pos; svc_t *svc; if (!cb) return; - for (svc = svc_dynamic_iterator(&pos, 1); svc; svc = svc_dynamic_iterator(&pos, 0)) + for (svc = svc_dynamic_iterator(NULL); svc; svc = svc_dynamic_iterator(svc)) cb(svc); } @@ -298,13 +250,12 @@ void svc_foreach_dynamic(void (*cb)(svc_t *)) */ void svc_foreach_type(int types, void (*cb)(svc_t *)) { - int pos; svc_t *svc; if (!cb) return; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (!(svc->type & types)) continue; @@ -322,10 +273,9 @@ void svc_foreach_type(int types, void (*cb)(svc_t *)) */ svc_t *svc_stop_completed(void) { - int pos; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (svc->state == SVC_STOPPING_STATE) return svc; } @@ -342,10 +292,9 @@ svc_t *svc_stop_completed(void) */ svc_t *svc_find(char *cmd, int id) { - int pos; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (svc->id == id && !strncmp(svc->cmd, cmd, strlen(svc->cmd))) return svc; } @@ -362,10 +311,9 @@ svc_t *svc_find(char *cmd, int id) */ svc_t *svc_find_by_pid(pid_t pid) { - int pos; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (svc->pid == pid) return svc; } @@ -383,10 +331,9 @@ svc_t *svc_find_by_pid(pid_t pid) */ svc_t *svc_find_by_jobid(int job, int id) { - int pos; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (svc->job == job && svc->id == id) return svc; } @@ -404,11 +351,10 @@ svc_t *svc_find_by_jobid(int job, int id) */ svc_t *svc_find_by_nameid(char *name, int id) { - int pos; char *ptr; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { ptr = strrchr(svc->cmd, '/'); if (ptr) ptr++; @@ -434,12 +380,11 @@ svc_t *svc_find_by_nameid(char *name, int id) */ void svc_mark_dynamic(void) { - int pos; - svc_t *svc = svc_dynamic_iterator(&pos, 1); + svc_t *svc = svc_dynamic_iterator(NULL); while (svc) { *((int *)&svc->dirty) = -1; - svc = svc_dynamic_iterator(&pos, 0); + svc = svc_dynamic_iterator(svc); } } @@ -473,15 +418,14 @@ void svc_check_dirty(svc_t *svc, struct timeval *mtime) */ void svc_clean_dynamic(void (*cb)(svc_t *)) { - int pos; - svc_t *svc = svc_dynamic_iterator(&pos, 1); + svc_t *svc = svc_dynamic_iterator(NULL); while (svc) { if (svc->dirty == -1 && cb) { cb(svc); svc_mark_clean(svc); } - svc = svc_dynamic_iterator(&pos, 0); + svc = svc_dynamic_iterator(svc); } } @@ -512,10 +456,9 @@ int svc_clean_bootstrap(svc_t *svc) */ void svc_prune_bootstrap(void) { - int pos; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (!svc->pid) svc_clean_bootstrap(svc); } @@ -547,10 +490,10 @@ int svc_enabled(svc_t *svc) /* Same base service, return unique ID */ int svc_next_id(char *cmd) { - int pos, id = 0; + int id = 0; svc_t *svc; - for (svc = svc_iterator1(&pos, 1); svc; svc = svc_iterator1(&pos, 0)) { + for (svc = svc_iterator(NULL); svc; svc = svc_iterator(svc)) { if (!strcmp(svc->cmd, cmd) && id < svc->id) id = svc->id; } @@ -560,12 +503,10 @@ int svc_next_id(char *cmd) int svc_is_unique(svc_t *svc) { - svc_t *list = __connect_shm(); - int i, unique = 1; - - for (i = 0; i < MAX_NUM_SVC; i++) { - svc_t *s = &list[i]; + svc_t *s; + int unique = 1; + for (s = svc_iterator(NULL); s; s = svc_iterator(svc)) { if (svc->type == SVC_TYPE_FREE) continue; @@ -603,16 +544,14 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun int job = atonum(token); if (!ptr) { - int pos; - - svc = svc_job_iterator(&pos, 1, job); + svc = svc_job_iterator(NULL, job); if (!svc && not_found) result += not_found(NULL, job); while (svc) { if (found) result += found(svc); - svc = svc_job_iterator(&pos, 0, job); + svc = svc_job_iterator(svc, job); } } else { *ptr++ = 0; @@ -627,16 +566,14 @@ int svc_parse_jobstr(char *str, size_t len, int (*found)(svc_t *), int (not_foun } } else { if (!ptr) { - int pos; - - svc = svc_named_iterator(&pos, 1, token); + svc = svc_named_iterator(NULL, token); if (!svc && not_found) result += not_found(token, id); while (svc) { if (found) result += found(svc); - svc = svc_named_iterator(&pos, 0, token); + svc = svc_named_iterator(svc, token); } } else { *ptr++ = 0; diff --git a/src/svc.h b/src/svc.h index 540f4442..43056d69 100644 --- a/src/svc.h +++ b/src/svc.h @@ -29,6 +29,7 @@ #include #include /* pid_t */ #include +#include /* BSD sys/queue.h API */ #include "inetd.h" #include "helpers.h" @@ -70,7 +71,6 @@ typedef enum { #define MAX_COND_LEN (MAX_ARG_LEN * 3) #define MAX_USER_LEN 16 #define MAX_NUM_FDS 64 /* Max number of I/O plugins */ -#define MAX_NUM_SVC 64 /* Enough? */ #define MAX_NUM_SVC_ARGS 32 /* @@ -80,6 +80,8 @@ typedef enum { * initctl service */ typedef struct svc { + TAILQ_ENTRY(svc) link; + /* Instance specifics */ int job, id; /* JOB:ID */ @@ -135,12 +137,11 @@ svc_t *svc_find_by_pid (pid_t pid); svc_t *svc_find_by_jobid (int job, int id); svc_t *svc_find_by_nameid (char *name, int id); -svc_t *svc_iterator (int first); -svc_t *svc_iterator1 (int *pos, int first); -svc_t *svc_inetd_iterator (int *pos, int first); -svc_t *svc_dynamic_iterator (int *pos, int first); -svc_t *svc_named_iterator (int *pos, int first, char *cmd); -svc_t *svc_job_iterator (int *pos, int first, int job); +svc_t *svc_iterator (svc_t *iter); +svc_t *svc_inetd_iterator (svc_t *iter); +svc_t *svc_dynamic_iterator (svc_t *iter); +svc_t *svc_named_iterator (svc_t *iter, char *cmd); +svc_t *svc_job_iterator (svc_t *iter, int job); void svc_foreach (void (*cb)(svc_t *)); void svc_foreach_dynamic (void (*cb)(svc_t *));