diff --git a/include/villas/node.h b/include/villas/node.h index f2491e43d..5332fa938 100644 --- a/include/villas/node.h +++ b/include/villas/node.h @@ -14,17 +14,11 @@ #include #include +#include "node_type.h" #include "sample.h" #include "list.h" #include "queue.h" -extern struct list node_types; /**< Vtable for virtual node sub types */ - -/* Forward declarations */ -struct node_type; -struct settings; -typedef struct config_setting_t config_setting_t; - /** The data structure for a node. * * Every entity which exchanges messages is represented by a node. @@ -57,135 +51,6 @@ struct node config_setting_t *cfg; /**< A pointer to the libconfig object which instantiated this node */ }; -/** C++ like vtable construct for node_types */ -struct node_type { - const char *name; /**< The unique name of this node. This must be allways the first member! */ - const char *description; /**< A short description of this node type. Will be shown in help text. */ - int vectorize; /**< Maximal vector length supported by this node type. Zero is unlimited. */ - - struct list instances; /**< A list of all existing nodes of this type. */ - size_t size; /**< Size of private data bock. @see node::_vd */ - - enum node_type_state { - NODE_TYPE_UNINITIALIZED = 0, - NODE_TYPE_INITIALIZED - } state; - - /** Global initialization per node type. - * - * This callback is invoked once per node-type. - * - * @param argc Number of arguments passed to the server executable (see main()). - * @param argv Array of arguments passed to the server executable (see main()). - * @param cfg Root libconfig object of global configuration file. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*init)(int argc, char * argv[], config_setting_t *cfg); - - /** Global de-initialization per node type. - * - * This callback is invoked once per node-type. - * - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*deinit)(); - - /** Allocate memory for an instance of this type. - * - * @return A pointer to the node-type specific private data. - */ - void * (*create)(); - - /** Free memory of an instance of this type. - * - * @param n A pointer to the node object. - */ - int (*destroy)(struct node *n); - - /** Parse node connection details.‚ - * - * @param n A pointer to the node object. - * @param cfg A libconfig object pointing to the node. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*parse)(struct node *n, config_setting_t *cfg); - - /** Returns a string with a textual represenation of this node. - * - * @param n A pointer to the node object. - * @return A pointer to a dynamically allocated string. Must be freed(). - */ - char * (*print)(struct node *n); - - /** Opens the connection to this node. - * - * @param n A pointer to the node object. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*open) (struct node *n); - - /** Close the connection to this node. - * - * @param n A pointer to the node object. - * @retval 0 Success. Everything went well. - * @retval <0 Error. Something went wrong. - */ - int (*close)(struct node *n); - - /** Receive multiple messages at once. - * - * Messages are received with a single recvmsg() syscall by - * using gathering techniques (struct iovec). - * The messages will be stored in a circular buffer / array @p m. - * Indexes used to address @p m will wrap around after len messages. - * Some node types might only support to receive one message at a time. - * - * @param n A pointer to the node object. - * @param smps An array of pointers to memory blocks where the function should store received samples. - * @param cnt The number of messages which should be received. - * @return The number of messages actually received. - */ - int (*read) (struct node *n, struct sample *smps[], unsigned cnt); - - /** Send multiple messages in a single datagram / packet. - * - * Messages are sent with a single sendmsg() syscall by - * using gathering techniques (struct iovec). - * The messages have to be stored in a circular buffer / array m. - * So the indexes will wrap around after len. - * - * @param n A pointer to the node object. - * @param smps An array of pointers to memory blocks where samples read from. - * @param cnt The number of messages which should be sent. - * @return The number of messages actually sent. - */ - int (*write)(struct node *n, struct sample *smps[], unsigned cnt); - - /** Reverse source and destination of a node. - * - * This is not supported by all node types! - * - * @param n A pointer to the node object. - */ - int (*reverse)(struct node *n); -}; - -/** Initialize all registered node type subsystems. - * - * @see node_type::init - */ -int node_init(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg); - -/** De-initialize node type subsystems. - * - * @see node_type::deinit - */ -int node_deinit(struct node_type *vt); - /** Create a node by allocating dynamic memory. * * @see node_type::create @@ -229,9 +94,6 @@ char * node_name(struct node *n); */ char * node_name_long(struct node *n); -/** Return a pointer to a string which describes the node type */ -const char * node_name_type(struct node *n); - /** Reverse local and remote socket address. * * @see node_type::reverse @@ -263,4 +125,7 @@ int node_parse_list(struct list *list, config_setting_t *cfg, struct list *all); */ 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/node_type.h b/include/villas/node_type.h new file mode 100644 index 000000000..aa57bd4ba --- /dev/null +++ b/include/villas/node_type.h @@ -0,0 +1,150 @@ +/** Nodes + * + * @file + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + * + * @addtogroup node Node + * @{ + *********************************************************************************/ + +#pragma once + +#include + +#include "list.h" + +/* Forward declarations */ +struct node; +struct sample; + +/** C++ like vtable construct for node_types */ +struct node_type { + const char *name; /**< The unique name of this node. This must be allways the first member! */ + const char *description; /**< A short description of this node type. Will be shown in help text. */ + int vectorize; /**< Maximal vector length supported by this node type. Zero is unlimited. */ + + struct list instances; /**< A list of all existing nodes of this type. */ + size_t size; /**< Size of private data bock. @see node::_vd */ + + enum node_type_state { + NODE_TYPE_UNINITIALIZED = 0, + NODE_TYPE_INITIALIZED + } state; + + /** Global initialization per node type. + * + * This callback is invoked once per node-type. + * + * @param argc Number of arguments passed to the server executable (see main()). + * @param argv Array of arguments passed to the server executable (see main()). + * @param cfg Root libconfig object of global configuration file. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*init)(int argc, char * argv[], config_setting_t *cfg); + + /** Global de-initialization per node type. + * + * This callback is invoked once per node-type. + * + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*deinit)(); + + /** Allocate memory for an instance of this type. + * + * @return A pointer to the node-type specific private data. + */ + void * (*create)(); + + /** Free memory of an instance of this type. + * + * @param n A pointer to the node object. + */ + int (*destroy)(struct node *n); + + /** Parse node connection details.‚ + * + * @param n A pointer to the node object. + * @param cfg A libconfig object pointing to the node. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*parse)(struct node *n, config_setting_t *cfg); + + /** Returns a string with a textual represenation of this node. + * + * @param n A pointer to the node object. + * @return A pointer to a dynamically allocated string. Must be freed(). + */ + char * (*print)(struct node *n); + + /** Opens the connection to this node. + * + * @param n A pointer to the node object. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*open) (struct node *n); + + /** Close the connection to this node. + * + * @param n A pointer to the node object. + * @retval 0 Success. Everything went well. + * @retval <0 Error. Something went wrong. + */ + int (*close)(struct node *n); + + /** Receive multiple messages at once. + * + * Messages are received with a single recvmsg() syscall by + * using gathering techniques (struct iovec). + * The messages will be stored in a circular buffer / array @p m. + * Indexes used to address @p m will wrap around after len messages. + * Some node types might only support to receive one message at a time. + * + * @param n A pointer to the node object. + * @param smps An array of pointers to memory blocks where the function should store received samples. + * @param cnt The number of messages which should be received. + * @return The number of messages actually received. + */ + int (*read) (struct node *n, struct sample *smps[], unsigned cnt); + + /** Send multiple messages in a single datagram / packet. + * + * Messages are sent with a single sendmsg() syscall by + * using gathering techniques (struct iovec). + * The messages have to be stored in a circular buffer / array m. + * So the indexes will wrap around after len. + * + * @param n A pointer to the node object. + * @param smps An array of pointers to memory blocks where samples read from. + * @param cnt The number of messages which should be sent. + * @return The number of messages actually sent. + */ + int (*write)(struct node *n, struct sample *smps[], unsigned cnt); + + /** Reverse source and destination of a node. + * + * This is not supported by all node types! + * + * @param n A pointer to the node object. + */ + int (*reverse)(struct node *n); +}; + +/** Initialize all registered node type subsystems. + * + * @see node_type::init + */ +int node_type_init(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg); + +/** De-initialize node type subsystems. + * + * @see node_type::deinit + */ +int node_type_deinit(struct node_type *vt); + +/** @} */ \ No newline at end of file diff --git a/lib/Makefile.inc b/lib/Makefile.inc index a11c5485e..60c598c9a 100644 --- a/lib/Makefile.inc +++ b/lib/Makefile.inc @@ -6,7 +6,8 @@ LIB_SRCS = $(addprefix lib/nodes/, file.c cbuilder.c) \ $(addprefix lib/kernel/, kernel.c rt.c) \ $(addprefix lib/, sample.c path.c node.c hook.c \ log.c utils.c cfg.c hist.c timing.c pool.c list.c \ - queue.c memory.c advio.c web.c api.c plugin.c stats.c \ + queue.c memory.c advio.c web.c api.c plugin.c \ + node_type.c stats.c \ ) LIB_CFLAGS = $(CFLAGS) -fPIC diff --git a/lib/node.c b/lib/node.c index f4fd8f9fd..19ce08920 100644 --- a/lib/node.c +++ b/lib/node.c @@ -57,42 +57,6 @@ int node_write(struct node *n, struct sample *smps[], unsigned cnt) return nsent; } -int node_init(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg) -{ - int ret; - - if (vt->state != NODE_TYPE_UNINITIALIZED) - return -1; - - info("Initializing " YEL("%s") " node type", vt->name); - { INDENT - ret = vt->init ? vt->init(argc, argv, cfg) : -1; - } - - if (ret == 0) - vt->state = NODE_TYPE_INITIALIZED; - - return ret; -} - -int node_deinit(struct node_type *vt) -{ - int ret; - - if (vt->state != NODE_TYPE_INITIALIZED) - return -1; - - info("De-initializing " YEL("%s") " node type", vt->name); - { INDENT - ret = vt->deinit ? vt->deinit() : -1; - } - - if (ret == 0) - vt->state = NODE_TYPE_UNINITIALIZED; - - return ret; -} - int node_start(struct node *n) { int ret; @@ -163,11 +127,6 @@ const char * node_name_short(struct node *n) return n->name; } -const char * node_name_type(struct node *n) -{ - return n->_vt->name; -} - int node_reverse(struct node *n) { return n->_vt->reverse ? n->_vt->reverse(n) : -1; diff --git a/lib/node_type.c b/lib/node_type.c new file mode 100644 index 000000000..75b5baa3f --- /dev/null +++ b/lib/node_type.c @@ -0,0 +1,51 @@ +/** Nodes. + * + * @author Steffen Vogel + * @copyright 2017, Institute for Automation of Complex Power Systems, EONERC + *********************************************************************************/ + +#include +#include + +#include "sample.h" +#include "node.h" +#include "cfg.h" +#include "utils.h" +#include "config.h" +#include "plugin.h" + +int node_type_init(struct node_type *vt, int argc, char *argv[], config_setting_t *cfg) +{ + int ret; + + if (vt->state != NODE_TYPE_UNINITIALIZED) + return -1; + + info("Initializing " YEL("%s") " node type", vt->name); + { INDENT + ret = vt->init ? vt->init(argc, argv, cfg) : -1; + } + + if (ret == 0) + vt->state = NODE_TYPE_INITIALIZED; + + return ret; +} + +int node_type_deinit(struct node_type *vt) +{ + int ret; + + if (vt->state != NODE_TYPE_INITIALIZED) + return -1; + + info("De-initializing " YEL("%s") " node type", vt->name); + { INDENT + ret = vt->deinit ? vt->deinit() : -1; + } + + if (ret == 0) + vt->state = NODE_TYPE_UNINITIALIZED; + + return ret; +} diff --git a/src/node.c b/src/node.c index c73069b7e..795470306 100644 --- a/src/node.c +++ b/src/node.c @@ -104,8 +104,6 @@ int main(int argc, char *argv[]) } else if (argc > 2) usage(); - - char *uri = (argc == 2) ? argv[1] : NULL; #endif log_init(&cfg.log, V, LOG_ALL); @@ -123,7 +121,7 @@ int main(int argc, char *argv[]) info("Parsing configuration"); cfg_init_pre(&cfg); - cfg_parse(&cfg, uri); + cfg_parse_cli(&cfg, argc, argv); cfg_init_post(&cfg); diff --git a/src/pipe.c b/src/pipe.c index a92005c77..4f3e77762 100644 --- a/src/pipe.c +++ b/src/pipe.c @@ -54,7 +54,7 @@ static void quit(int signal, siginfo_t *sinfo, void *ctx) } node_stop(node); - node_deinit(node->_vt); + node_type_deinit(node->_vt); cfg_destroy(&cfg); @@ -229,7 +229,7 @@ int main(int argc, char *argv[]) if (reverse) node_reverse(node); - ret = node_init(node->_vt, argc-optind, argv+optind, config_root_setting(&cfg.cfg)); + ret = node_type_init(node->_vt, argc-optind, argv+optind, config_root_setting(&cfg.cfg)); if (ret) error("Failed to intialize node: %s", node_name(node)); diff --git a/src/test.c b/src/test.c index 2b55bac5b..37d48cea7 100644 --- a/src/test.c +++ b/src/test.c @@ -93,7 +93,7 @@ int main(int argc, char *argv[]) if (!node) error("There's no node with the name '%s'", argv[3]); - node_init(node->_vt, argc-3, argv+3, config_root_setting(&cfg.cfg)); + node_type_init(node->_vt, argc-3, argv+3, config_root_setting(&cfg.cfg)); node_start(node); /* Parse Arguments */ @@ -132,7 +132,7 @@ check: if (optarg == endptr) error("Unknown test: '%s'", argv[2]); node_stop(node); - node_deinit(node->_vt); + node_type_deinit(node->_vt); cfg_destroy(&cfg);