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:
parent
b67acd52fb
commit
dabb1c5454
8 changed files with 789 additions and 716 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue