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

src: catch unhandled exceptions

This commit is contained in:
Steffen Vogel 2019-04-17 18:46:18 +02:00
parent b67acd52fb
commit dabb1c5454
8 changed files with 789 additions and 716 deletions

View file

@ -52,100 +52,112 @@ static void usage()
int main(int argc, char *argv[])
{
int ret;
const char *input_format = "villas.human";
const char *output_format = "villas.human";
const char *dtypes = "64f";
Logger logger = logging.get("test-rtt");
/* Parse optional command line arguments */
int c;
while ((c = getopt(argc, argv, "Vhd:i:o:t:")) != -1) {
switch (c) {
case 'V':
print_version();
exit(EXIT_SUCCESS);
try {
int ret;
const char *input_format = "villas.human";
const char *output_format = "villas.human";
const char *dtypes = "64f";
case 'i':
input_format = optarg;
break;
/* Parse optional command line arguments */
int c;
while ((c = getopt(argc, argv, "Vhd:i:o:t:")) != -1) {
switch (c) {
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 'o':
output_format = optarg;
break;
case 'i':
input_format = optarg;
break;
case 't':
dtypes = optarg;
break;
case 'o':
output_format = optarg;
break;
case 'd':
logging.setLevel(optarg);
break;
case 't':
dtypes = optarg;
break;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
case 'd':
logging.setLevel(optarg);
break;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
}
if (argc != optind) {
usage();
exit(EXIT_FAILURE);
}
struct format_type *ft;
struct io input;
struct io output;
input.state = STATE_DESTROYED;
output.state = STATE_DESTROYED;
struct {
const char *name;
struct io *io;
} dirs[] = {
{ input_format, &input },
{ output_format, &output },
};
for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) {
ft = format_type_lookup(dirs[i].name);
if (!ft)
throw RuntimeError("Invalid format: {}", dirs[i].name);
ret = io_init2(dirs[i].io, ft, dtypes, SAMPLE_HAS_ALL);
if (ret)
throw RuntimeError("Failed to initialize IO: {}", dirs[i].name);
ret = io_check(dirs[i].io);
if (ret)
throw RuntimeError("Failed to validate IO configuration");
ret = io_open(dirs[i].io, nullptr);
if (ret)
throw RuntimeError("Failed to open IO");
}
struct sample *smp = sample_alloc_mem(DEFAULT_SAMPLE_LENGTH);
for (;;) {
ret = io_scan(&input, &smp, 1);
if (ret == 0)
continue;
if (ret < 0)
break;
io_print(&output, &smp, 1);
}
for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) {
ret = io_close(dirs[i].io);
if (ret)
throw RuntimeError("Failed to close IO");
ret = io_destroy(dirs[i].io);
if (ret)
throw RuntimeError("Failed to destroy IO");
}
return 0;
}
catch (std::runtime_error &e) {
logger->error("{}", e.what());
if (argc != optind) {
usage();
exit(EXIT_FAILURE);
return -1;
}
struct format_type *ft;
struct io input = { .state = STATE_DESTROYED };
struct io output = { .state = STATE_DESTROYED };
struct {
const char *name;
struct io *io;
} dirs[] = {
{ input_format, &input },
{ output_format, &output },
};
for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) {
ft = format_type_lookup(dirs[i].name);
if (!ft)
throw RuntimeError("Invalid format: {}", dirs[i].name);
ret = io_init2(dirs[i].io, ft, dtypes, SAMPLE_HAS_ALL);
if (ret)
throw RuntimeError("Failed to initialize IO: {}", dirs[i].name);
ret = io_check(dirs[i].io);
if (ret)
throw RuntimeError("Failed to validate IO configuration");
ret = io_open(dirs[i].io, nullptr);
if (ret)
throw RuntimeError("Failed to open IO");
}
struct sample *smp = sample_alloc_mem(DEFAULT_SAMPLE_LENGTH);
for (;;) {
ret = io_scan(&input, &smp, 1);
if (ret == 0)
continue;
if (ret < 0)
break;
io_print(&output, &smp, 1);
}
for (unsigned i = 0; i < ARRAY_LEN(dirs); i++) {
ret = io_close(dirs[i].io);
if (ret)
throw RuntimeError("Failed to close IO");
ret = io_destroy(dirs[i].io);
if (ret)
throw RuntimeError("Failed to destroy IO");
}
return 0;
}
/** @} */

View file

@ -99,8 +99,11 @@ int main(int argc, char *argv[])
Logger logger = logging.get("hook");
try {
struct pool p = { .state = STATE_DESTROYED };
struct io io = { .state = STATE_DESTROYED };
struct pool p;
struct io io;
p.state = STATE_DESTROYED;
io.state = STATE_DESTROYED;
/* Default values */
cnt = 1;

View file

@ -251,210 +251,218 @@ leave2: stop = true;
int main(int argc, char *argv[])
{
int ret, timeout = 0;
bool reverse = false;
const char *format = "villas.human";
const char *dtypes = "64f";
struct node *node;
static struct io io = { .state = STATE_DESTROYED };
SuperNode sn; /**< The global configuration */
Logger logger = logging.get("pipe");
json_t *cfg_cli = json_object();
try {
int ret, timeout = 0;
bool reverse = false;
const char *format = "villas.human";
const char *dtypes = "64f";
bool enable_send = true, enable_recv = true;
int limit_send = -1, limit_recv = -1;
struct node *node;
static struct io io = { .state = STATE_DESTROYED };
/* Parse optional command line arguments */
int c;
char *endptr;
while ((c = getopt(argc, argv, "Vhxrsd:l:L:T:f:t:o:")) != -1) {
switch (c) {
case 'V':
print_version();
exit(EXIT_SUCCESS);
SuperNode sn; /**< The global configuration */
case 'f':
format = optarg;
break;
json_t *cfg_cli = json_object();
case 't':
dtypes = optarg;
break;
bool enable_send = true, enable_recv = true;
int limit_send = -1, limit_recv = -1;
case 'x':
reverse = true;
break;
/* Parse optional command line arguments */
int c;
char *endptr;
while ((c = getopt(argc, argv, "Vhxrsd:l:L:T:f:t:o:")) != -1) {
switch (c) {
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 's':
enable_recv = false; // send only
break;
case 'f':
format = optarg;
break;
case 'r':
enable_send = false; // receive only
break;
case 't':
dtypes = optarg;
break;
case 'l':
limit_recv = strtoul(optarg, &endptr, 10);
goto check;
case 'x':
reverse = true;
break;
case 'L':
limit_send = strtoul(optarg, &endptr, 10);
goto check;
case 's':
enable_recv = false; // send only
break;
case 'T':
timeout = strtoul(optarg, &endptr, 10);
goto check;
case 'r':
enable_send = false; // receive only
break;
case 'o':
ret = json_object_extend_str(cfg_cli, optarg);
if (ret)
throw RuntimeError("Invalid option: {}", optarg);
break;
case 'l':
limit_recv = strtoul(optarg, &endptr, 10);
goto check;
case 'd':
logging.setLevel(optarg);
break;
case 'L':
limit_send = strtoul(optarg, &endptr, 10);
goto check;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
case 'T':
timeout = strtoul(optarg, &endptr, 10);
goto check;
case 'o':
ret = json_object_extend_str(cfg_cli, optarg);
if (ret)
throw RuntimeError("Invalid option: {}", optarg);
break;
case 'd':
logging.setLevel(optarg);
break;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
continue;
check: if (optarg == endptr)
throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg);
}
continue;
if (argc != optind + 2) {
usage();
exit(EXIT_FAILURE);
}
check: if (optarg == endptr)
throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg);
}
logger->info("Logging level: {}", logging.getLevelName());
if (argc != optind + 2) {
usage();
exit(EXIT_FAILURE);
}
char *uri = argv[optind];
char *nodestr = argv[optind+1];
struct format_type *ft;
logger->info("Logging level: {}", logging.getLevelName());
ret = memory_init(0);
if (ret)
throw RuntimeError("Failed to intialize memory");
char *uri = argv[optind];
char *nodestr = argv[optind+1];
struct format_type *ft;
ret = utils::signals_init(quit);
if (ret)
throw RuntimeError("Failed to initialize signals");
ret = memory_init(0);
if (ret)
throw RuntimeError("Failed to intialize memory");
if (uri)
sn.parse(uri);
else
logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance.");
ret = utils::signals_init(quit);
if (ret)
throw RuntimeError("Failed to initialize signals");
ft = format_type_lookup(format);
if (!ft)
throw RuntimeError("Invalid format: {}", format);
if (uri)
sn.parse(uri);
else
logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance.");
ret = io_init2(&io, ft, dtypes, SAMPLE_HAS_ALL);
if (ret)
throw RuntimeError("Failed to initialize IO");
ft = format_type_lookup(format);
if (!ft)
throw RuntimeError("Invalid format: {}", format);
ret = io_check(&io);
if (ret)
throw RuntimeError("Failed to validate IO configuration");
ret = io_init2(&io, ft, dtypes, SAMPLE_HAS_ALL);
if (ret)
throw RuntimeError("Failed to initialize IO");
ret = io_open(&io, nullptr);
if (ret)
throw RuntimeError("Failed to open IO");
ret = io_check(&io);
if (ret)
throw RuntimeError("Failed to validate IO configuration");
ret = io_open(&io, nullptr);
if (ret)
throw RuntimeError("Failed to open IO");
node = sn.getNode(nodestr);
if (!node)
throw RuntimeError("Node {} does not exist!", nodestr);
node = sn.getNode(nodestr);
if (!node)
throw RuntimeError("Node {} does not exist!", nodestr);
#ifdef WITH_NODE_WEBSOCKET
/* Only start web subsystem if villas-pipe is used with a websocket node */
if (node_type(node)->start == websocket_start) {
Web *w = sn.getWeb();
w->start();
}
/* Only start web subsystem if villas-pipe is used with a websocket node */
if (node_type(node)->start == websocket_start) {
Web *w = sn.getWeb();
w->start();
}
#endif /* WITH_NODE_WEBSOCKET */
if (reverse)
node_reverse(node);
if (reverse)
node_reverse(node);
ret = node_type_start(node_type(node), reinterpret_cast<super_node *>(&sn));
if (ret)
throw RuntimeError("Failed to intialize node type {}: reason={}", node_type_name(node_type(node)), ret);
ret = node_type_start(node_type(node), reinterpret_cast<super_node *>(&sn));
if (ret)
throw RuntimeError("Failed to intialize node type {}: reason={}", node_type_name(node_type(node)), ret);
sn.startInterfaces();
sn.startInterfaces();
ret = node_check(node);
if (ret)
throw RuntimeError("Invalid node configuration");
ret = node_check(node);
if (ret)
throw RuntimeError("Invalid node configuration");
ret = node_prepare(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
ret = node_prepare(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
ret = node_start(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
ret = node_start(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
/* Start threads */
Directions dirs = {
.send = Direction(node, &io, enable_send, limit_send),
.recv = Direction(node, &io, enable_recv, limit_recv)
};
/* Start threads */
Directions dirs = {
.send = Direction(node, &io, enable_send, limit_send),
.recv = Direction(node, &io, enable_recv, limit_recv)
};
if (dirs.recv.enabled) {
dirs.recv.node = node;
pthread_create(&dirs.recv.thread, nullptr, recv_loop, &dirs);
if (dirs.recv.enabled) {
dirs.recv.node = node;
pthread_create(&dirs.recv.thread, nullptr, recv_loop, &dirs);
}
if (dirs.send.enabled) {
dirs.send.node = node;
pthread_create(&dirs.send.thread, nullptr, send_loop, &dirs);
}
alarm(timeout);
while (!stop)
sleep(1);
if (dirs.recv.enabled) {
pthread_cancel(dirs.recv.thread);
pthread_join(dirs.recv.thread, nullptr);
}
if (dirs.send.enabled) {
pthread_cancel(dirs.send.thread);
pthread_join(dirs.send.thread, nullptr);
}
ret = node_stop(node);
if (ret)
throw RuntimeError("Failed to stop node {}: reason={}", node_name(node), ret);
sn.stopInterfaces();
ret = node_type_stop(node->_vt);
if (ret)
throw RuntimeError("Failed to stop node type {}: reason={}", node_type_name(node->_vt), ret);
ret = io_close(&io);
if (ret)
throw RuntimeError("Failed to close IO");
ret = io_destroy(&io);
if (ret)
throw RuntimeError("Failed to destroy IO");
logger->info(CLR_GRN("Goodbye!"));
return 0;
}
catch (std::runtime_error &e) {
logger->error("{}", e.what());
if (dirs.send.enabled) {
dirs.send.node = node;
pthread_create(&dirs.send.thread, nullptr, send_loop, &dirs);
return -1;
}
alarm(timeout);
while (!stop)
sleep(1);
if (dirs.recv.enabled) {
pthread_cancel(dirs.recv.thread);
pthread_join(dirs.recv.thread, nullptr);
}
if (dirs.send.enabled) {
pthread_cancel(dirs.send.thread);
pthread_join(dirs.send.thread, nullptr);
}
ret = node_stop(node);
if (ret)
throw RuntimeError("Failed to stop node {}: reason={}", node_name(node), ret);
sn.stopInterfaces();
ret = node_type_stop(node->_vt);
if (ret)
throw RuntimeError("Failed to stop node type {}: reason={}", node_type_name(node->_vt), ret);
ret = io_close(&io);
if (ret)
throw RuntimeError("Failed to close IO");
ret = io_destroy(&io);
if (ret)
throw RuntimeError("Failed to destroy IO");
logger->info(CLR_GRN("Goodbye!"));
return 0;
}
/** @} */

View file

@ -44,9 +44,10 @@ static lws_context *context;
/** The libwebsockets vhost. */
static lws_vhost *vhost;
auto console = villas::logging.get("console");
std::map<std::string, Session *> sessions;
using Logger = villas::Logger;
/* Default options */
struct Options opts = {
.loopback = false,
@ -116,7 +117,9 @@ Session::Session(Identifier sid) :
identifier(sid),
connects(0)
{
console->info("Session created: {}", identifier);
Logger logger = villas::logging.get("console");
logger->info("Session created: {}", identifier);
sessions[sid] = this;
@ -127,13 +130,17 @@ Session::Session(Identifier sid) :
Session::~Session()
{
console->info("Session destroyed: {}", identifier);
Logger logger = villas::logging.get("console");
logger->info("Session destroyed: {}", identifier);
sessions.erase(identifier);
}
Session * Session::get(lws *wsi)
{
Logger logger = villas::logging.get("console");
char uri[64];
/* We use the URI to associate this connection to a session
@ -153,7 +160,7 @@ Session * Session::get(lws *wsi)
return new Session(sid);
}
else {
console->info("Found existing session: {}", sid);
logger->info("Found existing session: {}", sid);
return it->second;
}
@ -190,6 +197,8 @@ Connection::Connection(lws *w) :
frames_recv(0),
frames_sent(0)
{
Logger logger = villas::logging.get("console");
session = Session::get(wsi);
session->connections[wsi] = this;
session->connects++;
@ -198,12 +207,14 @@ Connection::Connection(lws *w) :
created = time(nullptr);
console->info("New connection established: session={}, remote={} ({})", session->identifier, name, ip);
logger->info("New connection established: session={}, remote={} ({})", session->identifier, name, ip);
}
Connection::~Connection()
{
console->info("Connection closed: session={}, remote={} ({})", session->identifier, name, ip);
Logger logger = villas::logging.get("console");
logger->info("Connection closed: session={}, remote={} ({})", session->identifier, name, ip);
session->connections.erase(wsi);
@ -245,13 +256,15 @@ void Connection::write()
void Connection::read(void *in, size_t len)
{
Logger logger = villas::logging.get("console");
currentFrame->insert(currentFrame->end(), (uint8_t *) in, (uint8_t *) in + len);
bytes_recv += len;
if (lws_is_final_fragment(wsi)) {
frames_recv++;
console->debug("Received frame, relaying to {} connections", session->connections.size() - (opts.loopback ? 0 : 1));
logger->debug("Received frame, relaying to {} connections", session->connections.size() - (opts.loopback ? 0 : 1));
for (auto p : session->connections) {
auto c = p.second;
@ -270,7 +283,7 @@ void Connection::read(void *in, size_t len)
}
}
static void logger(int level, const char *msg)
static void logger_cb(int level, const char *msg)
{
auto log = spdlog::get("lws");
@ -296,6 +309,8 @@ int http_protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *user, voi
size_t json_len;
json_t *json_sessions, *json_body;
Logger logger = villas::logging.get("console");
unsigned char buf[LWS_PRE + 2048], *start = &buf[LWS_PRE], *end = &buf[sizeof(buf) - LWS_PRE - 1], *p = start;
switch (reason) {
@ -341,7 +356,7 @@ int http_protocol_cb(lws *wsi, enum lws_callback_reasons reason, void *user, voi
if (ret < 0)
return ret;
console->info("Handled API request");
logger->info("Handled API request");
//if (lws_http_transaction_completed(wsi))
return -1;
@ -405,79 +420,88 @@ static void usage()
int main(int argc, char *argv[])
{
/* Initialize logging */
spdlog::stdout_color_mt("lws");
lws_set_log_level((1 << LLL_COUNT) - 1, logger);
Logger logger = villas::logging.get("console");
/* Start server */
lws_context_creation_info ctx_info = { 0 };
try {
/* Initialize logging */
spdlog::stdout_color_mt("lws");
lws_set_log_level((1 << LLL_COUNT) - 1, logger_cb);
char c, *endptr;
while ((c = getopt (argc, argv, "hVp:P:ld:")) != -1) {
switch (c) {
case 'd':
spdlog::set_level(spdlog::level::from_str(optarg));
break;
/* Start server */
lws_context_creation_info ctx_info = { 0 };
case 'p':
opts.port = strtoul(optarg, &endptr, 10);
goto check;
char c, *endptr;
while ((c = getopt (argc, argv, "hVp:P:ld:")) != -1) {
switch (c) {
case 'd':
spdlog::set_level(spdlog::level::from_str(optarg));
break;
case 'P':
opts.protocol = strdup(optarg);
break;
case 'p':
opts.port = strtoul(optarg, &endptr, 10);
goto check;
case 'l':
opts.loopback = true;
break;
case 'P':
opts.protocol = strdup(optarg);
break;
case 'V':
villas::print_version();
exit(EXIT_SUCCESS);
case 'l':
opts.loopback = true;
break;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
case 'V':
villas::print_version();
exit(EXIT_SUCCESS);
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
continue;
check: if (optarg == endptr) {
logger->error("Failed to parse parse option argument '-{} {}'", c, optarg);
exit(EXIT_FAILURE);
}
}
continue;
check: if (optarg == endptr) {
console->error("Failed to parse parse option argument '-{} {}'", c, optarg);
if (argc - optind < 0) {
usage();
exit(EXIT_FAILURE);
}
protocols[2].name = opts.protocol;
ctx_info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
ctx_info.gid = -1;
ctx_info.uid = -1;
ctx_info.protocols = protocols;
ctx_info.extensions = extensions;
ctx_info.port = opts.port;
ctx_info.mounts = &mount;
context = lws_create_context(&ctx_info);
if (context == nullptr) {
logger->error("WebSocket: failed to initialize server context");
exit(EXIT_FAILURE);
}
vhost = lws_create_vhost(context, &ctx_info);
if (vhost == nullptr) {
logger->error("WebSocket: failed to initialize virtual host");
exit(EXIT_FAILURE);
}
for (;;)
lws_service(context, 100);
return 0;
}
catch (std::runtime_error &e) {
logger->error("{}", e.what());
if (argc - optind < 0) {
usage();
exit(EXIT_FAILURE);
return -1;
}
protocols[2].name = opts.protocol;
ctx_info.options = LWS_SERVER_OPTION_EXPLICIT_VHOSTS | LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
ctx_info.gid = -1;
ctx_info.uid = -1;
ctx_info.protocols = protocols;
ctx_info.extensions = extensions;
ctx_info.port = opts.port;
ctx_info.mounts = &mount;
context = lws_create_context(&ctx_info);
if (context == nullptr) {
console->error("WebSocket: failed to initialize server context");
exit(EXIT_FAILURE);
}
vhost = lws_create_vhost(context, &ctx_info);
if (vhost == nullptr) {
console->error("WebSocket: failed to initialize virtual host");
exit(EXIT_FAILURE);
}
for (;;)
lws_service(context, 100);
return 0;
}

View file

@ -186,130 +186,138 @@ static void quit(int signal, siginfo_t *sinfo, void *ctx)
int main(int argc, char *argv[])
{
int ret;
json_t *cfg;
struct node_type *nt;
struct format_type *ft;
const char *format = "villas.human"; /** @todo hardcoded for now */
struct node n;
n.state = STATE_DESTROYED;
n.in.state = STATE_DESTROYED;
n.out.state = STATE_DESTROYED;
struct io io = { .state = STATE_DESTROYED };
struct pool q = { .state = STATE_DESTROYED };
struct sample *t;
q.queue.state = STATE_DESTROYED;
Logger logger = logging.get("signal");
ret = utils::signals_init(quit);
if (ret)
throw RuntimeError("Failed to intialize signals");
try {
int ret;
json_t *cfg;
struct node_type *nt;
struct format_type *ft;
ret = memory_init(0);
if (ret)
throw RuntimeError("Failed to initialize memory");
char *format = (char *) "villas.human"; /** @todo hardcoded for now */
nt = node_type_lookup("signal");
if (!nt)
throw RuntimeError("Signal generation is not supported.");
struct node n;
struct io io;
struct pool q;
struct sample *t;
ret = node_init(&n, nt);
if (ret)
throw RuntimeError("Failed to initialize node");
n.state = STATE_DESTROYED;
n.in.state = STATE_DESTROYED;
n.out.state = STATE_DESTROYED;
io.state = STATE_DESTROYED;
q.state = STATE_DESTROYED;
q.queue.state = STATE_DESTROYED;
cfg = parse_cli(argc, argv, &format);
if (!cfg) {
usage();
exit(EXIT_FAILURE);
ret = utils::signals_init(quit);
if (ret)
throw RuntimeError("Failed to intialize signals");
ret = memory_init(0);
if (ret)
throw RuntimeError("Failed to initialize memory");
nt = node_type_lookup("signal");
if (!nt)
throw RuntimeError("Signal generation is not supported.");
ret = node_init(&n, nt);
if (ret)
throw RuntimeError("Failed to initialize node");
cfg = parse_cli(argc, argv, &format);
if (!cfg) {
usage();
exit(EXIT_FAILURE);
}
ret = node_parse(&n, cfg, "cli");
if (ret) {
usage();
exit(EXIT_FAILURE);
}
ft = format_type_lookup(format);
if (!ft)
throw RuntimeError("Invalid output format '{}'", format);
// nt == n._vt
ret = node_type_start(nt, nullptr);
if (ret)
throw RuntimeError("Failed to initialize node type: {}", node_type_name(nt));
ret = node_check(&n);
if (ret)
throw RuntimeError("Failed to verify node configuration");
ret = pool_init(&q, 16, SAMPLE_LENGTH(vlist_length(&n.in.signals)), &memory_heap);
if (ret)
throw RuntimeError("Failed to initialize pool");
ret = node_prepare(&n);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(&n), ret);
ret = node_start(&n);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(&n), ret);
ret = io_init(&io, ft, &n.in.signals, IO_FLUSH | (SAMPLE_HAS_ALL & ~SAMPLE_HAS_OFFSET));
if (ret)
throw RuntimeError("Failed to initialize output");
ret = io_check(&io);
if (ret)
throw RuntimeError("Failed to validate IO configuration");
ret = io_open(&io, nullptr);
if (ret)
throw RuntimeError("Failed to open output");
while (!stop && n.state == STATE_STARTED) {
t = sample_alloc(&q);
unsigned release = 1; // release = allocated
retry: ret = node_read(&n, &t, 1, &release);
if (ret == 0)
goto retry;
else if (ret < 0)
goto out;
io_print(&io, &t, 1);
out: sample_decref(t);
}
ret = node_stop(&n);
if (ret)
throw RuntimeError("Failed to stop node");
ret = node_destroy(&n);
if (ret)
throw RuntimeError("Failed to destroy node");
ret = io_close(&io);
if (ret)
throw RuntimeError("Failed to close IO");
ret = io_destroy(&io);
if (ret)
throw RuntimeError("Failed to destroy IO");
ret = pool_destroy(&q);
if (ret)
throw RuntimeError("Failed to destroy pool");
logger->info(CLR_GRN("Goodbye!"));
return 0;
}
catch (std::runtime_error &e) {
logger->error("{}", e.what());
ret = node_parse(&n, cfg, "cli");
if (ret) {
usage();
exit(EXIT_FAILURE);
return -1;
}
ft = format_type_lookup(format);
if (!ft)
throw RuntimeError("Invalid output format '{}'", format);
// nt == n._vt
ret = node_type_start(nt, nullptr);
if (ret)
throw RuntimeError("Failed to initialize node type: {}", node_type_name(nt));
ret = node_check(&n);
if (ret)
throw RuntimeError("Failed to verify node configuration");
ret = pool_init(&q, 16, SAMPLE_LENGTH(vlist_length(&n.in.signals)), &memory_heap);
if (ret)
throw RuntimeError("Failed to initialize pool");
ret = node_prepare(&n);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(&n), ret);
ret = node_start(&n);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(&n), ret);
ret = io_init(&io, ft, &n.in.signals, IO_FLUSH | (SAMPLE_HAS_ALL & ~SAMPLE_HAS_OFFSET));
if (ret)
throw RuntimeError("Failed to initialize output");
ret = io_check(&io);
if (ret)
throw RuntimeError("Failed to validate IO configuration");
ret = io_open(&io, nullptr);
if (ret)
throw RuntimeError("Failed to open output");
while (!stop && n.state == STATE_STARTED) {
t = sample_alloc(&q);
unsigned release = 1; // release = allocated
retry: ret = node_read(&n, &t, 1, &release);
if (ret == 0)
goto retry;
else if (ret < 0)
goto out;
io_print(&io, &t, 1);
out: sample_decref(t);
}
ret = node_stop(&n);
if (ret)
throw RuntimeError("Failed to stop node");
ret = node_destroy(&n);
if (ret)
throw RuntimeError("Failed to destroy node");
ret = io_close(&io);
if (ret)
throw RuntimeError("Failed to close IO");
ret = io_destroy(&io);
if (ret)
throw RuntimeError("Failed to destroy IO");
ret = pool_destroy(&q);
if (ret)
throw RuntimeError("Failed to destroy pool");
logger->info(CLR_GRN("Goodbye!"));
return 0;
}
/** @} */

View file

@ -117,138 +117,147 @@ static void usage()
int main(int argc, char *argv[])
{
int ret, rc = 0;
Logger logger = logging.get("test-cmp");
/* Default values */
double epsilon = 1e-9;
const char *format = "villas.human";
const char *dtypes = "64f";
int flags = SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA | SAMPLE_HAS_TS_ORIGIN;
try {
int ret, rc = 0;
struct pool pool = { .state = STATE_DESTROYED };
/* Default values */
double epsilon = 1e-9;
const char *format = "villas.human";
const char *dtypes = "64f";
int flags = SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA | SAMPLE_HAS_TS_ORIGIN;
/* Parse Arguments */
int c;
char *endptr;
while ((c = getopt (argc, argv, "he:vTsf:t:Vd:")) != -1) {
switch (c) {
case 'e':
epsilon = strtod(optarg, &endptr);
goto check;
struct pool pool = { .state = STATE_DESTROYED };
case 'v':
flags &= ~SAMPLE_HAS_DATA;
break;
/* Parse Arguments */
int c;
char *endptr;
while ((c = getopt (argc, argv, "he:vTsf:t:Vd:")) != -1) {
switch (c) {
case 'e':
epsilon = strtod(optarg, &endptr);
goto check;
case 'T':
flags &= ~SAMPLE_HAS_TS_ORIGIN;
break;
case 'v':
flags &= ~SAMPLE_HAS_DATA;
break;
case 's':
flags &= ~SAMPLE_HAS_SEQUENCE;
break;
case 'T':
flags &= ~SAMPLE_HAS_TS_ORIGIN;
break;
case 'f':
format = optarg;
break;
case 's':
flags &= ~SAMPLE_HAS_SEQUENCE;
break;
case 't':
dtypes = optarg;
break;
case 'f':
format = optarg;
break;
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 't':
dtypes = optarg;
break;
case 'd':
logging.setLevel(optarg);
break;
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
case 'd':
logging.setLevel(optarg);
break;
continue;
check: if (optarg == endptr)
throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg);
}
if (argc - optind < 2) {
usage();
exit(EXIT_FAILURE);
}
int eofs, line, failed;
int n = argc - optind; /* The number of files which we compare */
Side *s[n];
ret = memory_init(0);
if (ret)
throw RuntimeError("Failed to initialize memory system");
ret = pool_init(&pool, n, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory_heap);
if (ret)
throw RuntimeError("Failed to initialize pool");
struct format_type *fmt = format_type_lookup(format);
if (!fmt)
throw RuntimeError("Invalid IO format: {}", format);
/* Open files */
for (int i = 0; i < n; i++)
s[i] = new Side(argv[optind + i], fmt, dtypes, &pool);
line = 0;
for (;;) {
/* Read next sample from all files */
retry: eofs = 0;
for (int i = 0; i < n; i++) {
ret = io_eof(&s[i]->io);
if (ret)
eofs++;
}
if (eofs) {
if (eofs == n)
ret = 0;
else {
std::cout << "length unequal" << std::endl;
rc = 1;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
goto out;
continue;
check: if (optarg == endptr)
throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg);
}
failed = 0;
for (int i = 0; i < n; i++) {
ret = io_scan(&s[i]->io, &s[i]->sample, 1);
if (ret <= 0)
failed++;
if (argc - optind < 2) {
usage();
exit(EXIT_FAILURE);
}
if (failed)
goto retry;
/* We compare all files against the first one */
for (int i = 1; i < n; i++) {
ret = sample_cmp(s[0]->sample, s[i]->sample, epsilon, flags);
if (ret) {
rc = ret;
int eofs, line, failed;
int n = argc - optind; /* The number of files which we compare */
Side *s[n];
ret = memory_init(0);
if (ret)
throw RuntimeError("Failed to initialize memory system");
ret = pool_init(&pool, n, SAMPLE_LENGTH(DEFAULT_SAMPLE_LENGTH), &memory_heap);
if (ret)
throw RuntimeError("Failed to initialize pool");
struct format_type *fmt = format_type_lookup(format);
if (!fmt)
throw RuntimeError("Invalid IO format: {}", format);
/* Open files */
for (int i = 0; i < n; i++)
s[i] = new Side(argv[optind + i], fmt, dtypes, &pool);
line = 0;
for (;;) {
/* Read next sample from all files */
retry: eofs = 0;
for (int i = 0; i < n; i++) {
ret = io_eof(&s[i]->io);
if (ret)
eofs++;
}
if (eofs) {
if (eofs == n)
ret = 0;
else {
std::cout << "length unequal" << std::endl;
rc = 1;
}
goto out;
}
failed = 0;
for (int i = 0; i < n; i++) {
ret = io_scan(&s[i]->io, &s[i]->sample, 1);
if (ret <= 0)
failed++;
}
if (failed)
goto retry;
/* We compare all files against the first one */
for (int i = 1; i < n; i++) {
ret = sample_cmp(s[0]->sample, s[i]->sample, epsilon, flags);
if (ret) {
rc = ret;
goto out;
}
}
line++;
}
line++;
out: for (int i = 0; i < n; i++)
delete s[i];
ret = pool_destroy(&pool);
if (ret)
throw RuntimeError("Failed to destroy pool");
return rc;
}
catch (std::runtime_error &e) {
logger->error("{}", e.what());
out: for (int i = 0; i < n; i++)
delete s[i];
ret = pool_destroy(&pool);
if (ret)
throw RuntimeError("Failed to destroy pool");
return rc;
return -1;
}
}

View file

@ -47,35 +47,36 @@ static void usage()
int main(int argc, char *argv[])
{
SuperNode sn;
Logger logger = logging.get("config-test");
bool check = false;
int c;
while ((c = getopt (argc, argv, "hcV")) != -1) {
switch (c) {
case 'c':
check = true;
break;
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
}
if (argc - optind < 1) {
usage();
exit(EXIT_FAILURE);
}
Logger logger = logging.get("test-config");
try {
SuperNode sn;
bool check = false;
int c;
while ((c = getopt (argc, argv, "hcV")) != -1) {
switch (c) {
case 'c':
check = true;
break;
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
}
if (argc - optind < 1) {
usage();
exit(EXIT_FAILURE);
}
sn.parse(argv[optind]);
if (check)

View file

@ -72,166 +72,174 @@ static void usage()
int main(int argc, char *argv[])
{
int ret;
struct hist hist;
struct timespec send, recv;
struct sample *smp_send = (struct sample *) new char[SAMPLE_LENGTH(2)];
struct sample *smp_recv = (struct sample *) new char[SAMPLE_LENGTH(2)];
struct node *node;
SuperNode sn;
Logger logger = logging.get("test-rtt");
/* Test options */
int count = -1; /**< Amount of messages which should be sent (default: -1 for unlimited) */
try {
int ret;
hist_cnt_t hist_warmup = 100;
int hist_buckets = 20;
struct hist hist;
struct timespec send, recv;
/** File descriptor for Matlab results.
* This allows you to write Matlab results in a seperate log file:
*
* ./test etc/example.conf rtt -f 3 3>> measurement_results.m
*/
int fd = STDOUT_FILENO;
struct sample *smp_send = (struct sample *) new char[SAMPLE_LENGTH(2)];
struct sample *smp_recv = (struct sample *) new char[SAMPLE_LENGTH(2)];
/* Parse Arguments */
int c;
char *endptr;
while ((c = getopt (argc, argv, "w:hr:f:c:b:Vd:")) != -1) {
switch (c) {
case 'c':
count = strtoul(optarg, &endptr, 10);
goto check;
struct node *node;
case 'f':
fd = strtoul(optarg, &endptr, 10);
goto check;
SuperNode sn;
case 'w':
hist_warmup = strtoul(optarg, &endptr, 10);
goto check;
/* Test options */
int count = -1; /**< Amount of messages which should be sent (default: -1 for unlimited) */
case 'b':
hist_buckets = strtoul(optarg, &endptr, 10);
goto check;
hist_cnt_t hist_warmup = 100;
int hist_buckets = 20;
case 'V':
print_version();
exit(EXIT_SUCCESS);
/** File descriptor for Matlab results.
* This allows you to write Matlab results in a seperate log file:
*
* ./test etc/example.conf rtt -f 3 3>> measurement_results.m
*/
int fd = STDOUT_FILENO;
case 'd':
logging.setLevel(optarg);
break;
/* Parse Arguments */
int c;
char *endptr;
while ((c = getopt (argc, argv, "w:hr:f:c:b:Vd:")) != -1) {
switch (c) {
case 'c':
count = strtoul(optarg, &endptr, 10);
goto check;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
case 'f':
fd = strtoul(optarg, &endptr, 10);
goto check;
case 'w':
hist_warmup = strtoul(optarg, &endptr, 10);
goto check;
case 'b':
hist_buckets = strtoul(optarg, &endptr, 10);
goto check;
case 'V':
print_version();
exit(EXIT_SUCCESS);
case 'd':
logging.setLevel(optarg);
break;
case 'h':
case '?':
usage();
exit(c == '?' ? EXIT_FAILURE : EXIT_SUCCESS);
}
continue;
check: if (optarg == endptr)
throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg);
}
continue;
if (argc != optind + 2) {
usage();
exit(EXIT_FAILURE);
}
check: if (optarg == endptr)
throw RuntimeError("Failed to parse parse option argument '-{} {}'", c, optarg);
char *uri = argv[optind];
char *nodestr = argv[optind + 1];
ret = utils::signals_init(quit);
if (ret)
throw RuntimeError("Failed to initialize signals subsystem");
if (uri)
sn.parse(uri);
else
logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance.");
node = sn.getNode(nodestr);
if (!node)
throw RuntimeError("There's no node with the name '{}'", nodestr);
ret = node_type_start(node->_vt, reinterpret_cast<super_node *>(&sn));
if (ret)
throw RuntimeError("Failed to start node-type {}: reason={}", node_type_name(node->_vt), ret);
ret = node_prepare(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
ret = node_start(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
ret = hist_init(&hist, hist_buckets, hist_warmup);
if (ret)
throw RuntimeError("Failed to initialize histogram");
/* Print header */
fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", "min", "max", "mean", "stddev");
while (!stop && (count < 0 || count--)) {
clock_gettime(CLOCK_ID, &send);
unsigned release;
release = 1; // release = allocated
node_write(node, &smp_send, 1, &release); /* Ping */
release = 1; // release = allocated
node_read(node, &smp_recv, 1, &release); /* Pong */
clock_gettime(CLOCK_ID, &recv);
double rtt = time_delta(&recv, &send);
if (rtt < 0)
logger->warn("Negative RTT: {}", rtt);
hist_put(&hist, rtt);
smp_send->sequence++;
fprintf(stdout, "%10lu.%06lu%5" PRIu64 "%10.3f%10.3f%10.3f%10.3f%10.3f\n",
recv.tv_sec, recv.tv_nsec / 1000, smp_send->sequence,
1e3 * rtt, 1e3 * hist.lowest, 1e3 * hist.highest,
1e3 * hist_mean(&hist), 1e3 * hist_stddev(&hist));
}
struct stat st;
if (!fstat(fd, &st)) {
FILE *f = fdopen(fd, "w");
hist_dump_matlab(&hist, f);
fclose(f);
}
else
throw RuntimeError("Invalid file descriptor: {}", fd);
hist_print(&hist, 1);
ret = hist_destroy(&hist);
if (ret)
throw RuntimeError("Failed to destroy histogram");
ret = node_stop(node);
if (ret)
throw RuntimeError("Failed to stop node {}: reason={}", node_name(node), ret);
ret = node_type_stop(node->_vt);
if (ret)
throw RuntimeError("Failed to stop node-type {}: reason={}", node_type_name(node->_vt), ret);
delete smp_send;
delete smp_recv;
return 0;
}
catch (std::runtime_error &e) {
logger->error("{}", e.what());
if (argc != optind + 2) {
usage();
exit(EXIT_FAILURE);
return -1;
}
char *uri = argv[optind];
char *nodestr = argv[optind + 1];
ret = utils::signals_init(quit);
if (ret)
throw RuntimeError("Failed to initialize signals subsystem");
if (uri)
sn.parse(uri);
else
logger->warn("No configuration file specified. Starting unconfigured. Use the API to configure this instance.");
node = sn.getNode(nodestr);
if (!node)
throw RuntimeError("There's no node with the name '{}'", nodestr);
ret = node_type_start(node->_vt, reinterpret_cast<super_node *>(&sn));
if (ret)
throw RuntimeError("Failed to start node-type {}: reason={}", node_type_name(node->_vt), ret);
ret = node_prepare(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
ret = node_start(node);
if (ret)
throw RuntimeError("Failed to start node {}: reason={}", node_name(node), ret);
ret = hist_init(&hist, hist_buckets, hist_warmup);
if (ret)
throw RuntimeError("Failed to initialize histogram");
/* Print header */
fprintf(stdout, "%17s%5s%10s%10s%10s%10s%10s\n", "timestamp", "seq", "rtt", "min", "max", "mean", "stddev");
while (!stop && (count < 0 || count--)) {
clock_gettime(CLOCK_ID, &send);
unsigned release;
release = 1; // release = allocated
node_write(node, &smp_send, 1, &release); /* Ping */
release = 1; // release = allocated
node_read(node, &smp_recv, 1, &release); /* Pong */
clock_gettime(CLOCK_ID, &recv);
double rtt = time_delta(&recv, &send);
if (rtt < 0)
logger->warn("Negative RTT: {}", rtt);
hist_put(&hist, rtt);
smp_send->sequence++;
fprintf(stdout, "%10lu.%06lu%5" PRIu64 "%10.3f%10.3f%10.3f%10.3f%10.3f\n",
recv.tv_sec, recv.tv_nsec / 1000, smp_send->sequence,
1e3 * rtt, 1e3 * hist.lowest, 1e3 * hist.highest,
1e3 * hist_mean(&hist), 1e3 * hist_stddev(&hist));
}
struct stat st;
if (!fstat(fd, &st)) {
FILE *f = fdopen(fd, "w");
hist_dump_matlab(&hist, f);
fclose(f);
}
else
throw RuntimeError("Invalid file descriptor: {}", fd);
hist_print(&hist, 1);
ret = hist_destroy(&hist);
if (ret)
throw RuntimeError("Failed to destroy histogram");
ret = node_stop(node);
if (ret)
throw RuntimeError("Failed to stop node {}: reason={}", node_name(node), ret);
ret = node_type_stop(node->_vt);
if (ret)
throw RuntimeError("Failed to stop node-type {}: reason={}", node_type_name(node->_vt), ret);
delete smp_send;
delete smp_recv;
return 0;
}