/* * ssexec_compute_ns.c * * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> * * All rights reserved. * * This file is part of Obarun. It is subject to the license terms in * the LICENSE file found in the top-level directory of this * distribution. * This file may not be copied, modified, propagated, or distributed * except according to the terms contained in the LICENSE file./ */ #include <stdint.h> #include <oblibs/log.h> #include <oblibs/graph.h> #include <oblibs/types.h> #include <oblibs/sastr.h> #include <skalibs/genalloc.h> #include <66/svc.h> #include <66/config.h> #include <66/resolve.h> #include <66/ssexec.h> #include <66/state.h> #include <66/enum.h> #include <66/service.h> #include <66/sanitize.h> #include <s6/supervise.h>//s6_svstatus_t static pidservice_t pidservice_init(unsigned int len) { log_flow() ; pidservice_t pids = PIDSERVICE_ZERO ; if (len > SS_MAX_SERVICE) log_die(LOG_EXIT_SYS, "too many services") ; graph_array_init_single(pids.edge, len) ; return pids ; } static void pidservice_init_array(unsigned int *list, unsigned int listlen, pidservice_t *apids, graph_t *g, resolve_service_t *ares, unsigned int areslen, ssexec_t *info, uint8_t requiredby, uint32_t flag) { log_flow() ; int r = 0 ; unsigned int pos = 0 ; for (; pos < listlen ; pos++) { pidservice_t pids = pidservice_init(g->mlen) ; char *name = g->data.s + genalloc_s(graph_hash_t,&g->hash)[list[pos]].vertex ; pids.aresid = service_resolve_array_search(ares, areslen, name) ; if (pids.aresid < 0) log_dieu(LOG_EXIT_SYS,"find ares id of: ", name, " -- please make a bug reports") ; if (FLAGS_ISSET(flag, STATE_FLAGS_TOPROPAGATE)) { pids.nedge = graph_matrix_get_edge_g_sorted_list(pids.edge, g, name, requiredby, 1) ; if (pids.nedge < 0) log_dieu(LOG_EXIT_SYS,"get sorted ", requiredby ? "required by" : "dependency", " list of service: ", name) ; pids.nnotif = graph_matrix_get_edge_g_sorted_list(pids.notif, g, name, !requiredby, 1) ; if (pids.nnotif < 0) log_dieu(LOG_EXIT_SYS,"get sorted ", !requiredby ? "required by" : "dependency", " list of service: ", name) ; } pids.vertex = graph_hash_vertex_get_id(g, name) ; if (pids.vertex < 0) log_dieu(LOG_EXIT_SYS, "get vertex id -- please make a bug report") ; if (ares[pids.aresid].type != TYPE_CLASSIC) { ss_state_t ste = STATE_ZERO ; if (!state_read(&ste, &ares[pids.aresid])) log_dieusys(LOG_EXIT_SYS, "read state file of: ", name) ; if (ste.isup == STATE_FLAGS_TRUE) FLAGS_SET(pids.state, SVC_FLAGS_UP) ; else FLAGS_SET(pids.state, SVC_FLAGS_DOWN) ; } else { s6_svstatus_t status ; r = s6_svstatus_read(ares[pids.aresid].sa.s + ares[pids.aresid].live.scandir, &status) ; pid_t pid = !r ? 0 : status.pid ; if (pid > 0) { FLAGS_SET(pids.state, SVC_FLAGS_UP) ; } else FLAGS_SET(pids.state, SVC_FLAGS_DOWN) ; } apids[pos] = pids ; } } int svc_compute_ns(resolve_service_t *res, uint8_t what, ssexec_t *info, char const *updown, uint8_t opt_updown, uint8_t reloadmsg,char const *data, uint8_t propagate) { log_flow() ; int r ; uint8_t requiredby = 0 ; size_t pos = 0 ; graph_t graph = GRAPH_ZERO ; stralloc sa = STRALLOC_ZERO ; unsigned int napid = 0 ; unsigned int areslen = 0, list[SS_MAX_SERVICE], visit[SS_MAX_SERVICE] ; resolve_service_t ares[SS_MAX_SERVICE] ; uint32_t gflag = STATE_FLAGS_TOPROPAGATE|STATE_FLAGS_WANTUP ; if (!propagate) FLAGS_CLEAR(gflag, STATE_FLAGS_TOPROPAGATE) ; if (what) { requiredby = 1 ; FLAGS_SET(gflag, STATE_FLAGS_WANTDOWN) ; FLAGS_CLEAR(gflag, STATE_FLAGS_WANTUP) ; } if (res->dependencies.ncontents) { if (!sastr_clean_string(&sa, res->sa.s + res->dependencies.contents)) log_dieu(LOG_EXIT_SYS, "clean string") ; } else { log_warn("empty ns: ", res->sa.s + res->name) ; return 0 ; } /** build the graph of the ns */ service_graph_g(sa.s, sa.len, &graph, ares, &areslen, info, gflag) ; if (!graph.mlen) log_die(LOG_EXIT_USER, "services selection is not supervised -- initiate its first") ; graph_array_init_single(visit, SS_MAX_SERVICE) ; FOREACH_SASTR(&sa, pos) { char const *name = sa.s + pos ; int aresid = service_resolve_array_search(ares, areslen, name) ; if (aresid < 0) log_die(LOG_EXIT_USER, "service: ", name, " not available -- did you parsed it?") ; graph_compute_visit(name, visit, list, &graph, &napid, requiredby) ; } if (!what) sanitize_init(list, napid, &graph, ares, areslen, STATE_FLAGS_UNKNOWN) ; pidservice_t apids[napid] ; pidservice_init_array(list, napid, apids, &graph, ares, areslen, info, requiredby, gflag) ; r = svc_launch(apids, napid, what, &graph, ares, info, updown, opt_updown, reloadmsg, data, propagate) ; graph_free_all(&graph) ; service_resolve_array_free(ares, areslen) ; stralloc_free(&sa) ; return r ; }