From ee57014ec4749871cff7ada717cdb9e6d599a767 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 10 Jun 2014 18:47:25 +0000 Subject: [PATCH] rewrite of config parsing to use linked lists git-svn-id: https://zerberus.eonerc.rwth-aachen.de:8443/svn/s2ss/trunk@65 8ec27952-4edc-4aab-86aa-e87bb2611832 --- include/cfg.h | 41 +++++++-------- include/node.h | 8 +-- include/path.h | 3 ++ include/utils.h | 6 +++ src/cfg.c | 132 +++++++++++++++++++++++++----------------------- src/node.c | 8 +-- src/server.c | 39 ++++++-------- 7 files changed, 122 insertions(+), 115 deletions(-) diff --git a/include/cfg.h b/include/cfg.h index 5a67b879b..97937d060 100644 --- a/include/cfg.h +++ b/include/cfg.h @@ -23,58 +23,53 @@ struct settings { int affinity; /** Protocol version of UDP packages */ int protocol; - /// Number of parsed paths - int path_count; - /// Number of parsed nodes - int node_count; /** A libconfig object pointing to the root of the config file */ config_setting_t *cfg; - - /// Array of nodes - struct node *nodes; - /// Array of paths - struct path *paths; }; /** Parse configuration file and store settings in supplied struct settings. * - * @param c A libconfig object - * @param g The global configuration structure (also contains the config filename) + * @param cfg A libconfig object + * @param set The global configuration structure (also contains the config filename) + * @param nodes A pointer to a linked list of nodes which should be parsed + * @param paths A pointer to a linked list of paths which should be parsed * @return * - 0 on success * - otherwise an error occured */ -int config_parse(const char *filename, config_t *c, struct settings *g); +int config_parse(const char *filename, config_t *cfg, + struct settings *set, struct node **nodes, struct path **paths); /** Parse the global section of a configuration file. * - * @param c A libconfig object pointing to the root of the file - * @param g The global configuration file + * @param cfg A libconfig object pointing to the root of the file + * @param set The global configuration file * @return * - 0 on success * - otherwise an error occured */ -int config_parse_global(config_setting_t *c, struct settings *g); +int config_parse_global(config_setting_t *cfg, struct settings *set); /** Parse a single path and add it to the global configuration. - * - * @param c A libconfig object pointing to the path - * @param g The global configuration file + * + * @param cfg A libconfig object pointing to the path + * @param path A pointer to the new path + * @param nodes A linked list of all existing nodes * @return * - 0 on success * - otherwise an error occured */ -int config_parse_path(config_setting_t *c, struct settings *g); +int config_parse_path(config_setting_t *cfg, struct path *path, struct node *nodes); /** Parse a single node and add it to the global configuration. - * - * @param c A libconfig object pointing to the node - * @param g The global configuration file + * + * @param cfg A libconfig object pointing to the node + * @param node A pointer to the new node * @return * - 0 on success * - otherwise an error occured */ -int config_parse_node(config_setting_t *c, struct settings *g); +int config_parse_node(config_setting_t *cfg, struct node *node); #endif /* _CFG_H_ */ diff --git a/include/node.h b/include/node.h index 5886d41a0..089010198 100644 --- a/include/node.h +++ b/include/node.h @@ -61,6 +61,9 @@ struct node /** A pointer to the libconfig object which instantiated this node */ config_setting_t *cfg; + + /** Linked list pointer */ + struct node *next; }; /** Create a new node. @@ -109,10 +112,9 @@ enum node_type node_lookup_type(const char *str); /** Search list of nodes for a name. * * @param str The name of the wanted node - * @param nodes A pointer to the first list element - * @param len Length of the node list + * @param nodes A linked list of all nodes * @return A pointer to the node or NULL if not found */ -struct node* node_lookup_name(const char *str, struct node *nodes, int len); +struct node* node_lookup_name(const char *str, struct node *nodes); #endif /* _NODE_H_ */ diff --git a/include/path.h b/include/path.h index 4bc06fe28..723c67904 100644 --- a/include/path.h +++ b/include/path.h @@ -46,6 +46,9 @@ struct path pthread_t tid; /** A pointer to the libconfig object which instantiated this path */ config_setting_t *cfg; + + /** Linked list pointer */ + struct path *next; }; /** Setup a new path. diff --git a/include/utils.h b/include/utils.h index 7c5e56083..53d5b9e3f 100644 --- a/include/utils.h +++ b/include/utils.h @@ -69,6 +69,12 @@ void init_realtime(struct settings *g); */ int sockaddr_cmp(struct sockaddr *a, struct sockaddr *b); +/** Append an element to a single linked list */ +#define list_add(list, elm) do { \ + elm->next = list; \ + list = elm; \ + } while (0) + /** Check assertion and exit if failed. */ #define assert(exp) do { \ if (!(exp)) { \ diff --git a/src/cfg.c b/src/cfg.c index ca9983a7c..f1397f0b8 100644 --- a/src/cfg.c +++ b/src/cfg.c @@ -15,7 +15,8 @@ #include "path.h" #include "utils.h" -int config_parse(const char *filename, config_t *cfg, struct settings *g) +int config_parse(const char *filename, config_t *cfg, + struct settings *g, struct node **n, struct path **p) { if (!config_read_file(cfg, filename)) { error("Failed to parse configuration: %s in %s:%d", @@ -38,49 +39,60 @@ int config_parse(const char *filename, config_t *cfg, struct settings *g) if (!cfg_paths || !config_setting_is_list(cfg_paths)) error("Missing path section in config file: %s", filename); - /* Read global settings */ + /* Parse global settings */ config_parse_global(cfg_root, g); - int node_count = config_setting_length(cfg_nodes); - int path_count = config_setting_length(cfg_paths); - - g->nodes = malloc(node_count * sizeof(struct node)); - if (!g->nodes) - error("Failed to allocate memory for nodes"); - - g->paths = malloc(path_count * sizeof(struct path)); - if (!g->paths) - error("Failed to allocate memory for paths"); - - /* Parse nodes */ - for (int i=0; i < node_count; i++) { - config_parse_node(config_setting_get_elem(cfg_nodes, i), g); + for (int i = 0; i < config_setting_length(cfg_nodes); i++) { + config_setting_t *cfg_node = config_setting_get_elem(cfg_nodes, i); + + struct node *node = (struct node *) malloc(sizeof(struct node)); + if (!node) + error("Failed to allocate memory for node"); + + if (!config_parse_node(cfg_node, node)) { + free(node); + cerror(cfg_node, "Failed to parse node"); + } + + list_add(*n, node); } /* Parse paths */ - for (int i=0; i < path_count; i++) { - config_parse_path(config_setting_get_elem(cfg_paths, i), g); + for (int i = 0; i < config_setting_length(cfg_paths); i++) { + config_setting_t *cfg_path = config_setting_get_elem(cfg_paths, i); + + struct path *path = (struct path *) malloc(sizeof(struct path)); + if (!path) + error("Failed to allocate memory for path"); + + if (!config_parse_path(cfg_path, path, *n)) { + free(path); + cerror(cfg_path, "Failed to parse path"); + } + + list_add(*p, path); } return CONFIG_TRUE; } -int config_parse_global(config_setting_t *c, struct settings *g) +int config_parse_global(config_setting_t *cfg, struct settings *set) { - if (!config_setting_lookup_string(c, "name", &g->name)) - cerror(c, "Missing node name"); + if (!config_setting_lookup_string(cfg, "name", &set->name)) + cerror(cfg, "Missing node name"); - config_setting_lookup_int(c, "affinity", &g->affinity); - config_setting_lookup_int(c, "priority", &g->priority); - config_setting_lookup_int(c, "protocol", &g->protocol); + config_setting_lookup_int(cfg, "affinity", &set->affinity); + config_setting_lookup_int(cfg, "priority", &set->priority); + config_setting_lookup_int(cfg, "protocol", &set->protocol); - g->cfg = c; + set->cfg = cfg; return CONFIG_TRUE; } -int config_parse_path(config_setting_t *c, struct settings *g) +int config_parse_path(config_setting_t *cfg, + struct path *path, struct node *nodes) { struct node *in, *out; const char *in_str = NULL; @@ -89,45 +101,43 @@ int config_parse_path(config_setting_t *c, struct settings *g) int reverse = 0; /* Optional settings */ - config_setting_lookup_bool(c, "enabled", &enabled); - config_setting_lookup_bool(c, "reverse", &reverse); + config_setting_lookup_bool(cfg, "enabled", &enabled); + config_setting_lookup_bool(cfg, "reverse", &reverse); /* Required settings */ - if (!config_setting_lookup_string(c, "in", &in_str)) - cerror(c, "Missing input node for path"); + if (!config_setting_lookup_string(cfg, "in", &in_str)) + cerror(cfg, "Missing input node for path"); - if (!config_setting_lookup_string(c, "out", &out_str)) - cerror(c, "Missing output node for path"); + if (!config_setting_lookup_string(cfg, "out", &out_str)) + cerror(cfg, "Missing output node for path"); info("Loading path from '%s' to '%s'", in_str, out_str); - in = node_lookup_name(in_str, g->nodes, g->node_count); + in = node_lookup_name(in_str, nodes); if (!in) - cerror(c, "Invalid input node '%s'"); + cerror(cfg, "Invalid input node '%s'"); - out = node_lookup_name(out_str, g->nodes, g->node_count); + out = node_lookup_name(out_str, nodes); if (!out) - cerror(c, "Invalid output node '%s'", out_str); + cerror(cfg, "Invalid output node '%s'", out_str); if (enabled) { - if (path_create(&g->paths[g->path_count], in, out)) - cerror(c, "Failed to parse path"); + if (path_create(path, in, out)) + cerror(cfg, "Failed to parse path"); - g->cfg = c; - g->path_count++; + path->cfg = cfg; - if (reverse) { - if (path_create(&g->paths[g->path_count], out, in)) + // TODO + /*if (reverse) { + if (path_create(path, out, in)) cerror(c, "Failed to parse path"); - - g->path_count++; - } + }*/ } else warn(" Path is not enabled"); } -int config_parse_node(config_setting_t *c, struct settings *g) +int config_parse_node(config_setting_t *cfg, struct node *node) { const char *name = NULL; const char *type_str = NULL; @@ -138,35 +148,33 @@ int config_parse_node(config_setting_t *c, struct settings *g) enum node_type type; /* Required settings */ - name = config_setting_name(c); + name = config_setting_name(cfg); if (!name) - cerror(c, "Missing node name"); + cerror(cfg, "Missing node name"); - if (!config_setting_lookup_string(c, "type", &type_str)) - cerror(c, "Missing node type"); + if (!config_setting_lookup_string(cfg, "type", &type_str)) + cerror(cfg, "Missing node type"); - if (!config_setting_lookup_string(c, "remote", &remote_str)) - cerror(c, "Missing node remote address"); + if (!config_setting_lookup_string(cfg, "remote", &remote_str)) + cerror(cfg, "Missing node remote address"); - if (!config_setting_lookup_string(c, "local", &local_str)) - cerror(c, "Missing node local address"); + if (!config_setting_lookup_string(cfg, "local", &local_str)) + cerror(cfg, "Missing node local address"); type = node_lookup_type(type_str); if (type == NODE_INVALID) - cerror(c, "Invalid node type '%s'", type); - + cerror(cfg, "Invalid node type '%s'", type); info("Loading %s node '%s'", type_str, name); if (resolve_addr(local_str, &local, 0)) - cerror(c, "Failed to resolve local address '%s' of node '%s'", local_str, name); + cerror(cfg, "Failed to resolve local address '%s' of node '%s'", local_str, name); if (resolve_addr(remote_str, &remote, 0)) - cerror(c, "Failed to resolve remote address '%s' of node '%s'", remote_str, name); + cerror(cfg, "Failed to resolve remote address '%s' of node '%s'", remote_str, name); - if (node_create(&g->nodes[g->node_count], name, type, local, remote)) - cerror(c, "Failed to parse node"); + if (node_create(node, name, type, local, remote)) + cerror(cfg, "Failed to parse node"); - g->cfg = c; - g->node_count++; + node->cfg = cfg; } diff --git a/src/node.c b/src/node.c index 68c57e3c3..9253d9a50 100644 --- a/src/node.c +++ b/src/node.c @@ -85,11 +85,11 @@ enum node_type node_lookup_type(const char *str) return NODE_INVALID; } -struct node* node_lookup_name(const char *str, struct node *nodes, int len) +struct node* node_lookup_name(const char *str, struct node *nodes) { - for (int i = 0; i < len; i++) { - if (!strcmp(str, nodes[i].name)) { - return &nodes[i]; + for (struct node *n = nodes; n; n = n->next) { + if (!strcmp(str, n->name)) { + return n; } } diff --git a/src/server.c b/src/server.c index 322c8e871..ffe17581b 100644 --- a/src/server.c +++ b/src/server.c @@ -20,6 +20,12 @@ #include "path.h" #include "node.h" +/** Linked list of nodes */ +static struct node *nodes; + +/** Linked list of paths */ +static struct path *paths; + /** Default settings */ static struct settings settings = { .priority = 0, @@ -32,9 +38,7 @@ static config_t config; static void start() { /* Connect and bind nodes to their sockets, set socket options */ - for (int i = 0; i < settings.node_count; i++) { - struct node *n = &settings.nodes[i]; - + for (struct node *n = nodes; n; n = n->next) { node_connect(n); debug(1, " We listen for node '%s' at %s:%u", n->name, inet_ntoa(n->local.sin_addr), ntohs(n->local.sin_port)); @@ -42,9 +46,7 @@ static void start() } /* Start on thread per path for asynchronous processing */ - for (int i = 0; i < settings.path_count; i++) { - struct path *p = &settings.paths[i]; - + for (struct path *p = paths; p; p = p->next) { path_start(p); info("Starting path: %12s => %s => %-12s", p->in->name, settings.name, p->out->name); @@ -54,9 +56,7 @@ static void start() static void stop() { /* Join all threads and print statistics */ - for (int i = 0; i < settings.path_count; i++) { - struct path *p = &settings.paths[i]; - + for (struct path *p = paths; p; p = p->next) { path_stop(p); info("Stopping path: %12s => %s => %-12s", p->in->name, settings.name, p->out->name); @@ -66,9 +66,7 @@ static void stop() } /* Close all sockets we listing on */ - for (int i = 0; i < settings.node_count; i++) { - struct node *n = &settings.nodes[i]; - + for (struct node *n = nodes; n; n = n->next) { node_disconnect(n); } } @@ -77,8 +75,8 @@ static void quit() { stop(); - free(settings.paths); - free(settings.nodes); + // TODO: free nodes and paths + config_destroy(&config); _exit(EXIT_SUCCESS); @@ -111,24 +109,19 @@ int main(int argc, char *argv[]) /* Parse configuration file */ config_init(&config); - config_parse(argv[1], &config, &settings); + config_parse(argv[1], &config, &settings, &nodes, &paths); - if (!settings.path_count) + if (!paths) error("No paths found. Terminating..."); - else - info("Parsed %u nodes and %u paths", settings.node_count, settings.path_count); /* Setup various realtime related things */ init_realtime(&settings); - /* Connect all nodes to their sockets and start one thread per path */ + /* Connect all nodes and start one thread per path */ start(); /* Main thread is sleeping */ - while (1) pause(); - - /* Stop and free ressources */ - quit(); + pause(); return 0; }