1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-09 00:00:00 +01:00

first bunch of global state object

This commit is contained in:
Steffen Vogel 2017-02-18 10:31:42 -05:00
parent 2b83fef2ce
commit bc634ebccc
7 changed files with 219 additions and 165 deletions

View file

@ -61,11 +61,3 @@
/** AXI Bus frequency for all components
* except RTDS AXI Stream bridge which runs at RTDS_HZ (100 Mhz) */
#define FPGA_AXI_HZ 125000000 // 125 MHz
/** Global configuration */
struct settings {
int priority; /**< Process priority (lower is better) */
int affinity; /**< Process affinity of the server and all created threads */
int debug; /**< Debug log level */
double stats; /**< Interval for path statistics. Set to 0 to disable themo disable them. */
};

View file

@ -15,37 +15,53 @@
#include <libconfig.h>
/* Forward declarations */
struct list;
struct settings;
#include "list.h"
#include "api.h"
#include "web.h"
#include "log.h"
/** Global configuration */
struct cfg {
int priority; /**< Process priority (lower is better) */
int affinity; /**< Process affinity of the server and all created threads */
double stats; /**< Interval for path statistics. Set to 0 to disable them. */
struct list nodes;
struct list paths;
struct list plugins;
struct log log;
struct api api;
struct web web;
config_t *cfg; /**< Pointer to configuration file */
json_t *json; /**< JSON representation of the same config. */
};
/* Compatibility with libconfig < 1.5 */
#if (LIBCONFIG_VER_MAJOR <= 1) && (LIBCONFIG_VER_MINOR < 5)
#define config_setting_lookup config_lookup_from
#endif
/** Simple wrapper around libconfig's config_init()
*
* This allows us to avoid an additional library dependency to libconfig
* for the excuctables. They only have to depend on libvillas.
*/
void cfg_init(config_t *cfg);
/** Inititalize configuration object before parsing the configuration. */
int cfg_init_pre(struct cfg *cfg);
/** Simple wrapper around libconfig's config_init() */
void cfg_destroy(config_t *cfg);
/** Initialize after parsing the configuration file. */
int cfg_init_post(struct cfg *cfg);
/** Parse config file and store settings in supplied struct settings.
int cfg_deinit(struct cfg *cfg);
/** Desctroy configuration object. */
int cfg_destroy(struct cfg *cfg);
/** Parse config file and store settings in supplied struct cfg.
*
* @param cfg A configuration object.
* @param filename The path to the configration file (relative or absolute)
* @param cfg A initialized libconfig object
* @param set The global configuration structure
* @param nodes A linked list of nodes which should be parsed
* @param paths A linked list of paths which should be parsed
* @retval 0 Success. Everything went well.
* @retval <0 Error. Something went wrong.
*/
int cfg_parse(const char *filename, config_t *cfg, struct settings *set,
struct list *nodes, struct list *paths);
int cfg_parse(struct cfg *cfg, const char *uri);
/** Parse the global section of a configuration file.
*
@ -54,7 +70,7 @@ int cfg_parse(const char *filename, config_t *cfg, struct settings *set,
* @retval 0 Success. Everything went well.
* @retval <0 Error. Something went wrong.
*/
int cfg_parse_global(config_setting_t *cfg, struct settings *set);
int cfg_parse_global(config_setting_t *cfg, struct cfg *set);
/** Parse a single path and add it to the global configuration.
*
@ -66,7 +82,7 @@ int cfg_parse_global(config_setting_t *cfg, struct settings *set);
* @retval <0 Error. Something went wrong.
*/
int cfg_parse_path(config_setting_t *cfg,
struct list *paths, struct list *nodes, struct settings *set);
struct list *paths, struct list *nodes, struct cfg *set);
/** Parse an array or single node and checks if they exist in the "nodes" section.
*

261
lib/cfg.c
View file

@ -17,134 +17,208 @@
#include "node.h"
#include "path.h"
#include "hooks.h"
#include "advio.h"
#include "web.h"
#include "log.h"
#include "api.h"
#include "plugin.h"
void cfg_init(config_t *cfg)
#include "kernel/rt.h"
int cfg_init_pre(struct cfg *cfg)
{
config_init(cfg);
}
void cfg_destroy(config_t *cfg)
{
config_destroy(cfg);
}
int cfg_parse(const char *filename, config_t *cfg, struct settings *set,
struct list *nodes, struct list *paths)
{
int ret = CONFIG_FALSE;
char *filename_cpy, *include_dir;
config_init(cfg);
filename_cpy = strdup(filename);
include_dir = dirname(filename_cpy);
/* Setup libconfig */
config_set_auto_convert(cfg, 1);
config_set_include_dir(cfg, include_dir);
free(filename_cpy);
config_init(cfg->cfg);
if (strcmp("-", filename) == 0)
ret = config_read(cfg, stdin);
else if (access(filename, F_OK) != -1)
ret = config_read_file(cfg, filename);
else
error("Invalid configuration file name: %s", filename);
info("Inititliaze logging sub-system");
log_init(&cfg->log);
if (ret != CONFIG_TRUE) {
error("Failed to parse configuration: %s in %s:%d",
config_error_text(cfg),
config_error_file(cfg) ? config_error_file(cfg) : filename,
config_error_line(cfg)
);
list_init(&cfg->nodes);
list_init(&cfg->paths);
list_init(&cfg->plugins);
return 0;
}
int cfg_init_post(struct cfg *cfg)
{
info("Initialize real-time sub-system");
rt_init(cfg);
info("Initialize hook sub-system");
hook_init(cfg);
info("Initialize API sub-system");
api_init(&cfg->api, cfg);
info("Initialize web sub-system");
web_init(&cfg->web, &cfg->api);
return 0;
}
int cfg_deinit(struct cfg *cfg)
{
info("De-initializing node types");
list_foreach(struct node_type *vt, &node_types) { INDENT
node_deinit(vt);
}
info("De-initializing web interface");
web_deinit(&cfg->web);
info("De-initialize API");
api_deinit(&cfg->api);
return 0;
}
config_setting_t *cfg_root = config_root_setting(cfg);
int cfg_destroy(struct cfg *cfg)
{
config_destroy(cfg->cfg);
web_destroy(&cfg->web);
log_destroy(&cfg->log);
api_destroy(&cfg->api);
list_destroy(&cfg->plugins, (dtor_cb_t) plugin_destroy, false);
list_destroy(&cfg->paths, (dtor_cb_t) path_destroy, true);
list_destroy(&cfg->nodes, (dtor_cb_t) node_destroy, true);
return 0;
}
int cfg_parse(struct cfg *cfg, const char *uri)
{
config_setting_t *cfg_root, *cfg_nodes, *cfg_paths, *cfg_plugins, *cfg_logging;
int ret = CONFIG_FALSE;
if (uri) {
/* Setup libconfig */
config_set_auto_convert(cfg->cfg, 1);
FILE *f;
AFILE *af;
/* Via stdin */
if (strcmp("-", uri) == 0) {
af = NULL;
f = stdin;
}
/* Local file? */
else if (access(uri, F_OK) != -1) {
/* Setup libconfig include path.
* This is only supported for local files */
char *uri_cpy = strdup(uri);
char *include_dir = dirname(uri_cpy);
config_set_include_dir(cfg->cfg, include_dir);
free(uri_cpy);
af = NULL;
f = fopen(uri, "r");
}
/* Use advio (libcurl) to fetch the config from a remote */
else {
af = afopen(uri, "r", ADVIO_MEM);
f = af ? af->file : NULL;
}
/* Check if file could be loaded / opened */
if (!f)
error("Failed to open configuration from: %s", uri);
/* Parse config */
ret = config_read(cfg->cfg, f);
if (ret != CONFIG_TRUE)
error("Failed to parse configuration: %s in %s:%d", config_error_text(cfg->cfg), uri, config_error_line(cfg->cfg));
/* Close configuration file */
if (af)
afclose(af);
else
fclose(f);
}
else
warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance.");
/* Parse global settings */
if (set) {
if (!cfg_root || !config_setting_is_group(cfg_root))
error("Missing global section in config file: %s", filename);
cfg_root = config_root_setting(cfg->cfg);
if (cfg_root) {
if (!config_setting_is_group(cfg_root))
warn("Missing global section in config file.");
cfg_parse_global(cfg_root, set);
cfg_parse_global(cfg_root, cfg);
}
/* Parse logging settings */
cfg_logging = config_setting_get_member(cfg_root, "logging");
if (cfg_logging) {
if (!config_setting_is_group(cfg_logging))
cerror(cfg_logging, "Setting 'logging' must be a group.");
log_parse(&cfg->log, cfg_logging);
}
/* Parse plugins */
cfg_plugins = config_setting_get_member(cfg_root, "plugins");
if (cfg_plugins) {
if (!config_setting_is_array(cfg_plugins))
cerror(cfg_plugins, "Setting 'plugins' must be a list of strings");
for (int i = 0; i < config_setting_length(cfg_plugins); i++) {
struct config_setting_t *cfg_plugin = config_setting_get_elem(cfg_plugins, i);
struct plugin plugin;
plugin_parse(&plugin, cfg_plugin);
}
}
/* Parse nodes */
if (nodes) {
config_setting_t *cfg_nodes = config_setting_get_member(cfg_root, "nodes");
if (!cfg_nodes || !config_setting_is_group(cfg_nodes))
error("Missing node section in config file: %s", filename);
cfg_nodes = config_setting_get_member(cfg_root, "nodes");
if (cfg_nodes) {
if (!config_setting_is_group(cfg_nodes))
warn("Setting 'nodes' must be a group with node name => group mappings.");
for (int i = 0; i < config_setting_length(cfg_nodes); i++) {
config_setting_t *cfg_node = config_setting_get_elem(cfg_nodes, i);
cfg_parse_node(cfg_node, nodes, set);
cfg_parse_node(cfg_node, &cfg->nodes, cfg);
}
}
/* Parse paths */
if (paths) {
config_setting_t *cfg_paths = config_setting_get_member(cfg_root, "paths");
if (!cfg_paths || !config_setting_is_list(cfg_paths))
error("Missing path section in config file: %s", filename);
cfg_paths = config_setting_get_member(cfg_root, "paths");
if (cfg_paths) {
if (!config_setting_is_list(cfg_paths))
warn("Setting 'paths' must be a list.");
for (int i = 0; i < config_setting_length(cfg_paths); i++) {
config_setting_t *cfg_path = config_setting_get_elem(cfg_paths, i);
cfg_parse_path(cfg_path, paths, nodes, set);
cfg_parse_path(cfg_path, &cfg->paths, &cfg->nodes, cfg);
}
}
return 0;
}
int cfg_parse_plugins(config_setting_t *cfg)
int cfg_parse_global(config_setting_t *cfg, struct cfg *set)
{
if (!config_setting_is_array(cfg))
cerror(cfg, "Setting 'plugins' must be a list of strings");
for (int i = 0; i < config_setting_length(cfg); i++) {
void *handle;
const char *path;
path = config_setting_get_string_elem(cfg, i);
if (!path)
cerror(cfg, "Setting 'plugins' must be a list of strings");
handle = dlopen(path, RTLD_NOW);
if (!handle)
error("Failed to load plugin %s", dlerror());
}
return 0;
}
int cfg_parse_global(config_setting_t *cfg, struct settings *set)
{
config_setting_t *cfg_plugins;
if (!config_setting_lookup_int(cfg, "affinity", &set->affinity))
set->affinity = 0;
if (!config_setting_lookup_int(cfg, "priority", &set->priority))
set->priority = 0;
if (!config_setting_lookup_int(cfg, "debug", &set->debug))
set->debug = V;
if (!config_setting_lookup_float(cfg, "stats", &set->stats))
set->stats = 0;
cfg_plugins = config_setting_get_member(cfg, "plugins");
if (cfg_plugins)
cfg_parse_plugins(cfg_plugins);
log_setlevel(set->debug, -1);
return 0;
}
int cfg_parse_path(config_setting_t *cfg,
struct list *paths, struct list *nodes, struct settings *set)
struct list *paths, struct list *nodes, struct cfg *set)
{
config_setting_t *cfg_out, *cfg_hook;
const char *in;
@ -203,11 +277,6 @@ int cfg_parse_path(config_setting_t *cfg,
if (!config_setting_lookup_float(cfg, "rate", &p->rate))
p->rate = 0; /* disabled */
if (!IS_POW2(p->queuelen)) {
p->queuelen = LOG2_CEIL(p->queuelen);
warn("Queue length should always be a power of 2. Adjusting to %d", p->queuelen);
}
p->cfg = cfg;
list_push(paths, p);
@ -276,9 +345,9 @@ int cfg_parse_nodelist(config_setting_t *cfg, struct list *list, struct list *al
return list_length(list);
}
int cfg_parse_node(config_setting_t *cfg, struct list *nodes, struct settings *set)
int cfg_parse_node(config_setting_t *cfg, struct list *nodes, struct cfg *set)
{
const char *type, *name;
const char *type;
int ret;
struct node *n;
@ -287,16 +356,14 @@ int cfg_parse_node(config_setting_t *cfg, struct list *nodes, struct settings *s
/* Required settings */
if (!config_setting_lookup_string(cfg, "type", &type))
cerror(cfg, "Missing node type");
name = config_setting_name(cfg);
vt = list_lookup(&node_types, type);
if (!vt)
cerror(cfg, "Invalid type for node '%s'", config_setting_name(cfg));
n = node_create(vt);
n->name = name;
n->name = config_setting_name(cfg);
n->cfg = cfg;
ret = node_parse(n, cfg);

View file

@ -26,7 +26,7 @@
int fpga_benchmarks(int argc, char *argv[], struct fpga *f);
int fpga_tests(int argc, char *argv[], struct fpga *f);
struct settings settings;
struct cfg settings;
void usage(char *name)
{

View file

@ -23,32 +23,21 @@
#include "opal.h"
#endif
struct list paths; /**< List of paths */
struct list nodes; /**< List of nodes */
static config_t config; /**< libconfig handle */
struct settings settings; /**< The global configuration */
struct cfg config;
static void quit()
{
info("Stopping paths");
list_foreach(struct path *p, &paths) { INDENT
list_foreach(struct path *p, &config.paths) { INDENT
path_stop(p);
}
info("Stopping nodes");
list_foreach(struct node *n, &nodes) { INDENT
list_foreach(struct node *n, &config.nodes) { INDENT
node_stop(n);
}
info("De-initializing node types");
list_foreach(struct node_type *vt, &node_types) { INDENT
node_deinit(vt);
}
/* Freeing dynamically allocated memory */
list_destroy(&paths, (dtor_cb_t) path_destroy, false);
list_destroy(&nodes, (dtor_cb_t) node_destroy, false);
cfg_deinit(&config);
cfg_destroy(&config);
info(GRN("Goodbye!"));
@ -103,9 +92,6 @@ int main(int argc, char *argv[])
#endif
usage(argv[0]);
char *configfile = (argc == 2) ? argv[1] : "opal-shmem.conf";
log_init();
info("This is VILLASnode %s (built on %s, %s)", BLD(YEL(VERSION)),
BLD(MAG(__DATE__)), BLD(MAG(__TIME__)));
@ -113,32 +99,26 @@ int main(int argc, char *argv[])
if (kernel_has_version(KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN))
error("Your kernel version is to old: required >= %u.%u", KERNEL_VERSION_MAJ, KERNEL_VERSION_MIN);
/* Initialize lists */
list_init(&paths);
list_init(&nodes);
info("Parsing configuration");
cfg_parse(configfile, &config, &settings, &nodes, &paths);
info("Initialize real-time system");
rt_init(settings.affinity, settings.priority);
info("Initialize signals");
signals_init();
info("Initialize hook sub-system");
hook_init(&nodes, &paths, &settings);
info("Parsing configuration");
cfg_init_pre(&config);
cfg_parse(&config, uri);
cfg_init_post(&config);
info("Initialize node types");
list_foreach(struct node_type *vt, &node_types) { INDENT
int refs = list_length(&vt->instances);
if (refs > 0)
node_init(vt, argc, argv, config_root_setting(&config));
node_init(vt, argc, argv, config_root_setting(config.cfg));
}
info("Starting nodes");
list_foreach(struct node *n, &nodes) { INDENT
int refs = list_count(&paths, (cmp_cb_t) path_uses_node, n);
list_foreach(struct node *n, &config.nodes) { INDENT
int refs = list_count(&config.paths, (cmp_cb_t) path_uses_node, n);
if (refs > 0)
node_start(n);
else
@ -146,7 +126,7 @@ int main(int argc, char *argv[])
}
info("Starting paths");
list_foreach(struct path *p, &paths) { INDENT
list_foreach(struct path *p, &config.paths) { INDENT
if (p->enabled) {
path_prepare(p);
path_start(p);
@ -154,9 +134,8 @@ int main(int argc, char *argv[])
else
warn("Path %s is disabled. Skipping...", path_name(p));
}
/* Run! */
if (settings.stats > 0) {
if (config.stats > 0)
hook_stats_header();
for (;;) {

View file

@ -27,7 +27,7 @@
#include "config.h"
static struct list nodes; /**< List of all nodes */
static struct settings settings; /**< The global configuration */
static struct cfg settings; /**< The global configuration */
static config_t config;
struct dir {

View file

@ -22,7 +22,7 @@
#include "timing.h"
#include "pool.h"
struct settings settings; /** <The global configuration */
struct cfg settings; /** <The global configuration */
struct list nodes;
static struct node *node;