mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
improved mapping module to support node name prefixes
This commit is contained in:
parent
f994e996a0
commit
50b3529c90
4 changed files with 147 additions and 71 deletions
|
@ -36,7 +36,7 @@ struct sample;
|
|||
struct list;
|
||||
|
||||
struct mapping_entry {
|
||||
struct node *source; /**< Unused for now. */
|
||||
struct node *node;
|
||||
int length;
|
||||
|
||||
enum {
|
||||
|
@ -71,7 +71,8 @@ struct mapping_entry {
|
|||
struct {
|
||||
enum timestamp_type {
|
||||
MAPPING_TIMESTAMP_ORIGIN,
|
||||
MAPPING_TIMESTAMP_RECEIVED
|
||||
MAPPING_TIMESTAMP_RECEIVED,
|
||||
MAPPING_TIMESTAMP_SENT
|
||||
} id;
|
||||
} timestamp;
|
||||
};
|
||||
|
@ -87,7 +88,7 @@ struct mapping {
|
|||
|
||||
int mapping_init(struct mapping *m);
|
||||
|
||||
int mapping_parse(struct mapping *m, json_t *cfg);
|
||||
int mapping_parse(struct mapping *m, json_t *cfg, struct list *nodes);
|
||||
|
||||
int mapping_check(struct mapping *m);
|
||||
|
||||
|
@ -95,6 +96,6 @@ int mapping_destroy(struct mapping *m);
|
|||
|
||||
int mapping_remap(struct mapping *m, struct sample *orig, struct sample *remapped, struct stats *s);
|
||||
|
||||
int mapping_entry_parse(struct mapping_entry *e, json_t *cfg);
|
||||
int mapping_entry_parse(struct mapping_entry *e, json_t *cfg, struct list *nodes);
|
||||
|
||||
int mapping_entry_parse_str(struct mapping_entry *e, const char *str);
|
||||
int mapping_entry_parse_str(struct mapping_entry *e, const char *str, struct list *nodes);
|
||||
|
|
|
@ -64,7 +64,7 @@ static int map_parse(struct hook *h, json_t *cfg)
|
|||
if (ret)
|
||||
jerror(&err, "Failed to parse configuration of hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
ret = mapping_parse(&p->mapping, cfg_mapping);
|
||||
ret = mapping_parse(&p->mapping, cfg_mapping, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
112
lib/mapping.c
112
lib/mapping.c
|
@ -28,18 +28,35 @@
|
|||
#include "list.h"
|
||||
#include "utils.h"
|
||||
|
||||
int mapping_entry_parse_str(struct mapping_entry *e, const char *str)
|
||||
int mapping_entry_parse_str(struct mapping_entry *e, const char *str, struct list *nodes)
|
||||
{
|
||||
int id;
|
||||
char *cpy, *type, *field, *subfield, *end;
|
||||
char *cpy, *node, *type, *field, *subfield, *end;
|
||||
|
||||
cpy = strdup(str);
|
||||
if (!cpy)
|
||||
return -1;
|
||||
|
||||
type = strtok(cpy, ".[");
|
||||
if (!type)
|
||||
goto invalid_format;
|
||||
|
||||
if (nodes) {
|
||||
node = strtok(cpy, ".");
|
||||
if (!node)
|
||||
goto invalid_format;
|
||||
|
||||
e->node = list_lookup(nodes, node);
|
||||
if (!e->node)
|
||||
goto invalid_format;
|
||||
|
||||
type = strtok(NULL, ".[");
|
||||
if (!type)
|
||||
type = "data";
|
||||
}
|
||||
else {
|
||||
e->node = NULL;
|
||||
|
||||
type = strtok(cpy, ".[");
|
||||
if (!type)
|
||||
goto invalid_format;
|
||||
}
|
||||
|
||||
if (!strcmp(type, "stats")) {
|
||||
e->type = MAPPING_TYPE_STATS;
|
||||
|
@ -53,10 +70,6 @@ int mapping_entry_parse_str(struct mapping_entry *e, const char *str)
|
|||
if (!subfield)
|
||||
goto invalid_format;
|
||||
|
||||
end = strtok(NULL, ".");
|
||||
if (end)
|
||||
goto invalid_format;
|
||||
|
||||
id = stats_lookup_id(field);
|
||||
if (id < 0)
|
||||
goto invalid_format;
|
||||
|
@ -88,10 +101,6 @@ int mapping_entry_parse_str(struct mapping_entry *e, const char *str)
|
|||
if (!field)
|
||||
goto invalid_format;
|
||||
|
||||
end = strtok(NULL, ".");
|
||||
if (end)
|
||||
goto invalid_format;
|
||||
|
||||
if (!strcmp(field, "sequence"))
|
||||
e->header.id = MAPPING_HEADER_SEQUENCE;
|
||||
else if (!strcmp(field, "length"))
|
||||
|
@ -107,70 +116,75 @@ int mapping_entry_parse_str(struct mapping_entry *e, const char *str)
|
|||
if (!field)
|
||||
goto invalid_format;
|
||||
|
||||
end = strtok(NULL, ".");
|
||||
if (end)
|
||||
goto invalid_format;
|
||||
|
||||
if (!strcmp(field, "origin"))
|
||||
e->timestamp.id = MAPPING_TIMESTAMP_ORIGIN;
|
||||
else if (!strcmp(field, "received"))
|
||||
e->timestamp.id = MAPPING_TIMESTAMP_RECEIVED;
|
||||
else if (!strcmp(field, "sent"))
|
||||
e->timestamp.id = MAPPING_TIMESTAMP_SENT;
|
||||
else
|
||||
goto invalid_format;
|
||||
}
|
||||
else if (!strcmp(type, "data")) {
|
||||
char *first_str, *last_str, *endptr;
|
||||
int first, last;
|
||||
|
||||
e->type = MAPPING_TYPE_DATA;
|
||||
|
||||
first_str = strtok(NULL, "-]");
|
||||
if (!first_str)
|
||||
goto invalid_format;
|
||||
if (first_str) {
|
||||
int first, last;
|
||||
|
||||
last_str = strtok(NULL, "]");
|
||||
if (!last_str)
|
||||
last_str = first_str; /* single element: data[5] => data[5-5] */
|
||||
last_str = strtok(NULL, "]");
|
||||
if (!last_str)
|
||||
last_str = first_str; /* single element: data[5] => data[5-5] */
|
||||
|
||||
end = strtok(NULL, ".");
|
||||
if (end)
|
||||
goto invalid_format;
|
||||
first = strtoul(first_str, &endptr, 10);
|
||||
if (endptr != first_str + strlen(first_str))
|
||||
goto invalid_format;
|
||||
|
||||
first = strtoul(first_str, &endptr, 10);
|
||||
if (endptr != first_str + strlen(first_str))
|
||||
goto invalid_format;
|
||||
last = strtoul(last_str, &endptr, 10);
|
||||
if (endptr != last_str + strlen(last_str))
|
||||
goto invalid_format;
|
||||
|
||||
last = strtoul(last_str, &endptr, 10);
|
||||
if (endptr != last_str + strlen(last_str))
|
||||
goto invalid_format;
|
||||
if (last < first)
|
||||
goto invalid_format;
|
||||
|
||||
if (last < first)
|
||||
goto invalid_format;
|
||||
|
||||
e->data.offset = first;
|
||||
e->length = last - first + 1;
|
||||
e->data.offset = first;
|
||||
e->length = last - first + 1;
|
||||
}
|
||||
else {
|
||||
e->data.offset = 0;
|
||||
e->length = 0; /* Length in unkown.. we will take all values */
|
||||
}
|
||||
}
|
||||
else
|
||||
goto invalid_format;
|
||||
|
||||
/* Check that there is no garbage at the end */
|
||||
end = strtok(NULL, "");
|
||||
if (end)
|
||||
goto invalid_format;
|
||||
|
||||
free(cpy);
|
||||
|
||||
return 0;
|
||||
|
||||
invalid_format:
|
||||
|
||||
free(cpy);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int mapping_entry_parse(struct mapping_entry *e, json_t *cfg)
|
||||
int mapping_entry_parse(struct mapping_entry *e, json_t *j, struct list *nodes)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = json_string_value(cfg);
|
||||
str = json_string_value(j);
|
||||
if (!str)
|
||||
return -1;
|
||||
|
||||
return mapping_entry_parse_str(e, str);
|
||||
return mapping_entry_parse_str(e, str, nodes);
|
||||
}
|
||||
|
||||
int mapping_init(struct mapping *m)
|
||||
|
@ -195,23 +209,29 @@ int mapping_destroy(struct mapping *m)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int mapping_parse(struct mapping *m, json_t *cfg)
|
||||
int mapping_parse(struct mapping *m, json_t *j, struct list *nodes)
|
||||
{
|
||||
int ret;
|
||||
|
||||
assert(m->state == STATE_INITIALIZED);
|
||||
|
||||
if (!json_is_array(cfg))
|
||||
json_t *json_entry;
|
||||
json_t *json_mapping;
|
||||
|
||||
if (json_is_string(j)) {
|
||||
json_mapping = json_array();
|
||||
json_array_append(json_mapping, j);
|
||||
}
|
||||
else if (!json_is_array(j))
|
||||
return -1;
|
||||
|
||||
m->real_length = 0;
|
||||
|
||||
size_t index;
|
||||
json_t *cfg_entry;
|
||||
json_array_foreach(cfg, index, cfg_entry) {
|
||||
json_array_foreach(j, index, json_entry) {
|
||||
struct mapping_entry *e = alloc(sizeof(struct mapping_entry));
|
||||
|
||||
ret = mapping_entry_parse(e, cfg_entry);
|
||||
ret = mapping_entry_parse(e, json_entry, nodes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -23,74 +23,129 @@
|
|||
#include <criterion/criterion.h>
|
||||
|
||||
#include "mapping.h"
|
||||
#include "node.h"
|
||||
#include "list.h"
|
||||
|
||||
Test(mapping, parse_nodes)
|
||||
{
|
||||
int ret;
|
||||
struct mapping_entry m;
|
||||
struct list n;
|
||||
|
||||
struct node n1 = { .name = "apple" };
|
||||
struct node n2 = { .name = "cherry" };
|
||||
struct node n3 = { .name = "carrot" };
|
||||
|
||||
list_init(&n);
|
||||
|
||||
list_push(&n, &n1);
|
||||
list_push(&n, &n2);
|
||||
list_push(&n, &n3);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "apple.ts.origin", &n);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.node, &n1);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_TIMESTAMP);
|
||||
cr_assert_eq(m.timestamp.id, MAPPING_TIMESTAMP_ORIGIN);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "cherry.stats.owd.mean", &n);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.node, &n2);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_STATS);
|
||||
cr_assert_eq(m.stats.id, STATS_OWD);
|
||||
cr_assert_eq(m.stats.type, MAPPING_STATS_TYPE_MEAN);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "carrot.data[1-2]", &n);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.node, &n3);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_DATA);
|
||||
cr_assert_eq(m.data.offset, 1);
|
||||
cr_assert_eq(m.length, 2);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "carrot", &n);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.node, &n3);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_DATA);
|
||||
cr_assert_eq(m.data.offset, 0);
|
||||
cr_assert_eq(m.length, 0);
|
||||
|
||||
ret = list_destroy(&n, NULL, false);
|
||||
cr_assert_eq(ret, 0);
|
||||
}
|
||||
|
||||
Test(mapping, parse)
|
||||
{
|
||||
int ret;
|
||||
struct mapping_entry m;
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "ts.origin");
|
||||
ret = mapping_entry_parse_str(&m, "ts.origin", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_TIMESTAMP);
|
||||
cr_assert_eq(m.timestamp.id, MAPPING_TIMESTAMP_ORIGIN);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "hdr.sequence");
|
||||
ret = mapping_entry_parse_str(&m, "hdr.sequence", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_HEADER);
|
||||
cr_assert_eq(m.header.id, MAPPING_HEADER_SEQUENCE);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "stats.owd.mean");
|
||||
ret = mapping_entry_parse_str(&m, "stats.owd.mean", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_STATS);
|
||||
cr_assert_eq(m.stats.id, STATS_OWD);
|
||||
cr_assert_eq(m.stats.type, MAPPING_STATS_TYPE_MEAN);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data[1-2]");
|
||||
ret = mapping_entry_parse_str(&m, "data[1-2]", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_DATA);
|
||||
cr_assert_eq(m.data.offset, 1);
|
||||
cr_assert_eq(m.length, 2);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data[5-5]");
|
||||
ret = mapping_entry_parse_str(&m, "data[5-5]", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_DATA);
|
||||
cr_assert_eq(m.data.offset, 5);
|
||||
cr_assert_eq(m.length, 1);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data[22]");
|
||||
ret = mapping_entry_parse_str(&m, "data[22]", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_DATA);
|
||||
cr_assert_eq(m.data.offset, 22);
|
||||
cr_assert_eq(m.length, 1);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_DATA);
|
||||
cr_assert_eq(m.data.offset, 0);
|
||||
cr_assert_eq(m.length, 0);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data[]", NULL);
|
||||
cr_assert_eq(ret, 0);
|
||||
cr_assert_eq(m.type, MAPPING_TYPE_DATA);
|
||||
cr_assert_eq(m.data.offset, 0);
|
||||
cr_assert_eq(m.length, 0);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data[]");
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data[1.1-2f]");
|
||||
ret = mapping_entry_parse_str(&m, "data[1.1-2f]", NULL);
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
/* Missing parts */
|
||||
ret = mapping_entry_parse_str(&m, "stats.owd");
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data");
|
||||
ret = mapping_entry_parse_str(&m, "stats.owd", NULL);
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
/* This a type */
|
||||
ret = mapping_entry_parse_str(&m, "hdr.sequences");
|
||||
ret = mapping_entry_parse_str(&m, "hdr.sequences", NULL);
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
/* Check for superfluous chars at the end */
|
||||
ret = mapping_entry_parse_str(&m, "stats.ts.origin.bla");
|
||||
ret = mapping_entry_parse_str(&m, "stats.ts.origin.bla", NULL);
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "stats.ts.origin.");
|
||||
ret = mapping_entry_parse_str(&m, "stats.ts.origin.", NULL);
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
ret = mapping_entry_parse_str(&m, "data[1-2]bla");
|
||||
ret = mapping_entry_parse_str(&m, "data[1-2]bla", NULL);
|
||||
cr_assert_neq(ret, 0);
|
||||
|
||||
/* Negative length of chunk */
|
||||
ret = mapping_entry_parse_str(&m, "data[5-3]");
|
||||
ret = mapping_entry_parse_str(&m, "data[5-3]", NULL);
|
||||
cr_assert_eq(ret, -1);
|
||||
}
|
Loading…
Add table
Reference in a new issue