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

hook: separate hook_list_*() and hook_*() functions

This commit is contained in:
Steffen Vogel 2019-03-16 10:04:23 +01:00
parent 4a5b0b65b2
commit b5444577b4
12 changed files with 341 additions and 244 deletions

View file

@ -1,8 +1,8 @@
/** Hook funktions
/** Hook functions
*
* 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.
* Every node or path can register hook functions which is called for every
* processed sample. This can be used to debug the data flow, get statistics
* or alter the sample contents.
*
* This file includes some examples.
*
@ -101,34 +101,6 @@ struct hook_type * hook_type(struct hook *h)
return h->_vt;
}
int hook_list_init(struct vlist *hs);
int hook_list_destroy(struct vlist *hs);
/** Parses an object of hooks
*
* Example:
*
* {
* stats = {
* output = "stdout"
* },
* skip_first = {
* seconds = 10
* },
* hooks = [ "print" ]
* }
*/
int hook_list_parse(struct vlist *hs, json_t *cfg, int mask, struct path *p, struct node *n);
int hook_list_prepare(struct vlist *hs, struct vlist *sigs, int mask, struct path *p, struct node *n);
int hook_list_prepare_signals(struct vlist *hs, struct vlist *signals);
int hook_list_add(struct vlist *hs, int mask, struct path *p, struct node *n);
int hook_list_process(struct vlist *hs, struct sample *smps[], unsigned cnt);
#ifdef __cplusplus
}
#endif

View file

@ -0,0 +1,84 @@
/** Hook list functions
*
* This file includes some examples.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup hooks User-defined hook functions
* @ingroup path
* @{
*********************************************************************************/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <jansson.h>
/* Forward declarations */
struct vlist;
struct sample;
struct path;
struct node;
int hook_list_init(struct vlist *hs);
int hook_list_destroy(struct vlist *hs);
/** Parses an object of hooks
*
* Example:
*
* {
* stats = {
* output = "stdout"
* },
* skip_first = {
* seconds = 10
* },
* hooks = [ "print" ]
* }
*/
int hook_list_parse(struct vlist *hs, json_t *cfg, int mask, struct path *p, struct node *n);
int hook_list_prepare(struct vlist *hs, struct vlist *sigs, int mask, struct path *p, struct node *n);
int hook_list_prepare_signals(struct vlist *hs, struct vlist *signals);
int hook_list_add(struct vlist *hs, int mask, struct path *p, struct node *n);
int hook_list_process(struct vlist *hs, struct sample *smps[], unsigned cnt);
int hook_list_periodic(struct vlist *hs);
int hook_list_start(struct vlist *hs);
int hook_list_stop(struct vlist *hs);
struct vlist * hook_list_get_signals(struct vlist *hs);
#ifdef __cplusplus
}
#endif

View file

@ -37,7 +37,6 @@
#include <villas/pool.h>
#include <villas/bitset.h>
#include <villas/common.h>
#include <villas/hook.h>
#include <villas/mapping.h>
#include <villas/task.h>

View file

@ -89,6 +89,7 @@ if(WITH_HOOKS)
list(APPEND LIB_SRC
hook.c
hook_type.c
hook_list.c
)
add_subdirectory(hooks)

View file

