mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-16 00:00:02 +01:00
105 lines
3 KiB
C
105 lines
3 KiB
C
/** Internal hook functions.
|
|
*
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
|
* @copyright 2014-2016, Institute for Automation of Complex Power Systems, EONERC
|
|
* This file is part of VILLASnode. All Rights Reserved. Proprietary and confidential.
|
|
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
|
*********************************************************************************/
|
|
|
|
#include "hooks.h"
|
|
#include "timing.h"
|
|
#include "sample.h"
|
|
#include "path.h"
|
|
#include "utils.h"
|
|
|
|
REGISTER_HOOK("fix_ts", "Update timestamps of sample if not set", 0, 0, hook_fix_ts, HOOK_INTERNAL | HOOK_READ)
|
|
int hook_fix_ts(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt)
|
|
{
|
|
struct timespec now = time_now();
|
|
|
|
for (int i = 0; i < cnt; i++) {
|
|
/* Check for missing receive timestamp
|
|
* Usually node_type::read() should update the receive timestamp.
|
|
* An example would be to use hardware timestamp capabilities of
|
|
* modern NICs.
|
|
*/
|
|
if ((smps[i]->ts.received.tv_sec == 0 && smps[i]->ts.received.tv_nsec == 0) ||
|
|
(smps[i]->ts.received.tv_sec == -1 && smps[i]->ts.received.tv_nsec == -1))
|
|
smps[i]->ts.received = now;
|
|
|
|
/* Check for missing origin timestamp */
|
|
if ((smps[i]->ts.origin.tv_sec == 0 && smps[i]->ts.origin.tv_nsec == 0) ||
|
|
(smps[i]->ts.origin.tv_sec == -1 && smps[i]->ts.origin.tv_nsec == -1))
|
|
smps[i]->ts.origin = now;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
REGISTER_HOOK("restart", "Call restart hooks for current path", 1, 1, hook_restart, HOOK_INTERNAL | HOOK_READ)
|
|
int hook_restart(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt)
|
|
{
|
|
for (int i = 0; i < cnt; i++) {
|
|
h->last = smps[i];
|
|
|
|
if (h->prev) {
|
|
if (h->last->sequence == 0 &&
|
|
h->prev->sequence <= UINT32_MAX - 32) {
|
|
warn("Simulation for path %s restarted (prev->seq=%u, current->seq=%u)",
|
|
path_name(p), h->prev->sequence, h->last->sequence);
|
|
|
|
p->invalid =
|
|
p->skipped =
|
|
p->dropped = 0;
|
|
|
|
hook_run(p, &smps[i], cnt - i, HOOK_PATH_RESTART);
|
|
}
|
|
}
|
|
|
|
h->prev = h->last;
|
|
}
|
|
|
|
return cnt;
|
|
}
|
|
|
|
REGISTER_HOOK("drop", "Drop messages with reordered sequence numbers", 3, 1, hook_drop, HOOK_INTERNAL | HOOK_READ)
|
|
int hook_drop(struct path *p, struct hook *h, int when, struct sample *smps[], size_t cnt)
|
|
{
|
|
int i, ok, dist;
|
|
|
|
for (i = 0, ok = 0; i < cnt; i++) {
|
|
h->last = smps[i];
|
|
|
|
if (h->prev) {
|
|
dist = h->last->sequence - (int32_t) h->prev->sequence;
|
|
if (dist <= 0) {
|
|
p->dropped++;
|
|
warn("Dropped sample: dist = %d, i = %d", dist, i);
|
|
}
|
|
else {
|
|
struct sample *tmp;
|
|
|
|
tmp = smps[i];
|
|
smps[i] = smps[ok];
|
|
smps[ok++] = tmp;
|
|
}
|
|
|
|
/* To discard the first X samples in 'smps[]' we must
|
|
* shift them to the end of the 'smps[]' array.
|
|
* In case the hook returns a number 'ok' which is smaller than 'cnt',
|
|
* only the first 'ok' samples in 'smps[]' are accepted and further processed.
|
|
*/
|
|
}
|
|
else {
|
|
struct sample *tmp;
|
|
|
|
tmp = smps[i];
|
|
smps[i] = smps[ok];
|
|
smps[ok++] = tmp;
|
|
}
|
|
|
|
h->prev = h->last;
|
|
}
|
|
|
|
return ok;
|
|
}
|