diff --git a/include/hooks.h b/include/hooks.h index c10198340..79fca72d4 100644 --- a/include/hooks.h +++ b/include/hooks.h @@ -88,6 +88,9 @@ struct hook { hook_cb_t cb; /**< The hook callback function as a function pointer. */ }; +/** Save references to global nodes, paths and settings */ +void hook_init(struct list *nodes, struct list *paths, struct settings *set); + /** Sort hook list according to the their priority. See hook::priority. */ int hooks_sort_priority(const void *a, const void *b); diff --git a/include/node.h b/include/node.h index 02ca158e5..324707930 100644 --- a/include/node.h +++ b/include/node.h @@ -33,7 +33,6 @@ __attribute__((constructor)) static void __register() { \ list_push(&node_types, vt); \ } -extern struct list nodes; /**< List of all nodes */ extern struct list node_types; /**< Vtable for virtual node sub types */ /* Forward declarations */ diff --git a/lib/hooks.c b/lib/hooks.c index 83861f4ef..432812f26 100644 --- a/lib/hooks.c +++ b/lib/hooks.c @@ -25,6 +25,18 @@ struct list hooks; +/* Those references can be used inside the hook callbacks after initializing them with hook_init() */ +static struct list *hook_nodes = NULL; +static struct list *hook_paths = NULL; +static struct settings *hook_settings = NULL; + +void hook_init(struct list *nodes, struct list *paths, struct settings *set) +{ + hook_nodes = nodes; + hook_paths = paths; + hook_settings = set; +} + int hooks_sort_priority(const void *a, const void *b) { struct hook *ha = (struct hook *) a; struct hook *hb = (struct hook *) b; @@ -448,6 +460,9 @@ void hook_stats_header() line(); } +/** @todo Come up with a better solution for this ugly workaround */ +struct list *hook_nodes = NULL; + REGISTER_HOOK("stats_send", 99, hook_stats_send, HOOK_PRIVATE | HOOK_PERIODIC) int hook_stats_send(struct path *p, struct hook *h, int when) { @@ -462,10 +477,13 @@ int hook_stats_send(struct path *p, struct hook *h, int when) if (!h->parameter) error("Missing parameter for hook 'stats_send'"); + if (!hook_nodes) + error("stats_send() hook has no reference to node list"); + x = h->private = alloc(sizeof(struct private)); x->msg = msg_create(9); - x->dest = list_lookup(&nodes, h->parameter); + x->dest = list_lookup(hook_nodes, h->parameter); if (!x->dest) error("Invalid destination node '%s' for hook 'stats_send'", h->parameter); break; @@ -481,10 +499,10 @@ int hook_stats_send(struct path *p, struct hook *h, int when) x->msg->data[2].f = p->invalid; x->msg->data[3].f = p->skipped; x->msg->data[4].f = p->dropped; - - x->msg->data[5].f = p->hist.owd.last, - x->msg->data[6].f = p->hist.gap_msg.last; - x->msg->data[7].f = p->hist.gap_recv.last; + x->msg->data[5].f = p->overrun; + x->msg->data[6].f = p->hist.owd.last, + x->msg->data[7].f = 1.0 / p->hist.gap_msg.last; + x->msg->data[8].f = 1.0 / p->hist.gap_recv.last; node_write_single(x->dest, x->msg); /* Send single message with statistics to destination node */ break; diff --git a/lib/node.c b/lib/node.c index e58e73761..bbcabe54d 100644 --- a/lib/node.c +++ b/lib/node.c @@ -12,7 +12,6 @@ #include "cfg.h" #include "utils.h" -struct list nodes = LIST_INIT((dtor_cb_t) node_destroy); /**< List of all nodes */ struct list node_types = LIST_INIT(NULL); /**< Vtable for virtual node sub types */ int node_parse(struct node *n, config_setting_t *cfg) @@ -160,7 +159,6 @@ struct node * node_create(struct node_type *vt) { struct node *n = alloc(sizeof(struct node)); - list_push(&nodes, n); list_push(&vt->instances, n); n->_vt = vt; @@ -179,7 +177,6 @@ void node_destroy(struct node *n) if (n->_vt->destroy) n->_vt->destroy(n); - list_remove(&nodes, n); list_remove(&n->_vt->instances, n); free(n->_vd); diff --git a/src/pipe.c b/src/pipe.c index 5191de01f..f432a873a 100644 --- a/src/pipe.c +++ b/src/pipe.c @@ -24,11 +24,9 @@ #include "timing.h" #include "pool.h" -/** Linked list of nodes */ -struct list nodes = LIST_INIT((dtor_cb_t) node_destroy); -/** The global configuration */ -struct settings settings; +struct list nodes; /**< List of all nodes */ +struct settings settings; /**< The global configuration */ struct pool recv_pool, send_pool; pthread_t recv_thread, send_thread; @@ -38,6 +36,9 @@ int reverse; static void quit(int signal, siginfo_t *sinfo, void *ctx) { + pthread_cancel(recv_thread); + pthread_cancel(send_thread); + pthread_join(recv_thread, NULL); pthread_join(send_thread, NULL); @@ -146,6 +147,9 @@ int main(int argc, char *argv[]) /* Initialize log, configuration.. */ config_t config; + + /* Create lists */ + list_init(&nodes, (dtor_cb_t) node_destroy); log_init(); config_init(&config); @@ -157,6 +161,7 @@ int main(int argc, char *argv[]) error("Node '%s' does not exist!", argv[2]); node_init(node->_vt, argc-optind, argv+optind, config_root_setting(&config)); + pool_create(&recv_pool, node->vectorize, sizeof(struct msg)); pool_create(&send_pool, node->vectorize, sizeof(struct msg)); diff --git a/src/server.c b/src/server.c index ed9fe87a8..fec7ecf19 100644 --- a/src/server.c +++ b/src/server.c @@ -26,6 +26,8 @@ #endif struct list paths; /**< List of paths */ +struct list nodes; /**< List of nodes */ + struct settings settings; /**< The global configuration */ static config_t config; /**< libconfig handle */ @@ -57,7 +59,7 @@ static void quit() } static void realtime_init() -{ +{ INDENT if (check_kernel_cmdline()) warn("You should reserve some cores for the server (see 'isolcpus')"); if (check_kernel_rt()) @@ -89,7 +91,7 @@ static void realtime_init() /* Setup exit handler */ static void signals_init() -{ +{ INDENT struct sigaction sa_quit = { .sa_flags = SA_SIGINFO, .sa_sigaction = quit @@ -141,22 +143,22 @@ int main(int argc, char *argv[]) /* Initialize lists */ list_init(&paths, (dtor_cb_t) path_destroy); - - info("Initialize real-time system"); - { INDENT - realtime_init(); - } - - info("Initialize signals"); - { INDENT - signals_init(); - } + list_init(&nodes, (dtor_cb_t) node_destroy); info("Parsing configuration"); { INDENT config_init(&config); config_parse(configfile, &config, &settings, &nodes, &paths); } + + info("Initialize real-time system"); + realtime_init(); + + info("Initialize signals"); + signals_init(); + + info("Initialize hook sub-system"); + hook_init(&nodes, &paths, &settings); info("Initialize node types"); list_foreach(struct node_type *vt, &node_types) { INDENT @@ -171,6 +173,9 @@ int main(int argc, char *argv[]) else warn("No path is using the node %s. Skipping...", node_name(n)); } + + /** @todo This is a ugly workaround to get a reference to the node list inside the stats_send() hook */ + extern struct list *hook_nodes = &nodes; info("Starting paths"); list_foreach(struct path *p, &paths) { INDENT diff --git a/src/test.c b/src/test.c index 771f3ac50..5bec48416 100644 --- a/src/test.c +++ b/src/test.c @@ -23,6 +23,7 @@ #include "pool.h" struct settings settings; /** _vt); + + list_destroy(&nodes); config_destroy(&config); return 0;