@ -229,157 +229,7 @@ int hook_cmp_priority(const void *a, const void *b)
return ha->priority - hb->priority;
}
int hook_list_init(struct vlist *hs)
{
int ret;
ret = vlist_init(hs);
if (ret)
return ret;
return 0;
}
int hook_list_destroy(struct vlist *hs)
{
int ret;
ret = vlist_destroy(hs, (dtor_cb_t) hook_destroy, true);
if (ret)
return ret;
return 0;
}
int hook_list_parse(struct vlist *hs, json_t *cfg, int mask, struct path *o, struct node *n)
{
if (!json_is_array(cfg))
error("Hooks must be configured as a list of objects");
size_t i;
json_t *json_hook;
json_array_foreach(cfg, i, json_hook) {
int ret;
const char *type;
struct hook_type *ht;
json_error_t err;
ret = json_unpack_ex(json_hook, &err, 0, "{ s: s }", "type", &type);
if (ret)
jerror(&err, "Failed to parse hook");
ht = hook_type_lookup(type);
if (!ht)
jerror(&err, "Unkown hook type '%s'", type);
if (!(ht->flags & mask))
error("Hook %s not allowed here.", type);
struct hook *h = (struct hook *) alloc(sizeof(struct hook));
ret = hook_init(h, ht, o, n);
if (ret)
error("Failed to initialize hook: %s", type);
ret = hook_parse(h, json_hook);
if (ret)
jerror(&err, "Failed to parse hook configuration");
vlist_push(hs, h);
}
return 0;
}
int hook_list_prepare(struct vlist *hs, struct vlist *sigs, int m, struct path *p, struct node *n)
{
int ret;
/* Add internal hooks if they are not already in the list */
ret = hook_list_add(hs, m, p, n);
if (ret)
return ret;
/* We sort the hooks according to their priority */
vlist_sort(hs, hook_cmp_priority);
for (size_t i = 0; i < vlist_length(hs); i++) {
struct hook *h = (struct hook *) vlist_at(hs, i);
ret = hook_prepare(h, sigs);
if (ret)
return ret;
sigs = &h->signals;
}
return 0;
}
int hook_list_add(struct vlist *hs, int mask, struct path *p, struct node *n)
{
int ret;
assert(hs->state == STATE_INITIALIZED);
for (size_t i = 0; i < vlist_length(&plugins); i++) {
struct plugin *q = (struct plugin *) vlist_at(&plugins, i);
struct hook *h;
struct hook_type *vt = &q->hook;
if (q->type != PLUGIN_TYPE_HOOK)
continue;
if ((vt->flags & mask) == mask) {
h = (struct hook *) alloc(sizeof(struct hook));
if (!h)
return -1;
ret = hook_init(h, vt, p, n);
if (ret)
return ret;
vlist_push(hs, h);
}
}
return 0;
}
const char * hook_type_name(struct hook_type *vt)
{
return plugin_name(vt);
}
int hook_list_process(struct vlist *hs, struct sample *smps[], unsigned cnt)
{
unsigned ret, curent, processed = 0;
for (curent = 0; curent < cnt; curent++) {
struct sample *smp = smps[curent];
for (size_t i = 0; i < vlist_length(hs); i++) {
struct hook *h = (struct hook *) vlist_at(hs, i);
ret = hook_process(h, smp);
switch (ret) {
case HOOK_ERROR:
return -1;
case HOOK_OK:
smps[processed++] = smp;
break;
case HOOK_SKIP_SAMPLE:
goto skip;
case HOOK_STOP_PROCESSING:
goto stop;
}
}
skip: {}
}
stop: return processed;
}

230
lib/hook_list.c Normal file
View file

