diff --git a/include/villas/fpga/card.h b/include/villas/fpga/card.h index 54e55e0da..3937aae48 100644 --- a/include/villas/fpga/card.h +++ b/include/villas/fpga/card.h @@ -7,7 +7,9 @@ * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ip.h b/include/villas/fpga/ip.h index 5b7593136..90f434331 100644 --- a/include/villas/fpga/ip.h +++ b/include/villas/fpga/ip.h @@ -7,7 +7,9 @@ * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/dft.h b/include/villas/fpga/ips/dft.h index f8ac4910d..ca7d16b0f 100644 --- a/include/villas/fpga/ips/dft.h +++ b/include/villas/fpga/ips/dft.h @@ -5,7 +5,9 @@ * @copyright 2017, Steffen Vogel **********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/dma.h b/include/villas/fpga/ips/dma.h index d42d4d885..db05a9595 100644 --- a/include/villas/fpga/ips/dma.h +++ b/include/villas/fpga/ips/dma.h @@ -7,7 +7,9 @@ * @copyright 2017, Steffen Vogel **********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/fifo.h b/include/villas/fpga/ips/fifo.h index c7af8eb49..d685fd663 100644 --- a/include/villas/fpga/ips/fifo.h +++ b/include/villas/fpga/ips/fifo.h @@ -7,7 +7,9 @@ * @copyright 2017, Steffen Vogel **********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/intc.h b/include/villas/fpga/ips/intc.h index 4af79a068..b4898730b 100644 --- a/include/villas/fpga/ips/intc.h +++ b/include/villas/fpga/ips/intc.h @@ -4,7 +4,9 @@ * @copyright 2017, Steffen Vogel **********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/model.h b/include/villas/fpga/ips/model.h index 60725589f..aa191ea00 100644 --- a/include/villas/fpga/ips/model.h +++ b/include/villas/fpga/ips/model.h @@ -5,7 +5,9 @@ * @copyright 2017, Steffen Vogel *********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/rtds_axis.h b/include/villas/fpga/ips/rtds_axis.h index b81759e26..f48fd8390 100644 --- a/include/villas/fpga/ips/rtds_axis.h +++ b/include/villas/fpga/ips/rtds_axis.h @@ -5,7 +5,9 @@ * @copyright 2017, Steffen Vogel **********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/switch.h b/include/villas/fpga/ips/switch.h index 0d09cb7a2..1172ab9cb 100644 --- a/include/villas/fpga/ips/switch.h +++ b/include/villas/fpga/ips/switch.h @@ -7,7 +7,9 @@ * @copyright 2017, Steffen Vogel **********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/ips/timer.h b/include/villas/fpga/ips/timer.h index cf5e3779e..f1ae91ecb 100644 --- a/include/villas/fpga/ips/timer.h +++ b/include/villas/fpga/ips/timer.h @@ -7,7 +7,9 @@ * @copyright 2017, Steffen Vogel **********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASfpga + * @{ + */ #pragma once diff --git a/include/villas/fpga/vlnv.h b/include/villas/fpga/vlnv.h index fa77555d7..19bce9485 100644 --- a/include/villas/fpga/vlnv.h +++ b/include/villas/fpga/vlnv.h @@ -5,7 +5,9 @@ * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC *********************************************************************************/ -/** @addtogroup fpga VILLASfpga @{ */ +/** @addtogroup fpga VILLASILLASfpga + * @{ + */ #ifndef _FPGA_VLNV_H_ #define _FPGA_VLNV_H_ diff --git a/include/villas/hook.h b/include/villas/hook.h index cac1d91f0..81d0ca153 100644 --- a/include/villas/hook.h +++ b/include/villas/hook.h @@ -148,11 +148,12 @@ void * hook_storage(struct hook *h, int when, size_t len, ctor_cb_t ctor, dtor_c */ int hook_parse_list(struct list *list, config_setting_t *cfg); -/** Parse a single hook and append it to the list. +/** Parse a single hook. + * * A hook definition is composed of the hook name and optional parameters * seperated by a colon. * * Examples: * "print:stdout" */ -int hook_parse(config_setting_t *cfg, struct list *list); +int hook_parse(struct hook *h, config_setting_t *cfg); \ No newline at end of file diff --git a/include/villas/node.h b/include/villas/node.h index e14ad3cd9..e2bdafe33 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -45,11 +45,19 @@ struct node config_setting_t *cfg; /**< A pointer to the libconfig object which instantiated this node */ }; -/** Destroy node by freeing dynamically allocated memory. +int node_init(struct node *n, struct node_type *vt); + +/** Parse a single node and add it to the global configuration. * - * @see node_type::destroy + * @param cfg A libconfig object pointing to the node. + * @param nodes Add new nodes to this linked list. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. */ -int node_destroy(struct node *n); +int node_parse(struct node *n, config_setting_t *cfg); + +/** Validate node configuration. */ +int node_check(struct node *n); /** Start operation of a node. * @@ -63,6 +71,12 @@ int node_start(struct node *n); */ int node_stop(struct node *n); +/** Destroy node by freeing dynamically allocated memory. + * + * @see node_type::destroy + */ +int node_destroy(struct node *n); + /** Return a pointer to a string which should be used to print this node. * * @see node::_name‚ @@ -103,16 +117,4 @@ int node_write(struct node *n, struct sample *smps[], unsigned cnt); */ int node_parse_list(struct list *list, config_setting_t *cfg, struct list *all); -/** Parse a single node and add it to the global configuration. - * - * @param cfg A libconfig object pointing to the node. - * @param nodes Add new nodes to this linked list. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ -int node_parse(struct node *n, config_setting_t *cfg); - -/** Validate node configuration. */ -int node_check(struct node *n); - /** @} */ \ No newline at end of file diff --git a/include/villas/nodes/ngsi.h b/include/villas/nodes/ngsi.h index d518e0025..45c6be49d 100644 --- a/include/villas/nodes/ngsi.h +++ b/include/villas/nodes/ngsi.h @@ -25,7 +25,7 @@ #include "list.h" #include "config.h" #include "msg.h" -#include "cfg.h" +#include "super_node.h" #include "node.h" struct node; diff --git a/include/villas/pool.h b/include/villas/pool.h index 9112bdf30..f8fef235f 100644 --- a/include/villas/pool.h +++ b/include/villas/pool.h @@ -33,19 +33,32 @@ struct pool { #define INLINE static inline __attribute__((unused)) -/** Initiazlize a pool */ +/** Initiazlize a pool + * + * @param[inout] p The pool data structure. + * @param[in] cnt The total number of blocks which are reserverd by this pool. + * @param[in] blocksz The size in bytes per block. + * @param[in] mem The type of memory which should be used for this pool. + * @retval 0 The pool has been successfully initialized. + * @retval <>0 There was an error during the pool initialization. + */ int pool_init(struct pool *p, size_t cnt, size_t blocksz, const struct memtype *mem); /** Destroy and release memory used by pool. */ int pool_destroy(struct pool *p); -/** Pop cnt values from the stack an place them in the array blocks */ +/** Pop up to \p cnt values from the stack an place them in the array \p blocks. + * + * @return The number of blocks actually retrieved from the pool. + * This number can be smaller than the requested \p cnt blocks + * in case the pool currently holds less than \p cnt blocks. + */ INLINE ssize_t pool_get_many(struct pool *p, void *blocks[], size_t cnt) { return queue_pull_many(&p->queue, blocks, cnt); } -/** Push cnt values which are giving by the array values to the stack. */ +/** Push \p cnt values which are giving by the array values to the stack. */ INLINE ssize_t pool_put_many(struct pool *p, void *blocks[], size_t cnt) { return queue_push_many(&p->queue, blocks, cnt); diff --git a/include/villas/queue.h b/include/villas/queue.h index 07d94c7e2..b68f72c76 100644 --- a/include/villas/queue.h +++ b/include/villas/queue.h @@ -86,6 +86,17 @@ int queue_push(struct queue *q, void *ptr); int queue_pull(struct queue *q, void **ptr); +/** Enqueue up to \p cnt pointers of the \p ptr array into the queue. + * + * @return The number of pointers actually enqueued. + * This number can be smaller then \p cnt in case the queue is filled. + */ int queue_push_many(struct queue *q, void *ptr[], size_t cnt); +/** Dequeue up to \p cnt pointers from the queue and place them into the \p ptr array. + * + * @return The number of pointers actually dequeued. + * This number can be smaller than \p cnt in case the queue contained less than + * \p cnt elements. + */ int queue_pull_many(struct queue *q, void *ptr[], size_t cnt); \ No newline at end of file diff --git a/include/villas/webmsg_format.h b/include/villas/webmsg_format.h index c6b0e0d4d..19b600de6 100644 --- a/include/villas/webmsg_format.h +++ b/include/villas/webmsg_format.h @@ -7,11 +7,12 @@ * Unauthorized copying of this file, via any medium is strictly prohibited. *********************************************************************************/ -#ifndef _WEBMSG_FORMAT_H_ -#define _WEBMSG_FORMAT_H_ +#pragma once #include +#include "msg_format.h" + #ifdef __linux__ #define _BSD_SOURCE 1 #include @@ -39,16 +40,16 @@ #endif /** The total size in bytes of a message */ -#define WEBMSG_LEN(values) (sizeof(struct msg) + MSG_DATA_LEN(values)) +#define WEBMSG_LEN(values) (sizeof(struct webmsg) + MSG_DATA_LEN(values)) /** The length of \p values values in bytes. */ #define WEBMSG_DATA_LEN(values) (sizeof(float) * (values)) /** The offset to the first data value in a message. */ -#define WEBMSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct msg, data)) +#define WEBMSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct webmsg, data)) /** Initialize a message with default values */ -#define WEBMSG_INIT(len, seq) (struct msg) {\ +#define WEBMSG_INIT(len, seq) (struct webmsg) {\ .version = WEBMSG_VERSION, \ .type = WEBMSG_TYPE_DATA, \ .endian = WEBMSG_ENDIAN_HOST, \ @@ -97,6 +98,4 @@ struct webmsg float f; /**< Floating point values (note msg::endian) */ uint32_t i; /**< Integer values (note msg::endian) */ } data[]; -} __attribute__((packed)); - -#endif /* _WEBMSG_FORMAT_H_ */ +} __attribute__((packed)); \ No newline at end of file diff --git a/lib/fpga/card.c b/lib/fpga/card.c index 39b28bbae..bdfbdcccb 100644 --- a/lib/fpga/card.c +++ b/lib/fpga/card.c @@ -25,8 +25,7 @@ int fpga_card_init(struct fpga_card *c, struct pci *pci, struct vfio_container * fpga_card_check(c); - if (c->state == STATE_INITIALIZED) - return 0; + assert(c->state != STATE_DESTROYED); /* Search for FPGA card */ pdev = pci_lookup_device(pci, &c->filter); diff --git a/lib/hook.c b/lib/hook.c index dfa9d9ffb..da0c03be0 100644 --- a/lib/hook.c +++ b/lib/hook.c @@ -113,14 +113,21 @@ void * hook_storage(struct hook *h, int when, size_t len, ctor_cb_t ctor, dtor_c */ int hook_parse_list(struct list *list, config_setting_t *cfg) { + struct hook h; + switch (config_setting_type(cfg)) { case CONFIG_TYPE_STRING: - hook_parse(cfg, list); + hook_parse(&h, cfg); + list_push(list, memdup(&h, sizeof(h))); break; case CONFIG_TYPE_ARRAY: - for (int i = 0; i < config_setting_length(cfg); i++) - hook_parse(config_setting_get_elem(cfg, i), list); + for (int i = 0; i < config_setting_length(cfg); i++) { + config_setting_t *cfg_hook = config_setting_get_elem(cfg, i); + + hook_parse(&h, cfg_hook); + list_push(list, memdup(&h, sizeof(h))); + } break; default: @@ -130,27 +137,35 @@ int hook_parse_list(struct list *list, config_setting_t *cfg) return list_length(list); } -int hook_parse(config_setting_t *cfg, struct list *list) +int hook_parse(struct hook *h, config_setting_t *cfg) { - struct hook *hook; - struct plugin *plg; - + int ret; + const char *hookline; char *name, *param; - const char *hookline = config_setting_get_string(cfg); + struct plugin *p; + + hookline = config_setting_get_string(cfg); if (!hookline) cerror(cfg, "Invalid hook function"); name = strtok((char *) hookline, ":"); param = strtok(NULL, ""); - plg = plugin_lookup(PLUGIN_TYPE_HOOK, name); - if (!plg) + p = plugin_lookup(PLUGIN_TYPE_HOOK, name); + if (!p) cerror(cfg, "Unknown hook function '%s'", name); - hook = memdup(&plg->hook, sizeof(plg->hook)); - hook->parameter = param; + if (p->hook.type & HOOK_AUTO) + cerror(cfg, "Hook '%s' is built-in and can not be added manually.", name); + + hook_copy(&p->hook, h); + + h->parameter = param; - list_push(list, hook); + /* Parse hook arguments */ + ret = h->cb(h, HOOK_PARSE, NULL); + if (ret) + cerror(cfg, "Failed to parse arguments for hook '%s'", name); return 0; } \ No newline at end of file diff --git a/lib/hooks/convert.c b/lib/hooks/convert.c index 4b4a4a645..ec272e7e3 100644 --- a/lib/hooks/convert.c +++ b/lib/hooks/convert.c @@ -35,7 +35,7 @@ static int hook_convert(struct hook *h, int when, struct hook_info *k) case HOOK_READ: for (int i = 0; i < k->cnt; i++) { - for (int j = 0; j < k->smps[0]->length; j++) { + for (int j = 0; j < k->smps[i]->length; j++) { switch (private->mode) { case TO_FIXED: k->smps[i]->data[j].i = k->smps[i]->data[j].f * 1e3; break; case TO_FLOAT: k->smps[i]->data[j].f = k->smps[i]->data[j].i; break; @@ -57,7 +57,7 @@ static struct plugin p = { .priority = 99, .history = 0, .cb = hook_convert, - .type = HOOK_STORAGE | HOOK_DESTROY | HOOK_READ + .type = HOOK_STORAGE | HOOK_READ } }; diff --git a/lib/node.c b/lib/node.c index bd4fbe0be..407e39456 100644 --- a/lib/node.c +++ b/lib/node.c @@ -13,10 +13,15 @@ #include "config.h" #include "plugin.h" -int node_init(struct node *n) +int node_init(struct node *n, struct node_type *vt) { assert(n->state == STATE_DESTROYED); + + n->_vt = vt; + n->_vd = alloc(vt->size); + list_push(&vt->instances, n); + n->state = STATE_INITIALIZED; return 0; diff --git a/lib/node_type.c b/lib/node_type.c index 83fd068af..92f074cec 100644 --- a/lib/node_type.c +++ b/lib/node_type.c @@ -20,7 +20,7 @@ int node_type_start(struct node_type *vt, int argc, char *argv[], config_setting assert(vt->state != STATE_STARTED); - info("Initializing " YEL("%s") " node type", plugin_name(vt)); + info("Initializing " YEL("%s") " node type which is used by %zu nodes", plugin_name(vt), list_length(&vt->instances)); { INDENT ret = vt->init ? vt->init(argc, argv, cfg) : 0; } diff --git a/lib/nodes/socket.c b/lib/nodes/socket.c index 71fe94ea7..dcef254b8 100644 --- a/lib/nodes/socket.c +++ b/lib/nodes/socket.c @@ -31,7 +31,7 @@ #include "plugin.h" /* Forward declartions */ -static struct node_type vt; +static struct plugin p; /* Private static storage */ struct list interfaces; @@ -45,7 +45,10 @@ int socket_init(int argc, char * argv[], config_setting_t *cfg) list_init(&interfaces); /* Gather list of used network interfaces */ - list_foreach(struct node *n, &vt.instances) { + list_foreach(struct node *n, &p.node.instances) { + if (n->state != STATE_INITIALIZED) + continue; + struct socket *s = n->_vd; struct rtnl_link *link; @@ -114,11 +117,12 @@ char * socket_print(struct node *n) if (s->header == SOCKET_HEADER_DEFAULT) endian = "auto"; - else + else { switch (s->endian) { case MSG_ENDIAN_LITTLE: endian = "little"; break; case MSG_ENDIAN_BIG: endian = "big"; break; } + } char *local = socket_print_addr((struct sockaddr *) &s->local); char *remote = socket_print_addr((struct sockaddr *) &s->remote); diff --git a/lib/nodes/websocket.c b/lib/nodes/websocket.c index adf33a92d..ffdd96c9f 100644 --- a/lib/nodes/websocket.c +++ b/lib/nodes/websocket.c @@ -12,15 +12,15 @@ #include -#include "nodes/websocket.h" #include "super_node.h" #include "webmsg_format.h" #include "timing.h" #include "utils.h" -#include "msg.h" #include "config.h" #include "plugin.h" +#include "nodes/websocket.h" + /* Internal datastructures */ struct destination { char *uri; @@ -33,7 +33,7 @@ static int id = 0; /**< Highest assigned ID to websocket nodes. */ struct list connections; /**< List of active libwebsocket connections which receive samples from all nodes (catch all) */ /* Forward declarations */ -static struct node_type vt; +static struct plugin p; __attribute__((unused)) static int websocket_connection_init(struct websocket_connection *c) { @@ -143,7 +143,7 @@ int websocket_protocol_cb(struct lws *wsi, enum lws_callback_reasons reason, voi char *node = uri + 1; /* Search for node whose name matches the URI. */ - c->node = list_lookup(&vt.instances, node); + c->node = list_lookup(&p.node.instances, node); if (c->node == NULL) { warn("LWS: Closing Connection for non-existent node: %s", uri + 1); return -1; diff --git a/lib/sample.c b/lib/sample.c index 009988338..73005d05f 100644 --- a/lib/sample.c +++ b/lib/sample.c @@ -143,8 +143,10 @@ int sample_scan(const char *line, struct sample *s, int *fl) *fl = flags; if (flags & SAMPLE_OFFSET) { struct timespec off = time_from_double(offset); - s->ts.received = time_diff(&s->ts.origin, &off); + s->ts.received = time_add(&s->ts.origin, &off); } + else + s->ts.received = s->ts.origin; return s->length; } diff --git a/lib/web.c b/lib/web.c index 601f2c288..3c1ea68d1 100644 --- a/lib/web.c +++ b/lib/web.c @@ -125,6 +125,8 @@ static void logger(int level, const char *msg) { int web_init(struct web *w, struct api *a) { info("Initialize web sub-system"); + + lws_set_log_level((1 << LLL_COUNT) - 1, logger); w->api = a; @@ -154,11 +156,6 @@ int web_parse(struct web *w, config_setting_t *cfg) int web_start(struct web *w) { - /* update web root of mount point */ - mounts[0].origin = w->htdocs; - - lws_set_log_level((1 << LLL_COUNT) - 1, logger); - /* Start server */ struct lws_context_creation_info ctx_info = { .options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT, @@ -176,14 +173,21 @@ int web_start(struct web *w) .ssl_private_key_filepath = w->ssl_private_key }; - w->context = lws_create_context(&ctx_info); - if (w->context == NULL) - error("WebSocket: failed to initialize server"); - - w->vhost = lws_create_vhost(w->context, &vhost_info); - if (w->vhost == NULL) - error("WebSocket: failed to initialize server"); + info("Starting web sub-system"); + + { INDENT + /* update web root of mount point */ + mounts[0].origin = w->htdocs; + + w->context = lws_create_context(&ctx_info); + if (w->context == NULL) + error("WebSocket: failed to initialize server"); + w->vhost = lws_create_vhost(w->context, &vhost_info); + if (w->vhost == NULL) + error("WebSocket: failed to initialize server"); + } + w->state = STATE_STARTED; return 0;