diff options
author | David Oberhollenzer <goliath@infraroot.at> | 2020-05-13 19:13:04 +0200 |
---|---|---|
committer | David Oberhollenzer <goliath@infraroot.at> | 2020-05-14 01:26:14 +0200 |
commit | dbe89195b258c1101b5dd37dfbf5f0d71c25e0fa (patch) | |
tree | 6a4192ebe460b8a64f739209bc0269933304da9b /initd/config.c | |
parent | f731537024c367368b728ed01c9232c3b1951589 (diff) |
initd: split configuration handling into "config.c"
This commit splits off only the handling of the service
configuration and handling of the run time state and adds
an abstraction layer in the form of functions that have to
be called to access the data.
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
Diffstat (limited to 'initd/config.c')
-rw-r--r-- | initd/config.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/initd/config.c b/initd/config.c new file mode 100644 index 0000000..7f9f25c --- /dev/null +++ b/initd/config.c @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: ISC */ +#include "init.h" + +/* service configurations */ +static service_list_t cfg; + +/* service run time data, sorted by target and topological order */ +static svc_run_data_t *rt_data = NULL; +static size_t rt_count = 0; + +/* maps a target to range in rt_data */ +static size_t queue_start[TGT_MAX]; +static size_t queue_count[TGT_MAX]; + +/* current state */ +static size_t queue_idx = 0; +static int target = TGT_BOOT; +static size_t singleshot = 0; + +int config_load(void) +{ + service_t *it; + size_t i, j; + + if (svcscan(SVCDIR, &cfg)) + return -1; + + /* allocate run time data */ + rt_count = 0; + + for (i = 0; i < TGT_MAX; ++i) { + for (it = cfg.targets[i]; it != NULL; it = it->next) + ++rt_count; + } + + rt_data = calloc(rt_count, sizeof(rt_data[0])); + if (rt_data == NULL) { + rt_count = 0; + del_svc_list(&cfg); + return -1; + } + + /* map runtime data to services */ + j = 0; + + for (i = 0; i < TGT_MAX; ++i) { + queue_start[i] = j; + + for (it = cfg.targets[i]; it != NULL; it = it->next) { + rt_data[j].svc = it; + rt_data[j].state = STATE_OFF; + rt_data[j].pid = -1; + ++j; + } + + queue_count[i] = j - queue_start[i]; + } + + /* initialize state */ + for (i = 0; i < queue_count[target]; ++i) + rt_data[queue_start[target] + i].state = STATE_QUEUED; + + return 0; +} + +svc_run_data_t *config_rt_data_by_pid(pid_t pid) +{ + size_t i; + + if (pid <= 1) + return NULL; + + for (i = 0; i < rt_count; ++i) { + if (rt_data[i].pid == pid) + return rt_data + i; + } + + return NULL; +} + +svc_run_data_t *config_dequeue(void) +{ + if (queue_idx >= queue_count[target]) + return NULL; + + return rt_data + queue_start[target] + queue_idx++; +} + +void config_set_target(int tgt) +{ + if (target == TGT_REBOOT || target == TGT_SHUTDOWN || target == tgt) + return; + + /* TODO: + - if there are services left in the queue of the current target: + - refuse unless the new target is shutdown/reboot? + - mark pending as "STATE_OFF" + - if the new target is reboot/shutdown + - enqueue the currently running services as "stop those"? + */ + + target = tgt; + queue_idx = 0; +} + +int config_get_current_target(void) +{ + return target; +} + +bool config_is_current_target_complete(void) +{ + return singleshot == 0 && queue_idx >= queue_count[target]; +} + +bool config_should_respawn(void) +{ + return target != TGT_REBOOT && target != TGT_SHUTDOWN; +} + +void config_singleshot_started(void) +{ + singleshot++; +} + +void config_singleshot_terminated(void) +{ + assert(singleshot > 0); + + singleshot--; +} |