@ -0,0 +1,230 @@
/** Hook-releated functions.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <villas/plugin.h>
#include <villas/hook.h>
#include <villas/hook_type.h>
#include <villas/hook_list.h>
#include <villas/list.h>
#include <villas/log.h>
int hook_list_init(struct vlist *hs)
{
int ret;
ret = vlist_init(hs);
if (ret)
return ret;
return 0;
}
int hook_list_destroy(struct vlist *hs)
{
int ret;
ret = vlist_destroy(hs, (dtor_cb_t) hook_destroy, true);
if (ret)
return ret;
return 0;
}
int hook_list_parse(struct vlist *hs, json_t *cfg, int mask, struct path *o, struct node *n)
{
if (!json_is_array(cfg))
error("Hooks must be configured as a list of objects");
size_t i;
json_t *json_hook;
json_array_foreach(cfg, i, json_hook) {
int ret;
const char *type;
struct hook_type *ht;
json_error_t err;
ret = json_unpack_ex(json_hook, &err, 0, "{ s: s }", "type", &type);
if (ret)
jerror(&err, "Failed to parse hook");
ht = hook_type_lookup(type);
if (!ht)
jerror(&err, "Unkown hook type '%s'", type);
if (!(ht->flags & mask))
error("Hook %s not allowed here.", type);
struct hook *h = (struct hook *) alloc(sizeof(struct hook));
ret = hook_init(h, ht, o, n);
if (ret)
error("Failed to initialize hook: %s", type);
ret = hook_parse(h, json_hook);
if (ret)
jerror(&err, "Failed to parse hook configuration");
vlist_push(hs, h);
}
return 0;
}
int hook_list_prepare(struct vlist *hs, struct vlist *sigs, int m, struct path *p, struct node *n)
{
int ret;
/* Add internal hooks if they are not already in the list */
ret = hook_list_add(hs, m, p, n);
if (ret)
return ret;
/* We sort the hooks according to their priority */
vlist_sort(hs, hook_cmp_priority);
for (size_t i = 0; i < vlist_length(hs); i++) {
struct hook *h = (struct hook *) vlist_at(hs, i);
ret = hook_prepare(h, sigs);
if (ret)
return ret;
sigs = &h->signals;
}
return 0;
}
int hook_list_add(struct vlist *hs, int mask, struct path *p, struct node *n)
{
int ret;
assert(hs->state == STATE_INITIALIZED);
for (size_t i = 0; i < vlist_length(&plugins); i++) {
struct plugin *q = (struct plugin *) vlist_at(&plugins, i);
struct hook *h;
struct hook_type *vt = &q->hook;
if (q->type != PLUGIN_TYPE_HOOK)
continue;
if ((vt->flags & mask) == mask) {
h = (struct hook *) alloc(sizeof(struct hook));
if (!h)
return -1;
ret = hook_init(h, vt, p, n);
if (ret)
return ret;
vlist_push(hs, h);
}
}
return 0;
}
int hook_list_process(struct vlist *hs, struct sample *smps[], unsigned cnt)
{
unsigned ret, curent, processed = 0;
for (curent = 0; curent < cnt; curent++) {
struct sample *smp = smps[curent];
for (size_t i = 0; i < vlist_length(hs); i++) {
struct hook *h = (struct hook *) vlist_at(hs, i);
ret = hook_process(h, smp);
switch (ret) {
case HOOK_ERROR:
return -1;
case HOOK_OK:
smps[processed++] = smp;
break;
case HOOK_SKIP_SAMPLE:
goto skip;
case HOOK_STOP_PROCESSING:
goto stop;
}
}
skip: {}
}
stop: return processed;
}
int hook_list_periodic(struct vlist *hs)
{
int ret;
for (size_t j = 0; j < vlist_length(hs); j++) {
struct hook *h = (struct hook *) vlist_at(hs, j);
ret = hook_periodic(h);
if (ret)
return ret;
}
return 0;
}
int hook_list_start(struct vlist *hs)
{
int ret;
for (size_t i = 0; i < vlist_length(hs); i++) {
struct hook *h = (struct hook *) vlist_at(hs, i);
ret = hook_start(h);
if (ret)
return ret;
}
return 0;
}
int hook_list_stop(struct vlist *hs)
{
int ret;
for (size_t i = 0; i < vlist_length(hs); i++) {
struct hook *h = (struct hook *) vlist_at(hs, i);
ret = hook_stop(h);
if (ret)
return ret;
}
return 0;
}
struct vlist * hook_list_get_signals(struct vlist *hs)
{
struct hook *h = vlist_last(hs);
return &h->signals;
}

View file

@ -25,6 +25,7 @@
#include <villas/node/config.h>
#include <villas/hook.h>
#include <villas/hook_list.h>
#include <villas/sample.h>
#include <villas/node.h>
#include <villas/utils.h>

View file

@ -23,6 +23,7 @@
#include <villas/utils.h>
#include <villas/hook.h>
#include <villas/hook_list.h>
#include <villas/node.h>
#include <villas/node_direction.h>
@ -193,13 +194,9 @@ int node_direction_start(struct node_direction *nd, struct node *n)
#ifdef WITH_HOOKS
int ret;
for (size_t i = 0; i < vlist_length(&nd->hooks); i++) {
struct hook *h = (struct hook *) vlist_at(&nd->hooks, i);
ret = hook_start(h);
if (ret)
return ret;
}
ret = hook_list_start(&nd->hooks);
if (ret)
return ret;
#endif /* WITH_HOOKS */
nd->state = STATE_STARTED;
@ -214,13 +211,9 @@ int node_direction_stop(struct node_direction *nd, struct node *n)
#ifdef WITH_HOOKS
int ret;
for (size_t i = 0; i < vlist_length(&nd->hooks); i++) {
struct hook *h = (struct hook *) vlist_at(&nd->hooks, i);
ret = hook_stop(h);
if (ret)
return ret;
}
ret = hook_list_stop(&nd->hooks);
if (ret)
return ret;
#endif /* WITH_HOOKS */
nd->state = STATE_STOPPED;
@ -233,9 +226,7 @@ struct vlist * node_direction_get_signals(struct node_direction *nd)
#ifdef WITH_HOOKS
assert(nd->state == STATE_PREPARED);
struct hook *h = vlist_last(&nd->hooks);
return &h->signals;
return hook_list_get_signals(&nd->hooks);
#else
return &nd->signals;
#endif

