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

added first version of configurable hook support with a few examples

TODO: this is not tested yet

git-svn-id: https://zerberus.eonerc.rwth-aachen.de:8443/svn/s2ss/trunk@177 8ec27952-4edc-4aab-86aa-e87bb2611832
This commit is contained in:
Steffen Vogel 2014-08-31 14:43:28 +00:00
parent 183b5e158a
commit 64cead2f2e
7 changed files with 147 additions and 9 deletions

View file

@ -5,7 +5,7 @@ SRCS = server.c send.c receive.c random.c node.c path.c utils.c msg.c cfg.c if.c
all: $(TARGETS)
# Dependencies for individual binaries
server: node.o msg.o utils.o path.o cfg.o if.o tc.o
server: node.o msg.o utils.o path.o cfg.o if.o tc.o hooks.o
send: node.o msg.o utils.o
receive: node.o msg.o utils.o
random: node.o msg.o utils.o

View file

@ -34,6 +34,7 @@ paths = (
reverse = true, # Setup a path in the reverse direction too
in = "acs", # Name of the node we listen to (see above)
out = "sintef", # Name of the node we send to
rate = 100 # Send message over this path with a fixed (equalized) rate
rate = 100, # Send message over this path with a fixed (equalized) rate
hook = "print" # Register custom hook funktion (see src/hooks.c)
}
);

60
server/include/hooks.h Normal file
View file

@ -0,0 +1,60 @@
/** Hook funktions
*
* Every path can register a hook function which is called for every received
* message. This can be used to debug the data flow, get statistics
* or alter the message.
*
* This file includes some examples.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
* @file
*/
#ifndef _HOOKS_H_
#define _HOOKS_H_
struct msg;
struct path;
/** Callback type of hook function
*
* @todo Add a way to pass custom data to the hooks
* @param m The message which is forwarded
* @param p The path which is processing this message.
* @retval 0 Success. Continue processing the message.
* @retval <0 Error. Drop the message.
*/
typedef int (*hook_cb_t)(struct msg *m, struct path *p);
/** 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!
*/
struct hook_id {
hook_cb_t cb;
const char *name;
};
/** 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.
*/
hook_cb_t hook_lookup(const char *name);
/** Example hook: Print the message. */
int hook_print(struct msg *m, struct path *p);
/** Example hook: Filter the message on some criteria. */
int hook_filter(struct msg *m, struct path *p);
/** Example hook: Convert the message values to fixed precision. */
int hook_tofixed(struct msg *m, struct path *p);
/** Example hook: Chain multiple hooks */
int hook_multiple(struct msg *m, struct path *p);
#endif /* _HOOKS_H_ */

View file

@ -14,6 +14,7 @@
#include "config.h"
#include "node.h"
#include "msg.h"
#include "hooks.h"
/** The datastructure for a path.
*
@ -26,12 +27,8 @@ struct path
/** Pointer to the outgoing node */
struct node *out;
/** If non NULL this function is called for every received message.
*
* This hook can be used to filter messages on a user-defined criteria.
* If the function has a non-zero return value the message will be dropped.
*/
int (*hook)(struct msg *m);
/** Function pointer of the hook */
hook_cb_t hook;
/** Send messages with a fixed rate over this path */
double rate;

View file

@ -17,6 +17,7 @@
#include "node.h"
#include "path.h"
#include "utils.h"
#include "hooks.h"
int config_parse(const char *filename, config_t *cfg, struct settings *set,
struct node **nodes, struct path **paths)
@ -101,6 +102,13 @@ int config_parse_path(config_setting_t *cfg,
cerror(cfg, "Invalid output node '%s'", out);
/* Optional settings */
if (config_setting_lookup_string(cfg, "hook", &hook)) {
path->hook = hook_lookup(hook);
if (!path->hook)
cerror(cfg, "Failed to lookup hook function. Not registred?");
}
config_setting_lookup_bool(cfg, "enabled", &enabled);
config_setting_lookup_bool(cfg, "reverse", &reverse);
config_setting_lookup_float(cfg, "rate", &path->rate);

72
server/src/hooks.c Normal file
View file

@ -0,0 +1,72 @@
/** Hook funktions
*
* Every path can register a hook function which is called for every received
* message. This can be used to debug the data flow, get statistics
* or alter the message.
*
* This file includes some examples.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014, Institute for Automation of Complex Power Systems, EONERC
*/
#include <string.h>
#include "msg.h"
#include "hooks.h"
/** @todo Make const */
static struct hook_id hook_list[] = {
{ hook_print, "print" },
{ hook_filter, "filter" },
{ hook_tofixed, "tofixed" },
{ hook_multiple, "multiple" },
{ NULL }
};
hook_cb_t hook_lookup(const char *name)
{
for (struct hook_id *hid = hook_list; hid->cb; hid++) {
if (!strcmp(name, hid->name)) {
return hid->cb;
}
}
return NULL; /* No matching hook was found */
}
int hook_print(struct msg *m, struct path *p)
{
/* Print every message once to stdout */
msg_fprint(stdout, m);
return 0;
}
int hook_filter(struct msg *m, struct path *p)
{
/* Drop every 10th message */
if (m->sequence % 10 == 0)
return -1;
else
return 0;
}
int hook_tofixed(struct msg *m, struct path *p)
{
for (int i=0; i<m->length; i++) {
m->data[i].i = m->data[i].f * 1e3;
}
return 0;
}
int hook_multiple(struct msg *m, struct path *p)
{
if (hook_print(m, p))
return -1;
else if (hook_tofixed(m, p))
return -1;
else
return 0;
}

View file

@ -108,7 +108,7 @@ static void * path_run(void *arg)
continue;
}
if (p->hook && p->hook(m)) {
if (p->hook && p->hook(m, p)) {
p->skipped++;
continue;
}