1
0
Fork 0
mirror of https://git.rwth-aachen.de/acs/public/villas/node/ synced 2025-03-16 00:00:02 +01:00
VILLASnode/lib/hook_list.cpp

234 lines
4.4 KiB
C++

/** 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>
extern "C" {
int hook_list_init(vlist *hs)
{
int ret;
ret = vlist_init(hs);
if (ret)
return ret;
return 0;
}
int hook_list_destroy(vlist *hs)
{
int ret;
ret = vlist_destroy(hs, (dtor_cb_t) hook_destroy, true);
if (ret)
return ret;
return 0;
}
int hook_list_parse(vlist *hs, json_t *cfg, int mask, path *o, 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);
hook *h = (hook *) alloc(sizeof(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(vlist *hs, vlist *sigs, int m, path *p, 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++) {
hook *h = (hook *) vlist_at(hs, i);
ret = hook_prepare(h, sigs);
if (ret)
return ret;
sigs = &h->signals;
}
return 0;
}
int hook_list_add(vlist *hs, int mask, path *p, node *n)
{
int ret;
assert(hs->state == STATE_INITIALIZED);
for (size_t i = 0; i < vlist_length(&plugins); i++) {
plugin *q = (plugin *) vlist_at(&plugins, i);
hook *h;
struct hook_type *ht = &q->hook;
if (q->type != PLUGIN_TYPE_HOOK)
continue;
if ((ht->flags & mask) == mask) {
h = (hook *) alloc(sizeof(hook));
if (!h)
return -1;
ret = hook_init(h, ht, p, n);
if (ret)
return ret;
vlist_push(hs, h);
}
}
return 0;
}
int hook_list_process(vlist *hs, sample *smps[], unsigned cnt)
{
unsigned ret, curent, processed = 0;
for (curent = 0; curent < cnt; curent++) {
sample *smp = smps[curent];
for (size_t i = 0; i < vlist_length(hs); i++) {
hook *h = (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(vlist *hs)
{
int ret;
for (size_t j = 0; j < vlist_length(hs); j++) {
hook *h = (hook *) vlist_at(hs, j);
ret = hook_periodic(h);
if (ret)
return ret;
}
return 0;
}
int hook_list_start(vlist *hs)
{
int ret;
for (size_t i = 0; i < vlist_length(hs); i++) {
hook *h = (hook *) vlist_at(hs, i);
ret = hook_start(h);
if (ret)
return ret;
}
return 0;
}
int hook_list_stop(vlist *hs)
{
int ret;
for (size_t i = 0; i < vlist_length(hs); i++) {
hook *h = (hook *) vlist_at(hs, i);
ret = hook_stop(h);
if (ret)
return ret;
}
return 0;
}
vlist * hook_list_get_signals(vlist *hs)
{
hook *h = (hook *) vlist_last(hs);
return &h->signals;
}
}