mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
Replaced static arrays for hooks and node types by dynamic linked lists and REGISTER_* macros
This commit is contained in:
parent
17659ffc83
commit
de37528788
14 changed files with 88 additions and 100 deletions
|
@ -21,11 +21,19 @@
|
|||
|
||||
#include <time.h>
|
||||
|
||||
#define REGISTER_HOOK(name, prio, fnc, type) \
|
||||
__attribute__((constructor)) void __register_ ## fnc () { \
|
||||
static struct hook h = { name, prio, fnc, type }; \
|
||||
list_push(&hooks, &h); \
|
||||
}
|
||||
|
||||
/* The configuration of hook parameters is done in "config.h" */
|
||||
|
||||
/* Forward declarations */
|
||||
struct path;
|
||||
|
||||
extern struct list hooks;
|
||||
|
||||
/** Callback type of hook function
|
||||
*
|
||||
* @param p The path which is processing this message.
|
||||
|
@ -50,24 +58,20 @@ enum hook_type {
|
|||
|
||||
/** Descriptor for user defined hooks. See hook_list[]. */
|
||||
struct hook {
|
||||
/** The unique name of this hook. This must be the first member! */
|
||||
const char *name;
|
||||
int priority;
|
||||
hook_cb_t callback;
|
||||
const char *name;
|
||||
enum hook_type type;
|
||||
};
|
||||
|
||||
/** Get a function pointer of a hook function by its name
|
||||
*
|
||||
* @param name The name of the requested hook
|
||||
* @retval NULL There is no hook registred with name.
|
||||
* @retval >0 A function pointer to the requested hook_cb_t hook.
|
||||
*/
|
||||
const struct hook * hook_lookup(const char *name);
|
||||
|
||||
struct hook * hook_lookup(const char *name);
|
||||
|
||||
/* The following prototypes are example hooks */
|
||||
|
||||
/** Example hook: Print the message. */
|
||||
/** Example hook: Print the message.
|
||||
* @example
|
||||
*/
|
||||
int hook_print(struct path *p);
|
||||
|
||||
/** Example hook: Drop messages. */
|
||||
|
|
|
@ -49,6 +49,8 @@ struct opal;
|
|||
* @param data A pointer to the data which should be freed.
|
||||
*/
|
||||
typedef void (*dtor_cb_t)(void *data);
|
||||
|
||||
typedef int (*cmp_cb_t)(void *, void *);
|
||||
|
||||
struct list {
|
||||
struct list_elm *head, *tail;
|
||||
|
@ -62,11 +64,13 @@ struct list_elm {
|
|||
union {
|
||||
void *ptr;
|
||||
struct node *node;
|
||||
struct node_type *type;
|
||||
struct path *path;
|
||||
struct interface *interface;
|
||||
struct socket *socket;
|
||||
struct opal *opal;
|
||||
struct gtfpga *gtfpga;
|
||||
struct hook *hook;
|
||||
} /* anonymous */;
|
||||
|
||||
int priority;
|
||||
|
@ -81,6 +85,12 @@ void list_push(struct list *l, void *p);
|
|||
|
||||
void list_insert(struct list *l, int prio, void *p);
|
||||
|
||||
struct list_elm * list_search(struct list *l, int (*cmp)(void *));
|
||||
/** Search the list for an element whose first element is a character array which matches name.
|
||||
*
|
||||
* @see Only possible because of §1424 of http://c0x.coding-guidelines.com/6.7.2.1.html
|
||||
*/
|
||||
void * list_lookup(const struct list *l, const char *name);
|
||||
|
||||
void * list_search(const struct list *l, cmp_cb_t cmp, void *ctx);
|
||||
|
||||
#endif /* _LIST_H_ */
|
||||
|
|
|
@ -23,11 +23,6 @@
|
|||
#include "msg.h"
|
||||
#include "list.h"
|
||||
|
||||
/** Static node initialization */
|
||||
#define NODE_INIT(n) { \
|
||||
.name = n \
|
||||
}
|
||||
|
||||
/* Helper macros for virtual node type */
|
||||
#define node_type(n) ((n)->vt->type)
|
||||
#define node_print(n, b, l) ((n)->vt->print(n, b, l))
|
||||
|
@ -38,20 +33,34 @@
|
|||
#define node_read_single(n, m) ((n)->vt->read(n, m, 1, 0, 1))
|
||||
#define node_write_single(n, m) ((n)->vt->write(n, m, 1, 0, 1))
|
||||
|
||||
/** Node type: layer, protocol, listen/connect */
|
||||
enum node_type {
|
||||
BSD_SOCKET, /**< BSD Socket API */
|
||||
LOG_FILE, /**< File IO */
|
||||
OPAL_ASYNC, /**< OPAL-RT Asynchronous Process Api */
|
||||
GTFPGA /**< Xilinx ML507 GTFPGA card */
|
||||
};
|
||||
|
||||
#define REGISTER_NODE_TYPE(type, name, fnc) \
|
||||
__attribute__((constructor)) void __register_node_ ## fnc () { \
|
||||
static struct node_type t = { name, type, \
|
||||
fnc ## _parse, fnc ## _print, \
|
||||
fnc ## _open, fnc ## _close, \
|
||||
fnc ## _read, fnc ## _write, \
|
||||
fnc ## _init, fnc ## _deinit };\
|
||||
list_push(&node_types, &t); \
|
||||
}
|
||||
|
||||
extern struct list node_types;
|
||||
|
||||
/** C++ like vtable construct for node_types
|
||||
* @todo Add comments
|
||||
*/
|
||||
struct node_vtable {
|
||||
const enum node_type type;
|
||||
const char *name;
|
||||
struct node_type {
|
||||
/** The unique name of this node. This must be the first member! */
|
||||
char *name;
|
||||
|
||||
/** Node type: layer, protocol, listen/connect */
|
||||
enum {
|
||||
BSD_SOCKET, /**< BSD Socket API */
|
||||
LOG_FILE, /**< File IO */
|
||||
OPAL_ASYNC, /**< OPAL-RT Asynchronous Process Api */
|
||||
GTFPGA, /**< Xilinx ML507 GTFPGA card */
|
||||
NGSI /**< NGSI 9/10 HTTP RESTful API (FIRWARE ContextBroker) */
|
||||
} type;
|
||||
|
||||
/** Parse node connection details for SOCKET type
|
||||
*
|
||||
|
|
|
@ -107,7 +107,7 @@ int config_parse_path(config_setting_t *cfg,
|
|||
cerror(cfg, "Invalid input node for path");
|
||||
|
||||
in = config_setting_get_string(cfg_in);
|
||||
p->in = node_lookup_name(in, nodes);
|
||||
p->in = list_lookup(nodes, in);
|
||||
if (!p->in)
|
||||
cerror(cfg_in, "Invalid input node '%s'", in);
|
||||
|
||||
|
|
|
@ -222,3 +222,5 @@ int file_write(struct node *n, struct msg *pool, int poolsize, int first, int cn
|
|||
|
||||
return i;
|
||||
}
|
||||
|
||||
REGISTER_NODE_TYPE(LOG_FILE, "file", file)
|
|
@ -268,3 +268,4 @@ int gtfpga_write(struct node *n, struct msg *pool, int poolsize, int first, int
|
|||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_NODE_TYPE(GTFPGA, "gtfpga", gtfpga)
|
|
@ -23,32 +23,10 @@
|
|||
|
||||
/* Some hooks can be configured by constants in te file "config.h" */
|
||||
|
||||
/** This is a static list of available hooks.
|
||||
*
|
||||
* It's used by hook_lookup to parse hook identfiers from the configuration file.
|
||||
* The list must be terminated by NULL pointers!
|
||||
*/
|
||||
static const struct hook hook_list[] = {
|
||||
/* Priority, Callback, Name, Type */
|
||||
{ 99, hook_print, "print", HOOK_MSG },
|
||||
{ 99, hook_decimate, "decimate", HOOK_POST },
|
||||
{ 99, hook_tofixed, "tofixed", HOOK_MSG },
|
||||
{ 99, hook_ts, "ts", HOOK_MSG },
|
||||
{ 99, hook_fir, "fir", HOOK_POST },
|
||||
{ 99, hook_dft, "dft", HOOK_POST }
|
||||
};
|
||||
|
||||
const struct hook* hook_lookup(const char *name)
|
||||
{
|
||||
for (int i=0; i<ARRAY_LEN(hook_list); i++) {
|
||||
if (!strcmp(name, hook_list[i].name))
|
||||
return &hook_list[i];
|
||||
}
|
||||
|
||||
return NULL; /* No matching hook was found */
|
||||
}
|
||||
|
||||
/** This is a static list of available hooks. */
|
||||
struct list hooks;
|
||||
|
||||
REGISTER_HOOK("print", 99, hook_print, HOOK_MSG)
|
||||
int hook_print(struct path *p)
|
||||
{
|
||||
struct msg *m = p->current;
|
||||
|
@ -60,6 +38,7 @@ int hook_print(struct path *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_HOOK("tofixed", 99, hook_tofixed, HOOK_MSG)
|
||||
int hook_tofixed(struct path *p)
|
||||
{
|
||||
struct msg *m = p->current;
|
||||
|
@ -70,6 +49,7 @@ int hook_tofixed(struct path *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_HOOK("ts", 99, hook_ts, HOOK_MSG)
|
||||
int hook_ts(struct path *p)
|
||||
{
|
||||
struct msg *m = p->current;
|
||||
|
@ -80,6 +60,7 @@ int hook_ts(struct path *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_HOOK("fir", 99, hook_fir, HOOK_POST)
|
||||
int hook_fir(struct path *p)
|
||||
{
|
||||
/** Simple FIR-LP: F_s = 1kHz, F_pass = 100 Hz, F_block = 300
|
||||
|
@ -108,12 +89,14 @@ int hook_fir(struct path *p)
|
|||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_HOOK("decimate", 99, hook_decimate, HOOK_POST)
|
||||
int hook_decimate(struct path *p)
|
||||
{
|
||||
/* Only sent every HOOK_DECIMATE_RATIO'th message */
|
||||
return p->received % HOOK_DECIMATE_RATIO;
|
||||
}
|
||||
|
||||
REGISTER_HOOK("dft", 99, hook_dft, HOOK_POST)
|
||||
int hook_dft(struct path *p)
|
||||
{
|
||||
return 0; /** @todo Implement */
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
||||
*********************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "utils.h"
|
||||
#include "list.h"
|
||||
|
||||
|
@ -103,11 +105,21 @@ void list_insert(struct list *l, int prio, void *p)
|
|||
pthread_mutex_unlock(&l->lock);
|
||||
}
|
||||
|
||||
struct list_elm * list_search(struct list *l, int (*cmp)(void *))
|
||||
void * list_lookup(const struct list *l, const char *name)
|
||||
{
|
||||
FOREACH(l, it) {
|
||||
if (!cmp(it->ptr))
|
||||
return it;
|
||||
if (!strcmp(*(char **) it->ptr, name))
|
||||
return it->ptr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void * list_search(const struct list *l, cmp_cb_t cmp, void *ctx)
|
||||
{
|
||||
FOREACH(l, it) {
|
||||
if (!cmp(it->ptr, ctx))
|
||||
return it->ptr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
|
|
@ -27,30 +27,13 @@
|
|||
#include <netlink/route/classifier.h>
|
||||
#endif
|
||||
|
||||
#define VTABLE(type, name, fnc) { type, name, \
|
||||
fnc ## _parse, fnc ## _print, \
|
||||
fnc ## _open, fnc ## _close, \
|
||||
fnc ## _read, fnc ## _write, \
|
||||
fnc ## _init, fnc ## _deinit }
|
||||
|
||||
/** Vtable for virtual node sub types */
|
||||
struct node_vtable vtables[] = {
|
||||
#ifdef ENABLE_OPAL_ASYNC
|
||||
VTABLE(OPAL_ASYNC, "opal", opal),
|
||||
#endif
|
||||
#ifdef ENABLE_GTFPGA
|
||||
VTABLE(GTFPGA, "gtfpga", gtfpga),
|
||||
#endif
|
||||
#ifdef ENABLE_SOCKET
|
||||
VTABLE(BSD_SOCKET, "socket", socket),
|
||||
#endif
|
||||
VTABLE(LOG_FILE, "file", file)
|
||||
};
|
||||
struct list node_types = LIST_INIT(NULL);
|
||||
|
||||
int node_init(int argc, char *argv[], struct settings *set)
|
||||
{ INDENT
|
||||
for (int i=0; i<ARRAY_LEN(vtables); i++) {
|
||||
const struct node_vtable *vt = &vtables[i];
|
||||
FOREACH(&node_types, it) {
|
||||
const struct node_type *vt = it->type;
|
||||
if (vt->refcnt) {
|
||||
info("Initializing '%s' node type", vt->name);
|
||||
vt->init(argc, argv, set);
|
||||
|
@ -63,8 +46,8 @@ int node_init(int argc, char *argv[], struct settings *set)
|
|||
int node_deinit()
|
||||
{ INDENT
|
||||
/* De-initialize node types */
|
||||
for (int i=0; i<ARRAY_LEN(vtables); i++) {
|
||||
struct node_vtable *vt = &vtables[i];
|
||||
FOREACH(&node_types, it) {
|
||||
struct node_type *vt = it->type;
|
||||
if (vt->refcnt) {
|
||||
info("De-initializing '%s' node type", vt->name);
|
||||
vt->deinit();
|
||||
|
@ -73,26 +56,6 @@ int node_deinit()
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct node * node_lookup_name(const char *str, struct list *nodes)
|
||||
{
|
||||
FOREACH(nodes, it) {
|
||||
if (!strcmp(str, it->node->name))
|
||||
return it->node;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct node_vtable * node_lookup_vtable(const char *str)
|
||||
{
|
||||
for (int i = 0; i < ARRAY_LEN(vtables); i++) {
|
||||
if (!strcmp(vtables[i].name, str))
|
||||
return &vtables[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int node_start(struct node *n)
|
||||
{ INDENT
|
||||
if (!n->refcnt) {
|
||||
|
|
|
@ -271,3 +271,5 @@ int opal_write(struct node *n, struct msg *pool, int poolsize, int first, int cn
|
|||
|
||||
return 1;
|
||||
}
|
||||
|
||||
REGISTER_NODE_TYPE(OPAL_ASYNC, "opal", opal)
|
|
@ -92,7 +92,7 @@ int main(int argc, char *argv[])
|
|||
config_init(&config);
|
||||
config_parse(argv[optind], &config, &set, &nodes, NULL);
|
||||
|
||||
node = node_lookup_name(argv[optind+1], &nodes);
|
||||
node = list_lookup(&nodes, argv[optind+1]);
|
||||
if (!node)
|
||||
error("There's no node with the name '%s'", argv[optind+1]);
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ int main(int argc, char *argv[])
|
|||
config_init(&config);
|
||||
config_parse(argv[optind], &config, &set, &nodes, NULL);
|
||||
|
||||
node = node_lookup_name(argv[optind+1], &nodes);
|
||||
node = list_lookup(&nodes, argv[optind+1]);
|
||||
if (!node)
|
||||
error("There's no node with the name '%s'", argv[optind+1]);
|
||||
|
||||
|
|
|
@ -452,3 +452,5 @@ int socket_parse_addr(const char *addr, struct sockaddr *saddr, enum socket_laye
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
REGISTER_NODE_TYPE(BSD_SOCKET, "socket", socket)
|
|
@ -91,7 +91,7 @@ int main(int argc, char *argv[])
|
|||
config_init(&config);
|
||||
config_parse(argv[1], &config, &settings, &nodes, NULL);
|
||||
|
||||
node = node_lookup_name(argv[3], &nodes);
|
||||
node = list_lookup(&nodes, argv[3]);
|
||||
if (!node)
|
||||
error("There's no node with the name '%s'", argv[3]);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue