2014-07-14 11:49:44 +00:00
|
|
|
/** Nodes.
|
2014-06-05 09:34:29 +00:00
|
|
|
*
|
|
|
|
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
|
2015-06-02 21:53:04 +02:00
|
|
|
* @copyright 2014-2015, Institute for Automation of Complex Power Systems, EONERC
|
|
|
|
* This file is part of S2SS. All Rights Reserved. Proprietary and confidential.
|
2015-08-07 01:11:43 +02:00
|
|
|
* Unauthorized copying of this file, via any medium is strictly prohibited.
|
2015-06-02 21:53:04 +02:00
|
|
|
*********************************************************************************/
|
2014-06-05 09:34:29 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
2014-12-05 12:39:52 +01:00
|
|
|
#include "node.h"
|
2014-06-05 09:34:56 +00:00
|
|
|
#include "cfg.h"
|
2014-06-05 09:34:29 +00:00
|
|
|
#include "utils.h"
|
|
|
|
|
2014-12-05 12:39:52 +01:00
|
|
|
/** Vtable for virtual node sub types */
|
2015-09-19 15:26:30 +02:00
|
|
|
struct list node_types = LIST_INIT(NULL);
|
2014-12-05 12:39:52 +01:00
|
|
|
|
2015-11-23 16:42:43 +01:00
|
|
|
int node_parse(struct node *n, config_setting_t *cfg)
|
|
|
|
{
|
|
|
|
return n->_vt->parse ? n->_vt->parse(n, cfg) : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int node_read(struct node *n, struct msg *p, int ps, int f, int c)
|
|
|
|
{
|
|
|
|
return n->_vt->read ? n->_vt->read(n, p, ps, f, c) : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int node_write(struct node *n, struct msg *p, int ps, int f, int c)
|
|
|
|
{
|
|
|
|
return n->_vt->write ? n->_vt->write(n, p, ps, f, c) : -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int node_open(struct node *n)
|
|
|
|
{
|
|
|
|
return n->_vt->open ? n->_vt->open(n) : -1;
|
|
|
|
}
|
|
|
|
int node_close(struct node *n)
|
|
|
|
{
|
|
|
|
return n->_vt->close ? n->_vt->close(n) : -1;
|
|
|
|
}
|
|
|
|
|
2015-05-06 11:48:30 +02:00
|
|
|
int node_init(int argc, char *argv[], struct settings *set)
|
2015-03-31 13:54:04 +02:00
|
|
|
{ INDENT
|
2015-10-09 12:50:35 +02:00
|
|
|
list_foreach(const struct node_type *vt, &node_types) {
|
2015-11-23 16:32:24 +01:00
|
|
|
if (list_length(&vt->instances) > 0) {
|
2015-05-06 11:48:30 +02:00
|
|
|
info("Initializing '%s' node type", vt->name);
|
2015-11-23 16:32:24 +01:00
|
|
|
|
|
|
|
if (vt->init)
|
|
|
|
vt->init(argc, argv, set);
|
2015-03-31 13:54:04 +02:00
|
|
|
}
|
2015-11-23 16:32:24 +01:00
|
|
|
else
|
|
|
|
warn("No node is using the '%s' type. Skipping...", vt->name);
|
2015-03-31 13:54:04 +02:00
|
|
|
}
|
2015-08-07 01:11:43 +02:00
|
|
|
|
2015-03-31 13:54:04 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int node_deinit()
|
|
|
|
{ INDENT
|
|
|
|
/* De-initialize node types */
|
2015-10-09 12:50:35 +02:00
|
|
|
list_foreach(const struct node_type *vt, &node_types) {
|
2015-11-23 16:32:24 +01:00
|
|
|
if (list_length(&vt->instances) > 0) {
|
2015-05-06 11:48:30 +02:00
|
|
|
info("De-initializing '%s' node type", vt->name);
|
|
|
|
vt->deinit();
|
2015-03-31 13:54:04 +02:00
|
|
|
}
|
|
|
|
}
|
2015-10-09 13:04:52 +02:00
|
|
|
|
2015-03-31 13:54:04 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-12-05 12:39:52 +01:00
|
|
|
int node_start(struct node *n)
|
2015-03-21 15:29:00 +01:00
|
|
|
{ INDENT
|
2015-11-16 10:51:00 +01:00
|
|
|
int ret;
|
2014-12-05 12:39:52 +01:00
|
|
|
|
2015-11-29 22:45:46 +01:00
|
|
|
info("Starting node %s", node_name_long(n));
|
2014-12-05 12:39:52 +01:00
|
|
|
{ INDENT
|
2015-11-16 10:51:00 +01:00
|
|
|
ret = node_open(n);
|
2014-06-05 09:34:56 +00:00
|
|
|
}
|
2015-11-16 10:51:00 +01:00
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
n->state = NODE_RUNNING;
|
|
|
|
|
|
|
|
return ret;
|
2014-12-05 12:39:52 +01:00
|
|
|
}
|
2014-06-05 09:34:29 +00:00
|
|
|
|
2014-12-05 12:39:52 +01:00
|
|
|
int node_stop(struct node *n)
|
2015-03-21 15:29:00 +01:00
|
|
|
{ INDENT
|
2015-11-16 10:51:00 +01:00
|
|
|
int ret;
|
|
|
|
|
2015-11-29 22:45:46 +01:00
|
|
|
if (n->state != NODE_RUNNING)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
info("Stopping node %s", node_name(n));
|
2015-08-07 01:11:43 +02:00
|
|
|
|
2014-12-05 12:39:52 +01:00
|
|
|
{ INDENT
|
2015-11-16 10:51:00 +01:00
|
|
|
ret = node_close(n);
|
2014-12-05 12:39:52 +01:00
|
|
|
}
|
2015-11-16 10:51:00 +01:00
|
|
|
|
|
|
|
if (ret == 0)
|
|
|
|
n->state = NODE_STOPPED;
|
|
|
|
|
|
|
|
return ret;
|
2014-06-05 09:34:29 +00:00
|
|
|
}
|
2015-03-18 16:18:10 +01:00
|
|
|
|
2015-11-29 22:45:46 +01:00
|
|
|
const char * node_name(struct node *n)
|
2015-10-17 19:05:15 +02:00
|
|
|
{
|
2015-11-29 22:45:46 +01:00
|
|
|
if (!n->_name)
|
|
|
|
strcatf(&n->_name, YEL("%s") GRY("(%s)"), n->name, n->_vt->name);
|
|
|
|
|
|
|
|
return n->_name;
|
|
|
|
}
|
2015-10-17 19:05:15 +02:00
|
|
|
|
2015-11-29 22:45:46 +01:00
|
|
|
const char * node_name_long(struct node *n)
|
|
|
|
{
|
|
|
|
if (!n->_name_long)
|
|
|
|
n->_name_long = n->_vt->print(n);
|
|
|
|
|
|
|
|
return n->_name_long;
|
2015-10-17 19:05:15 +02:00
|
|
|
}
|
|
|
|
|
2015-11-23 16:42:43 +01:00
|
|
|
int node_reverse(struct node *n)
|
2015-03-18 16:18:10 +01:00
|
|
|
{
|
2015-11-23 16:42:43 +01:00
|
|
|
return n->_vt->reverse ? n->_vt->reverse(n) : -1;
|
2015-03-21 15:29:00 +01:00
|
|
|
}
|
2015-03-21 15:23:57 +01:00
|
|
|
|
2015-10-13 15:05:48 +02:00
|
|
|
struct node * node_create(struct node_type *vt)
|
2015-03-21 15:23:57 +01:00
|
|
|
{
|
2015-10-13 15:05:48 +02:00
|
|
|
struct node *n = alloc(sizeof(struct node));
|
|
|
|
|
2015-11-23 16:32:24 +01:00
|
|
|
list_push(&vt->instances, n);
|
|
|
|
|
2015-10-13 15:05:48 +02:00
|
|
|
n->_vt = vt;
|
2015-11-16 10:51:00 +01:00
|
|
|
n->state = NODE_CREATED;
|
2015-10-13 15:05:48 +02:00
|
|
|
|
|
|
|
return n;
|
2015-03-21 15:23:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void node_destroy(struct node *n)
|
|
|
|
{
|
2015-11-23 16:42:43 +01:00
|
|
|
if (n->_vt->destroy)
|
|
|
|
n->_vt->destroy(n);
|
2015-03-21 15:23:57 +01:00
|
|
|
|
|
|
|
free(n->socket);
|
2015-11-29 22:45:46 +01:00
|
|
|
free(n->_name);
|
2015-03-21 15:23:57 +01:00
|
|
|
free(n);
|
2015-03-18 16:18:10 +01:00
|
|
|
}
|