1
0
Fork 0
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:
Steffen Vogel 2015-09-19 15:26:30 +02:00
parent 17659ffc83
commit de37528788
14 changed files with 88 additions and 100 deletions

View file

@ -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. */

View file

@ -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_ */

View file

@ -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
*

View file

@ -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);

View file

@ -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)

View 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)

View file

@ -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 */

View file

@ -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;

View file

@ -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) {

View file

@ -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)

View file

@ -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]);

View file

@ -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]);

View file

@ -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)

View file

@ -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]);