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

use new NodeList and PathList in SuperNode

This commit is contained in:
Steffen Vogel 2021-06-21 16:12:47 -04:00
parent 00a9e92b0a
commit 2d1e8d17ce
19 changed files with 259 additions and 122 deletions

View file

@ -27,6 +27,7 @@
#include <villas/stats.hpp>
#include <villas/common.hpp>
#include <villas/node_list.hpp>
#define RE_MAPPING_INDEX "[a-zA-Z0-9_]+"
#define RE_MAPPING_RANGE "(" RE_MAPPING_INDEX ")(?:-(" RE_MAPPING_INDEX "))?"
@ -99,7 +100,7 @@ struct mapping_entry {
};
};
int mapping_entry_prepare(struct mapping_entry *me, struct vlist *nodes);
int mapping_entry_prepare(struct mapping_entry *me, villas::node::NodeList &nodes);
int mapping_entry_update(const struct mapping_entry *me, struct sample *remapped, const struct sample *original);
@ -115,6 +116,6 @@ int mapping_entry_to_str(const struct mapping_entry *me, unsigned index, char **
int mapping_list_parse(struct vlist *ml, json_t *json);
int mapping_list_prepare(struct vlist *ml, struct vlist *nodes);
int mapping_list_prepare(struct vlist *ml, villas::node::NodeList &nodes);
int mapping_list_remap(const struct vlist *ml, struct sample *remapped, const struct sample *original);

View file

@ -34,6 +34,7 @@
#include <uuid/uuid.h>
#include <villas/node_type.h>
#include <villas/node_list.hpp>
#include <villas/node_direction.h>
#include <villas/sample.h>
#include <villas/list.h>
@ -121,7 +122,7 @@ int node_parse(struct vnode *n, json_t *json, const uuid_t sn_uuid);
* @param nodes The nodes will be added to this list.
* @param all This list contains all valid nodes.
*/
int node_list_parse(struct vlist *list, json_t *json, struct vlist *all);
int node_list_parse(struct vlist *list, json_t *json, villas::node::NodeList &all);
/** Parse the list of signal definitions. */
int node_parse_signals(struct vlist *list, json_t *json);

View file

@ -0,0 +1,48 @@
/** Node list
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2021, 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/>.
*/
#pragma once
#include <uuid/uuid.h>
#include <list>
#include <string>
/* Forward declarations */
struct vnode;
namespace villas {
namespace node {
class NodeList : public std::list<struct vnode *> {
public:
/** Lookup a node from the list based on its name */
struct vnode * lookup(const std::string &name);
/** Lookup a node from the list based on its UUID */
struct vnode * lookup(const uuid_t &uuid);
};
} /* namespace node */
} /* namespace villas */

View file

@ -28,7 +28,7 @@
#include <jansson.h>
#include <villas/list.h>
#include <villas/node_list.hpp>
#include <villas/common.hpp>
#include <villas/memory.h>
#include <villas/log.hpp>
@ -58,7 +58,7 @@ struct vnode_type {
enum State state; /**< State of this node-type. */
struct vlist instances; /**< A list of all existing nodes of this type. */
villas::node::NodeList instances; /**< A list of all existing nodes of this type. */
size_t size; /**< Size of private data bock. @see node::_vd */
size_t pool_size;

View file

@ -41,6 +41,7 @@
#include <villas/common.hpp>
#include <villas/mapping.h>
#include <villas/task.hpp>
#include <villas/node_list.hpp>
#include <villas/log.hpp>
@ -104,7 +105,7 @@ struct vpath {
/** Initialize internal data structures. */
int path_init(struct vpath *p) __attribute__ ((warn_unused_result));
int path_prepare(struct vpath *p, struct vlist *nodes);
int path_prepare(struct vpath *p, villas::node::NodeList &nodes);
/** Check if path configuration is proper. */
void path_check(struct vpath *p);
@ -158,9 +159,9 @@ int path_reverse(struct vpath *p, struct vpath *r);
* @retval 0 Success. Everything went well.
* @retval <0 Error. Something went wrong.
*/
int path_parse(struct vpath *p, json_t *json, struct vlist *nodes, const uuid_t sn_uuid);
int path_parse(struct vpath *p, json_t *json, villas::node::NodeList &nodes, const uuid_t sn_uuid);
void path_parse_mask(struct vpath *p, json_t *json_mask, struct vlist *nodes);
void path_parse_mask(struct vpath *p, json_t *json_mask, villas::node::NodeList &nodes);
bool path_is_simple(const struct vpath *p);

View file

@ -0,0 +1,45 @@
/** Node list
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2021, 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/>.
*/
#pragma once
#include <uuid/uuid.h>
#include <list>
#include <string>
/* Forward declarations */
struct vpath;
namespace villas {
namespace node {
class PathList : public std::list<struct vpath *> {
public:
/** Lookup a path from the list based on its UUID */
struct vpath * lookup(const uuid_t &uuid);
};
} /* namespace node */
} /* namespace villas */

View file

@ -33,12 +33,13 @@ extern "C" {
#include <fstream>
#include <villas/list.h>
#include <villas/api.hpp>
#include <villas/web.hpp>
#include <villas/log.hpp>
#include <villas/config.hpp>
#include <villas/node.h>
#include <villas/node_list.hpp>
#include <villas/path_list.hpp>
#include <villas/task.hpp>
#include <villas/common.hpp>
#include <villas/kernel/if.hpp>
@ -59,8 +60,8 @@ protected:
Logger logger;
struct vlist nodes;
struct vlist paths;
NodeList nodes;
PathList paths;
std::list<kernel::Interface *> interfaces;
#ifdef WITH_API
@ -137,17 +138,17 @@ public:
struct vnode * getNode(const std::string &name)
{
return vlist_lookup_name<struct vnode>(&nodes, name);
return nodes.lookup(name);
}
struct vlist * getNodes()
NodeList & getNodes()
{
return &nodes;
return nodes;
}
struct vlist * getPaths()
PathList & getPaths()
{
return &paths;
return paths;
}
std::list<kernel::Interface *> & getInterfaces()

View file

@ -57,9 +57,11 @@ set(LIB_SRC
node_direction.cpp
node_type.cpp
node.cpp
node_list.cpp
path_destination.cpp
path_source.cpp
path.cpp
path_list.cpp
pool.cpp
queue_signalled.cpp
queue.cpp

View file

@ -30,19 +30,19 @@ NodeRequest::prepare()
{
int ret;
auto *nodes = session->getSuperNode()->getNodes();
auto &nodes = session->getSuperNode()->getNodes();
uuid_t uuid;
ret = uuid_parse(matches[1].c_str(), uuid);
if (ret) {
node = vlist_lookup_name<struct vnode>(nodes, matches[1]);
node = nodes.lookup(matches[1]);
if (!node)
throw BadRequest("Unknown node", "{ s: s }",
"node", matches[1].c_str()
);
}
else {
node = vlist_lookup_uuid<struct vnode>(nodes, uuid);
node = nodes.lookup(uuid);
if (!node)
throw BadRequest("No node found with with matching UUID", "{ s: s }",
"uuid", matches[1].c_str()

View file

@ -38,8 +38,8 @@ PathRequest::prepare()
"uuid", matches[1].c_str()
);
auto *paths = session->getSuperNode()->getPaths();
path = vlist_lookup_uuid<struct vpath>(paths, uuid);
auto paths = session->getSuperNode()->getPaths();
path = paths.lookup(uuid);
if (!path)
throw BadRequest("No path found with with matching UUID", "{ s: s }",
"uuid", matches[1].c_str()

View file

@ -50,13 +50,8 @@ public:
json_t *json_nodes = json_array();
struct vlist *nodes = session->getSuperNode()->getNodes();
for (size_t i = 0; i < vlist_length(nodes); i++) {
struct vnode *n = (struct vnode *) vlist_at(nodes, i);
for (auto *n : session->getSuperNode()->getNodes())
json_array_append_new(json_nodes, node_to_json(n));
}
return new JsonResponse(session, HTTP_STATUS_OK, json_nodes);
}

View file

@ -51,13 +51,8 @@ public:
json_t *json_paths = json_array();
struct vlist *paths = session->getSuperNode()->getPaths();
for (size_t i = 0; i < vlist_length(paths); i++) {
struct vpath *p = (struct vpath *) vlist_at(paths, i);
for (auto *p : session->getSuperNode()->getPaths())
json_array_append_new(json_paths, path_to_json(p));
}
return new JsonResponse(session, HTTP_STATUS_OK, json_paths);
}

View file

@ -25,7 +25,6 @@
#include <libwebsockets.h>
#include <villas/web.hpp>
#include <villas/plugin.h>
#include <villas/memory.h>
#include <villas/api/session.hpp>

View file

@ -32,6 +32,7 @@
#include <villas/signal.h>
using namespace villas;
using namespace villas::node;
using namespace villas::utils;
int mapping_entry_parse_str(struct mapping_entry *me, const std::string &str)
@ -267,10 +268,10 @@ int mapping_list_remap(const struct vlist *ml, struct sample *remapped, const st
return 0;
}
int mapping_entry_prepare(struct mapping_entry *me, struct vlist *nodes)
int mapping_entry_prepare(struct mapping_entry *me, NodeList &nodes)
{
if (me->node_name && me->node == nullptr) {
me->node = vlist_lookup_name<struct vnode>(nodes, me->node_name);
me->node = nodes.lookup(me->node_name);
if (!me->node)
throw RuntimeError("Invalid node name in mapping: {}", me->node_name);
}
@ -327,7 +328,7 @@ end:
return 0;
}
int mapping_list_prepare(struct vlist *ml, struct vlist *nodes)
int mapping_list_prepare(struct vlist *ml, NodeList &nodes)
{
int ret;

View file

@ -30,10 +30,10 @@
#include <villas/hook_list.hpp>
#include <villas/sample.h>
#include <villas/node.h>
#include <villas/node_list.hpp>
#include <villas/path.h>
#include <villas/utils.hpp>
#include <villas/colors.hpp>
#include <villas/plugin.h>
#include <villas/mapping.h>
#include <villas/timing.h>
#include <villas/signal.h>
@ -47,6 +47,7 @@
#endif /* WITH_NETEM */
using namespace villas;
using namespace villas::node;
using namespace villas::utils;
int node_init(struct vnode *n, struct vnode_type *vt)
@ -107,7 +108,7 @@ int node_init(struct vnode *n, struct vnode_type *vt)
n->state = State::INITIALIZED;
vlist_push(&vt->instances, n);
vt->instances.push_back(n);
return 0;
}
@ -415,7 +416,7 @@ int node_destroy(struct vnode *n)
return ret;
}
vlist_remove_all(&node_type(n)->instances, n);
node_type(n)->instances.remove(n);
if (n->_vd)
delete[] (char *) n->_vd;
@ -598,7 +599,7 @@ struct memory_type * node_memory_type(struct vnode *n)
return node_type(n)->memory_type ? node_type(n)->memory_type(n, memory_default) : memory_default;
}
int node_list_parse(struct vlist *list, json_t *json, struct vlist *all)
int node_list_parse(struct vlist *list, json_t *json, NodeList &all)
{
struct vnode *node;
const char *str;
@ -612,7 +613,7 @@ int node_list_parse(struct vlist *list, json_t *json, struct vlist *all)
switch (json_typeof(json)) {
case JSON_STRING:
str = json_string_value(json);
node = vlist_lookup_name<struct vnode>(all, str);
node = all.lookup(str);
if (!node)
goto invalid2;
@ -624,7 +625,8 @@ int node_list_parse(struct vlist *list, json_t *json, struct vlist *all)
if (!json_is_string(elm))
goto invalid;
node = vlist_lookup_name<struct vnode>(all, json_string_value(elm));
str = json_string_value(elm);
node = all.lookup(str);
if (!node)
goto invalid;
@ -644,11 +646,8 @@ invalid:
return -1;
invalid2:
for (size_t i = 0; i < vlist_length(all); i++) {
struct vnode *n = (struct vnode *) vlist_at(all, i);
for (auto *n : all)
strcatf(&allstr, " %s", node_name_short(n));
}
throw RuntimeError("Unknown node {}. Choose of one of: {}", str, allstr);

46
lib/node_list.cpp Normal file
View file

@ -0,0 +1,46 @@
/** Node list
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2021, 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/node_list.hpp>
#include <villas/node.h>
using namespace villas::node;
struct vnode * NodeList::lookup(const uuid_t &uuid)
{
for (auto *n : *this) {
if (!uuid_compare(uuid, n->uuid))
return n;
}
return nullptr;
}
struct vnode * NodeList::lookup(const std::string &name)
{
for (auto *n : *this) {
if (name == n->name)
return n;
}
return nullptr;
}

View file

@ -40,7 +40,6 @@
#include <villas/queue.h>
#include <villas/hook.hpp>
#include <villas/hook_list.hpp>
#include <villas/plugin.h>
#include <villas/memory.h>
#include <villas/node.h>
#include <villas/signal.h>
@ -235,7 +234,7 @@ static int path_prepare_poll(struct vpath *p)
return 0;
}
int path_prepare(struct vpath *p, struct vlist *nodes)
int path_prepare(struct vpath *p, NodeList &nodes)
{
int ret;
unsigned pool_size;
@ -283,7 +282,7 @@ int path_prepare(struct vpath *p, struct vlist *nodes)
return ret;
if (ps->type == PathSourceType::SECONDARY) {
vlist_push(nodes, ps->node);
nodes.push_back(ps->node);
vlist_push(&ps->node->sources, ps);
}
@ -388,7 +387,7 @@ int path_prepare(struct vpath *p, struct vlist *nodes)
return 0;
}
int path_parse(struct vpath *p, json_t *json, struct vlist *nodes, const uuid_t sn_uuid)
int path_parse(struct vpath *p, json_t *json, NodeList &nodes, const uuid_t sn_uuid)
{
int ret;
@ -496,7 +495,7 @@ int path_parse(struct vpath *p, json_t *json, struct vlist *nodes, const uuid_t
return 0;
}
void path_parse_mask(struct vpath *p, json_t *json_mask, struct vlist *nodes)
void path_parse_mask(struct vpath *p, json_t *json_mask, villas::node::NodeList &nodes)
{
json_t *json_entry;
size_t i;
@ -512,7 +511,7 @@ void path_parse_mask(struct vpath *p, json_t *json_mask, struct vlist *nodes)
if (!name)
throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' setting must be a list of node names");
node = vlist_lookup_name<struct vnode>(nodes, name);
node = nodes.lookup(name);
if (!node)
throw ConfigError(json_mask, "node-config-path-mask", "The 'mask' entry '{}' is not a valid node name", name);

36
lib/path_list.cpp Normal file
View file

@ -0,0 +1,36 @@
/** Path list
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2021, 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/path_list.hpp>
#include <villas/path.h>
using namespace villas::node;
struct vpath * PathList::lookup(const uuid_t &uuid)
{
for (auto *p : *this) {
if (!uuid_compare(uuid, p->uuid))
return p;
}
return nullptr;
}

View file

@ -20,6 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <algorithm>
#include <cstdlib>
#include <cstring>
@ -31,7 +32,6 @@
#include <villas/utils.hpp>
#include <villas/list.h>
#include <villas/hook_list.hpp>
#include <villas/plugin.h>
#include <villas/memory.h>
#include <villas/config_helper.hpp>
#include <villas/log.hpp>
@ -80,14 +80,6 @@ SuperNode::SuperNode() :
/* Default UUID is derived from hostname */
uuid_generate_from_str(uuid, hname);
ret = vlist_init(&nodes);
if (ret)
throw RuntimeError("Failed to initialize list");
ret = vlist_init(&paths);
if (ret)
throw RuntimeError("Failed to initialize list");
#ifdef WITH_NETEM
kernel::nl::init(); /* Fill link cache */
#endif /* WITH_NETEM */
@ -190,7 +182,7 @@ void SuperNode::parse(json_t *root)
json_object_del(json_node, "name");
vlist_push(&nodes, n);
nodes.push_back(n);
}
}
@ -210,11 +202,11 @@ parse: auto *p = new vpath;
if (ret)
throw RuntimeError("Failed to initialize path");
ret = path_parse(p, json_path, &nodes, uuid);
ret = path_parse(p, json_path, nodes, uuid);
if (ret)
throw RuntimeError("Failed to parse path");
vlist_push(&paths, p);
paths.push_back(p);
if (p->reverse) {
/* Only simple paths can be reversed */
@ -249,19 +241,14 @@ void SuperNode::check()
assert(state == State::INITIALIZED || state == State::PARSED || state == State::CHECKED);
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
ret = node_check(n);
if (ret)
throw RuntimeError("Invalid configuration for node {}", node_name(n));
}
for (size_t i = 0; i < vlist_length(&paths); i++) {
auto *p = (struct vpath *) vlist_at(&paths, i);
for (auto *p : paths)
path_check(p);
}
state = State::CHECKED;
}
@ -270,9 +257,7 @@ void SuperNode::startNodeTypes()
{
int ret;
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
ret = node_type_start(n->_vt, this);
if (ret)
throw RuntimeError("Failed to start node-type: {}", node_type_name(n->_vt));
@ -296,9 +281,7 @@ void SuperNode::startNodes()
{
int ret;
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
if (!node_is_enabled(n))
continue;
@ -312,9 +295,7 @@ void SuperNode::startPaths()
{
int ret;
for (size_t i = 0; i < vlist_length(&paths); i++) {
auto *p = (struct vpath *) vlist_at(&paths, i);
for (auto *p : paths) {
if (!path_is_enabled(p))
continue;
@ -328,9 +309,7 @@ void SuperNode::prepareNodes()
{
int ret;
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
if (!node_is_enabled(n))
continue;
@ -344,13 +323,11 @@ void SuperNode::preparePaths()
{
int ret;
for (size_t i = 0; i < vlist_length(&paths); i++) {
auto *p = (struct vpath *) vlist_at(&paths, i);
for (auto *p : paths) {
if (!path_is_enabled(p))
continue;
ret = path_prepare(p, &nodes);
ret = path_prepare(p, nodes);
if (ret)
throw RuntimeError("Failed to prepare path: {}", path_name(p));
}
@ -371,8 +348,7 @@ void SuperNode::prepare()
prepareNodes();
preparePaths();
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
if (vlist_length(&n->sources) == 0 &&
vlist_length(&n->destinations) == 0) {
logger->info("Node {} is not used by any path. Disabling...", node_name(n));
@ -412,9 +388,7 @@ void SuperNode::stopPaths()
{
int ret;
for (size_t i = 0; i < vlist_length(&paths); i++) {
auto *p = (struct vpath *) vlist_at(&paths, i);
for (auto *p : paths) {
ret = path_stop(p);
if (ret)
throw RuntimeError("Failed to stop path: {}", path_name(p));
@ -425,9 +399,7 @@ void SuperNode::stopNodes()
{
int ret;
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
ret = node_stop(n);
if (ret)
throw RuntimeError("Failed to stop node: {}", node_name(n));
@ -438,14 +410,10 @@ void SuperNode::stopNodeTypes()
{
int ret;
for (size_t i = 0; i < vlist_length(&plugins); i++) {
auto *p = (struct plugin *) vlist_at(&plugins, i);
if (p->type == PluginType::NODE) {
ret = node_type_stop(&p->node);
if (ret)
throw RuntimeError("Failed to stop node-type: {}", node_type_name(&p->node));
}
for (auto *vt : *node_types) {
ret = node_type_stop(vt);
if (ret)
throw RuntimeError("Failed to stop node-type: {}", node_type_name(vt));
}
}
@ -495,21 +463,26 @@ void SuperNode::run()
SuperNode::~SuperNode()
{
int ret __attribute__((unused));
assert(state != State::STARTED);
ret = vlist_destroy(&paths, (dtor_cb_t) path_destroy, true);
ret = vlist_destroy(&nodes, (dtor_cb_t) node_destroy, true);
int ret __attribute__((unused));
for (auto *p : paths) {
ret = path_destroy(p);
delete p;
}
for (auto *n : nodes) {
ret = node_destroy(n);
delete n;
}
}
int SuperNode::periodic()
{
int started = 0;
for (size_t i = 0; i < vlist_length(&paths); i++) {
auto *p = (struct vpath *) vlist_at(&paths, i);
for (auto *p : paths) {
if (p->state == State::STARTED) {
started++;
@ -519,9 +492,7 @@ int SuperNode::periodic()
}
}
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
if (n->state == State::STARTED) {
#ifdef WITH_HOOKS
hook_list_periodic(&n->in.hooks);
@ -564,24 +535,21 @@ graph_t * SuperNode::getGraph()
uuid_string_t uuid_str;
for (size_t i = 0; i < vlist_length(&nodes); i++) {
auto *n = (struct vnode *) vlist_at(&nodes, i);
for (auto *n : nodes) {
nodeMap[n] = agnode(g, (char *) node_name_short(n), 1);
uuid_unparse(n->uuid, uuid_str);
set_attr(nodeMap[n], "shape", "ellipse");
set_attr(nodeMap[n], "tooltip", fmt::format("type={}, uuid={}", plugin_name(node_type(n)), uuid_str));
set_attr(nodeMap[n], "tooltip", fmt::format("type={}, uuid={}", node_type_name((node_type(n))), uuid_str));
// set_attr(nodeMap[n], "fixedsize", "true");
// set_attr(nodeMap[n], "width", "0.15");
// set_attr(nodeMap[n], "height", "0.15");
}
for (size_t i = 0; i < vlist_length(&paths); i++) {
auto *p = (struct vpath *) vlist_at(&paths, i);
auto name = fmt::format("path_{}", i);
unsigned i = 0;
for (auto *p : paths) {
auto name = fmt::format("path_{}", i++);
m = agnode(g, (char *) name.c_str(), 1);