diff --git a/server/include/list.h b/server/include/list.h index f1611cc00..ce9f201be 100644 --- a/server/include/list.h +++ b/server/include/list.h @@ -67,8 +67,15 @@ void list_push(struct list *l, void *p); */ void * list_lookup(struct list *l, const char *name); +/** Return the first element of the list for which cmp returns zero */ void * list_search(struct list *l, cmp_cb_t cmp, void *ctx); +/** Returns the number of occurences for which cmp returns zero when called on all list elements. */ +int list_count(struct list *l, cmp_cb_t cmp, void *ctx); + +/** Return 0 if list contains pointer p */ +int list_contains(struct list *l, void *p); + /** Sort the list using the quicksort algorithm of libc */ void list_sort(struct list *l, cmp_cb_t cmp); diff --git a/server/include/node.h b/server/include/node.h index 8531c9f1f..3d324fa2b 100644 --- a/server/include/node.h +++ b/server/include/node.h @@ -56,6 +56,8 @@ extern struct list node_types; struct node_type { /** The unique name of this node. This must be allways the first member! */ const char *name; + /** A list of all existing nodes of this type. */ + struct list instances; enum { BSD_SOCKET, /**< BSD Socket API */ @@ -164,7 +166,6 @@ struct node const char *name; /**< A short identifier of the node, only used for configuration and logging */ char *_print; /**< A string used to print to screen. */ - int refcnt; /**< How many paths are sending / receiving from this node? */ int combine; /**< Number of messages to send / recv at once (scatter / gather) */ int affinity; /**< CPU Affinity of this node */ diff --git a/server/include/path.h b/server/include/path.h index c536481a5..c7b81d60d 100644 --- a/server/include/path.h +++ b/server/include/path.h @@ -37,6 +37,7 @@ struct path struct list destinations; /**< List of all outgoing nodes */ struct list hooks; /**< List of function pointers to hooks */ + int enabled; /**< Is this path enabled */ int tfd; /**< Timer file descriptor for fixed rate sending */ double rate; /**< Send messages with a fixed rate over this path */ diff --git a/server/src/cfg.c b/server/src/cfg.c index d8727234a..2966c5b25 100644 --- a/server/src/cfg.c +++ b/server/src/cfg.c @@ -103,7 +103,7 @@ int config_parse_path(config_setting_t *cfg, { config_setting_t *cfg_out, *cfg_hook; const char *in; - int enabled, reverse; + int reverse; struct path *p = path_create(); @@ -130,8 +130,8 @@ int config_parse_path(config_setting_t *cfg, /* Initialize hooks and their private data / parameters */ path_run_hook(p, HOOK_INIT); - if (!config_setting_lookup_bool(cfg, "enabled", &enabled)) - enabled = 1; + if (!config_setting_lookup_bool(cfg, "enabled", &p->enabled)) + p->enabled = 1; if (!config_setting_lookup_bool(cfg, "reverse", &reverse)) reverse = 0; if (!config_setting_lookup_float(cfg, "rate", &p->rate)) @@ -143,52 +143,31 @@ int config_parse_path(config_setting_t *cfg, p->cfg = cfg; - if (enabled) { - p->in->refcnt++; - p->in->_vt->refcnt++; + list_push(paths, p); - list_foreach(struct node *node, &p->destinations) { - node->refcnt++; - node->_vt->refcnt++; - } - - list_push(paths, p); + if (reverse) { + if (list_length(&p->destinations) > 1) + error("Can't reverse path with multiple destination nodes"); - if (reverse) { - if (list_length(&p->destinations) > 1) - error("Can't reverse path with multiple destination nodes"); + struct path *r = path_create(); - struct path *r = path_create(); - - /* Swap in/out */ - r->in = p->out; - r->out = p->in; + /* Swap in/out */ + r->in = p->out; + r->out = p->in; - list_push(&r->destinations, r->out); + list_push(&r->destinations, r->out); - /* Increment reference counters */ - r->in->refcnt++; - r->in->_vt->refcnt++; - r->out->refcnt++; - r->out->_vt->refcnt++; + if (cfg_hook) + config_parse_hooklist(cfg_hook, &r->hooks); - if (cfg_hook) - config_parse_hooklist(cfg_hook, &r->hooks); + /* Initialize hooks and their private data / parameters */ + path_run_hook(r, HOOK_INIT); - /* Initialize hooks and their private data / parameters */ - path_run_hook(r, HOOK_INIT); - - r->rate = p->rate; - r->poolsize = p->poolsize; - r->msgsize = p->msgsize; + r->rate = p->rate; + r->poolsize = p->poolsize; + r->msgsize = p->msgsize; - list_push(paths, r); - } - } - else { - warn("Path %s is not enabled", path_print(p)); - - path_destroy(p); + list_push(paths, r); } return 0; diff --git a/server/src/list.c b/server/src/list.c index e06bd4268..84fd4a252 100644 --- a/server/src/list.c +++ b/server/src/list.c @@ -72,6 +72,32 @@ void * list_lookup(struct list *l, const char *name) return list_search(l, cmp, (void *) name); } +int list_count(struct list *l, cmp_cb_t cmp, void *ctx) +{ + int c = 0; + + pthread_mutex_lock(&l->lock); + + void *e; + list_foreach(e, l) { + if (!cmp(e, ctx)) + c++; + } + + pthread_mutex_unlock(&l->lock); + + return c; +} + +int list_contains(struct list *l, void *p) +{ + int cmp(const void *a, const void *b) { + return a == b; + } + + return list_count(l, cmp, p); +} + void * list_search(struct list *l, cmp_cb_t cmp, void *ctx) { pthread_mutex_lock(&l->lock); diff --git a/server/src/node.c b/server/src/node.c index 714c8710c..8c360ebb0 100644 --- a/server/src/node.c +++ b/server/src/node.c @@ -36,10 +36,14 @@ struct list node_types = LIST_INIT(NULL); int node_init(int argc, char *argv[], struct settings *set) { INDENT list_foreach(const struct node_type *vt, &node_types) { - if (vt->refcnt) { + if (list_length(&vt->instances) > 0) { info("Initializing '%s' node type", vt->name); - vt->init(argc, argv, set); + + if (vt->init) + vt->init(argc, argv, set); } + else + warn("No node is using the '%s' type. Skipping...", vt->name); } return 0; @@ -49,7 +53,7 @@ int node_deinit() { INDENT /* De-initialize node types */ list_foreach(const struct node_type *vt, &node_types) { - if (vt->refcnt) { + if (list_length(&vt->instances) > 0) { info("De-initializing '%s' node type", vt->name); vt->deinit(); } @@ -60,12 +64,7 @@ int node_deinit() int node_start(struct node *n) { INDENT - if (!n->refcnt) { - warn("Node '%s' is unused. Skipping...", n->name); - return -1; - } - - debug(1, "Starting node '%s' of type '%s' (%s)", n->name, n->_vt->name, node_print(n)); + info("Starting node '%s' of type '%s' (%s)", n->name, n->_vt->name, node_print(n)); { INDENT return node_open(n); @@ -74,18 +73,11 @@ int node_start(struct node *n) int node_stop(struct node *n) { INDENT - int ret; - - if (!n->refcnt) /* Unused and not started. No reason to stop.. */ - return -1; - info("Stopping node '%s'", n->name); { INDENT - ret = node_close(n); + return node_close(n); } - - return ret; } char * node_print(struct node *n) @@ -115,6 +107,8 @@ struct node * node_create(struct node_type *vt) { struct node *n = alloc(sizeof(struct node)); + list_push(&vt->instances, n); + n->_vt = vt; return n; diff --git a/server/src/opal.c b/server/src/opal.c index a7e90a094..29c03ad77 100644 --- a/server/src/opal.c +++ b/server/src/opal.c @@ -17,9 +17,6 @@ /** Global OPAL specific settings */ static struct opal_global *og = NULL; -/** List of all opal nodes */ -static struct list opals; - int opal_init(int argc, char *argv[], struct settings *set) { INDENT int err; @@ -142,8 +139,6 @@ int opal_parse(config_setting_t *cfg, struct node *n) n->opal = o; n->cfg = cfg; - list_push(&opals, o); - return 0; } diff --git a/server/src/receive.c b/server/src/receive.c index 7ba8a33fd..26d96dddb 100644 --- a/server/src/receive.c +++ b/server/src/receive.c @@ -101,9 +101,6 @@ int main(int argc, char *argv[]) if (reverse) node_reverse(node); - node->refcnt++; - node->_vt->refcnt++; - node_init(argc-optind, argv+optind, &set); node_start(node); diff --git a/server/src/send.c b/server/src/send.c index 501087442..977484c65 100644 --- a/server/src/send.c +++ b/server/src/send.c @@ -101,9 +101,6 @@ int main(int argc, char *argv[]) if (reverse) node_reverse(node); - node->refcnt++; - node->_vt->refcnt++; - info("Initialize node types"); node_init(argc-optind, argv+optind, &set); diff --git a/server/src/server.c b/server/src/server.c index 16e136714..8b7d09719 100644 --- a/server/src/server.c +++ b/server/src/server.c @@ -180,12 +180,25 @@ int main(int argc, char *argv[]) node_init(argc, argv, &settings); info("Starting nodes"); - list_foreach(struct node *n, &nodes) - node_start(n); + list_foreach(struct node *n, &nodes) { + int used_by_path(struct path *p, struct node *n) { + return (p->in == n) || list_contains(&p->destinations, n); + } + + int refs = list_count(&paths, (cmp_cb_t) used_by_path, n); + if (refs) + node_start(n); + else + warn("Node '%s' is unused. Skipping...", n->name); + } info("Starting paths"); - list_foreach(struct path *p, &paths) - path_start(p); + list_foreach(struct path *p, &paths) { + if (p->enabled) + path_start(p); + else + warn("Path %s is disabled. Skipping...", path_print(p)); + } /* Run! */ if (settings.stats > 0) { diff --git a/server/src/socket.c b/server/src/socket.c index 45f5696b4..76f88de93 100644 --- a/server/src/socket.c +++ b/server/src/socket.c @@ -35,8 +35,6 @@ /** Linked list of interfaces */ extern struct list interfaces; -/** Linked list of all sockets nodes */ -static struct list sockets; int socket_init(int argc, char * argv[], struct settings *set) { INDENT @@ -47,7 +45,8 @@ int socket_init(int argc, char * argv[], struct settings *set) list_init(&interfaces, (dtor_cb_t) if_destroy); /* Gather list of used network interfaces */ - list_foreach(struct socket *s, &sockets) { + list_foreach(struct node *n, &vt.instances) { + struct socket *s = n->socket; struct rtnl_link *link; /* Determine outgoing interface */ @@ -317,8 +316,6 @@ int socket_parse(config_setting_t *cfg, struct node *n) n->socket = s; - list_push(&sockets, s); - return 0; } diff --git a/server/src/test.c b/server/src/test.c index a64098100..d70d3a2b0 100644 --- a/server/src/test.c +++ b/server/src/test.c @@ -96,9 +96,6 @@ int main(int argc, char *argv[]) if (!node) error("There's no node with the name '%s'", argv[3]); - node->refcnt++; - node->_vt->refcnt++; - node_init(argc-3, argv+3, &settings); node_start(node);