View file

@ -32,7 +32,7 @@
#include <villas/timing.h>
#include <villas/pool.h>
#include <villas/queue.h>
#include <villas/hook.h>
#include <villas/hook_list.h>
#include <villas/plugin.h>
#include <villas/memory.h>
#include <villas/stats.h>
@ -204,9 +204,6 @@ int path_prepare(struct path *p)
ret = hook_list_prepare(&p->hooks, &p->signals, m, p, NULL);
if (ret)
return ret;
/* We sort the hooks according to their priority before starting the path */
vlist_sort(&p->hooks, hook_cmp_priority);
#endif /* WITH_HOOKS */
/* Initialize destinations */
@ -561,13 +558,9 @@ int path_start(struct path *p)
free(mask);
#ifdef WITH_HOOKS
for (size_t i = 0; i < vlist_length(&p->hooks); i++) {
struct hook *h = (struct hook *) vlist_at(&p->hooks, i);
ret = hook_start(h);
if (ret)
return ret;
}
ret = hook_list_start(&p->hooks);
if (ret)
return ret;
#endif /* WITH_HOOKS */
p->last_sequence = 0;
@ -627,13 +620,9 @@ int path_stop(struct path *p)
return ret;
#ifdef WITH_HOOKS
for (size_t i = 0; i < vlist_length(&p->hooks); i++) {
struct hook *h = (struct hook *) vlist_at(&p->hooks, i);
ret = hook_stop(h);
if (ret)
return ret;
}
ret = hook_list_stop(&p->hooks);
if (ret)
return ret;
#endif /* WITH_HOOKS */
sample_decref(p->last_sample);

View file

@ -25,6 +25,8 @@
#include <villas/sample.h>
#include <villas/node.h>
#include <villas/path.h>
#include <villas/hook_list.h>
#include <villas/path_destination.h>
#include <villas/path_source.h>

View file

@ -30,7 +30,7 @@
#include <villas/path.h>
#include <villas/utils.h>
#include <villas/list.h>
#include <villas/hook.h>
#include <villas/hook_list.h>
#include <villas/advio.h>
#include <villas/plugin.h>
#include <villas/memory.h>
@ -571,8 +571,6 @@ SuperNode::~SuperNode()
int SuperNode::periodic()
{
int ret;
int started = 0;
for (size_t i = 0; i < vlist_length(&paths); i++) {
@ -582,13 +580,7 @@ int SuperNode::periodic()
started++;
#ifdef WITH_HOOKS
for (size_t j = 0; j < vlist_length(&p->hooks); j++) {
hook *h = (struct hook *) vlist_at(&p->hooks, j);
ret = hook_periodic(h);
if (ret)
return ret;
}
hook_list_periodic(&p->hooks);
#endif /* WITH_HOOKS */
}
}
@ -600,21 +592,8 @@ int SuperNode::periodic()
continue;
#ifdef WITH_HOOKS
for (size_t j = 0; j < vlist_length(&n->in.hooks); j++) {
auto *h = (struct hook *) vlist_at(&n->in.hooks, j);
ret = hook_periodic(h);
if (ret)
return ret;
}
for (size_t j = 0; j < vlist_length(&n->out.hooks); j++) {
auto *h = (struct hook *) vlist_at(&n->out.hooks, j);
ret = hook_periodic(h);
if (ret)
return ret;
}
hook_list_periodic(&n->in.hooks);
hook_list_periodic(&n->out.hooks);
#endif /* WITH_HOOKS */
}

View file

@ -44,7 +44,6 @@
#include <villas/plugin.h>
#include <villas/kernel/kernel.hpp>
#include <villas/kernel/rt.hpp>
#include <villas/hook.h>
#include <villas/stats.h>
#ifdef ENABLE_OPAL_ASYNC