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

merge remote version, accept all changes of remote version

This commit is contained in:
Sonja Happ 2019-10-16 13:32:35 +02:00
commit 51527d3403
184 changed files with 4831 additions and 3341 deletions

View file

@ -8,10 +8,8 @@ variables:
DOCKER_TAG: ${CI_COMMIT_REF_NAME}
DOCKER_IMAGE: villas/node
DOCKER_IMAGE_DEV: villas/node-dev
MAKE_OPTS: -j 16
LD_PRELOAD: /usr/lib64/libSegFault.so
SEGFAULT_SIGNALS: all
SEGFAULT_SIGNALS: bus abrt
MAKE_OPTS: -j32
RELEASEVER: 29
stages:
- prepare
@ -31,18 +29,18 @@ before_script:
prepare:fedora:docker-dev:
stage: prepare
script:
- docker build
- docker build ${DOCKER_OPTS}
--file ${DOCKER_FILE}
--tag ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} .
tags:
- shell
- linux
#prepare:raspbian:docker-dev:
# extends: prepare:fedora:docker-dev
# variables:
# DOCKER_FILE: packaging/docker/Dockerfile.dev-raspbian
# DOCKER_IMAGE_DEV: villas/node-dev-raspbian
prepare:raspbian:docker-dev:
extends: prepare:fedora:docker-dev
variables:
DOCKER_FILE: packaging/docker/Dockerfile.dev-raspbian
DOCKER_IMAGE_DEV: villas/node-dev-raspbian
prepare:ubuntu:docker-dev:
extends: prepare:fedora:docker-dev
@ -50,11 +48,24 @@ prepare:ubuntu:docker-dev:
DOCKER_FILE: packaging/docker/Dockerfile.dev-ubuntu
DOCKER_IMAGE_DEV: villas/node-dev-ubuntu
prepare:debian-armhf:docker-dev:
extends: prepare:fedora:docker-dev
variables:
DOCKER_FILE: packaging/docker/Dockerfile.dev-debian-multiarch
DOCKER_IMAGE_DEV: villas/node-dev-debian-armhf
DOCKER_OPTS: --build-arg ARCH=armhf --build-arg TRIPLET=arm-linux-gnueabihf
prepare:debian-arm64:docker-dev:
extends: prepare:fedora:docker-dev
variables:
DOCKER_FILE: packaging/docker/Dockerfile.dev-debian-multiarch
DOCKER_IMAGE_DEV: villas/node-dev-debian-arm64
DOCKER_OPTS: --build-arg ARCH=arm64 --build-arg TRIPLET=aarch64-linux-gnu
# Stage: build
##############################################################################
build:fedora:x86_64:
build:base:
stage: build
script:
- mkdir -p build && cd build
@ -68,22 +79,38 @@ build:fedora:x86_64:
tags:
- docker
build:fedora:x86_64:
extends: build:base
build:fedora-minimal:x86_64:
extends: build:fedora:x86_64
extends: build:base
variables:
CMAKE_OPTS: -DWITH_HOOKS=OFF -DWITH_WEB=OFF -DWITH_API=OFF -DWITH_CONFIG=OFF -DWITH_SRC=OFF -DWITH_TOOLS=OFF -DWITH_TESTS=OFF -DWITH_PLUGINS=OFF -DWITH_CLIENTS=OFF -DWITH_DOC=OFF
build:ubuntu:x86_64:
extends: build:fedora:x86_64
extends: build:base
variables:
LD_PRELOAD: /lib/x86_64-linux-gnu/libSegFault.so
DOCKER_IMAGE_DEV: villas/node-dev-ubuntu
CMAKE_OPTS: -DCMAKE_MODULE_PATH=/usr/local/lib64/cmake -DCMAKE_PREFIX_PATH=/usr/local
#build:raspbian:armv6l:
# extends: build:fedora:x86_64
# variables:
# LD_PRELOAD: /lib/arm-linux-gnueabihf/libSegFault.so
# DOCKER_IMAGE_DEV: villas/node-dev-raspbian
build:raspbian:armv6l:
extends: build:base
variables:
DOCKER_IMAGE_DEV: villas/node-dev-raspbian
CMAKE_OPTS: -DWITH_NODE_INFINIBAND=OFF
when: manual
build:debian-multiarch:armhf:
extends: build:base
variables:
DOCKER_IMAGE_DEV: villas/node-dev-debian-armhf
CMAKE_OPTS: -DCMAKE_TOOLCHAIN_FILE=/debian-armhf.cmake -DCMAKE_INSTALL_LIBDIR=/usr/lib/arm-linux-gnueabihf
build:debian-multiarch:arm64:
extends: build:base
variables:
DOCKER_IMAGE_DEV: villas/node-dev-debian-arm64
CMAKE_OPTS: -DCMAKE_TOOLCHAIN_FILE=/debian-arm64.cmake -DCMAKE_INSTALL_LIBDIR=/usr/lib/aarch64-linux-gnu
build:docs:
stage: build
@ -98,9 +125,6 @@ build:docs:
image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}
tags:
- docker
only:
- tags
- master
# Stage: test
@ -110,6 +134,10 @@ test:unit:
stage: test
dependencies:
- build:fedora:x86_64
variables:
LD_PRELOAD: /usr/lib64/libSegFault.so
SEGFAULT_SIGNALS: all
SEGFAULT_SIGNALS: bus abrt
script:
- mkdir -p build && cd build
- cmake .. && make ${MAKE_OPTS} unit-tests
@ -122,6 +150,10 @@ test:integration:
stage: test
dependencies:
- build:fedora:x86_64
variables:
LD_PRELOAD: /usr/lib64/libSegFault.so
SEGFAULT_SIGNALS: all
SEGFAULT_SIGNALS: bus abrt
script:
- mkdir -p build && cd build
- cmake ..
@ -132,6 +164,7 @@ test:integration:
paths:
- build/tests/integration/
image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}
allow_failure: true
tags:
- docker
@ -154,10 +187,11 @@ packaging:docker:
packaging:rpm:
stage: packaging
dependencies:
- build:docs
- build:fedora:x86_64
script:
- mkdir -p build && cd build
- cmake ..
- make ${MAKE_OPTS} doc
- make ${MAKE_OPTS} package
artifacts:
expire_in: 1 week
@ -168,9 +202,6 @@ packaging:rpm:
image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}
tags:
- docker
only:
- tags
- master
# Stage: deploy
##############################################################################
@ -188,16 +219,24 @@ deploy:web:
tags:
- villas-deploy
deploy:packages:
.deploy:packages: &deploy_packages
stage: deploy
script:
- ssh ${DEPLOY_USER}@${DEPLOY_HOST} mkdir -p ${DEPLOY_PATH}/{dist,../packages}
- rsync ${RSYNC_OPTS} build/*.rpm ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/../packages/x86_64/
- rsync ${RSYNC_OPTS} build/*.tar.gz ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/dist/
- ssh ${DEPLOY_USER}@${DEPLOY_HOST} createrepo ${DEPLOY_PATH}/../packages
- ssh ${DEPLOY_USER}@${DEPLOY_HOST} mkdir -p $${DEPLOY_PATH_PACKAGES}/{fedora/x86_64,dist}
- rsync ${RSYNC_OPTS} build/*.tar.gz ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH_PACKAGES}/dist/
- rsync ${RSYNC_OPTS} build/*.rpm ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH_PACKAGES}/fedora/${RELEASEVER}/x86_64
- ssh ${DEPLOY_USER}@${DEPLOY_HOST} createrepo ${DEPLOY_PATH_PACKAGES}/fedora/${RELEASEVER}/x86_64
dependencies:
- packaging:rpm
tags:
- villas-deploy
deploy:packages:manual:
<<: *deploy_packages
when: manual
deploy:packages:tags:
<<: *deploy_packages
only:
- tags
# Only on version tags
- "/^v\\d+(\\.\\d+)+$/"

View file

@ -129,6 +129,7 @@ cmake_dependent_option(WITH_DOC "Build documentation"
cmake_dependent_option(WITH_NODE_AMQP "Build with amqp node-type" ON "RABBITMQ_C_FOUND" OFF)
cmake_dependent_option(WITH_NODE_COMEDI "Build with comedi node-type" ON "COMEDILIB_FOUND" OFF)
cmake_dependent_option(WITH_NODE_FILE "Build with file node-type" ON "" OFF)
cmake_dependent_option(WITH_NODE_EXEC "Build with exec node-type" ON "" OFF)
cmake_dependent_option(WITH_NODE_IEC61850 "Build with iec61850 node-types" ON "LIBIEC61850_FOUND" OFF)
cmake_dependent_option(WITH_NODE_INFINIBAND "Build with infiniband node-type" ON "IBVERBS_FOUND; RDMACM_FOUND" OFF)
cmake_dependent_option(WITH_NODE_INFLUXDB "Build with influxdb node-type" ON "" OFF)

View file

@ -568,9 +568,9 @@ struct msg
#if BYTE_ORDER == BIG_ENDIAN
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
unsigned rsvd1 : 2; /**< Reserved bits */
unsigned reserved1 : 2; /**< Reserved bits */
#elif BYTE_ORDER == LITTLE_ENDIAN
unsigned rsvd1 : 2; /**< Reserved bits */
unsigned reserved1 : 2; /**< Reserved bits */
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
#else
@ -730,7 +730,8 @@ struct sockaddr_in rec_addr;
msg->version = MSG_VERSION;
msg->type = MSG_TYPE_DATA;
msg->rsvd1 = 0;
msg->reserved1 = 0;
msg->reserved2 = 0;
msg->id = 0;
msg->length = NO_SEND_DATA;
msg->sequence = sequence++;

View file

@ -66,9 +66,9 @@ struct msg
#if BYTE_ORDER == BIG_ENDIAN
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
unsigned rsvd1 : 2; /**< Reserved bits */
unsigned reserved1 : 2; /**< Reserved bits */
#elif BYTE_ORDER == LITTLE_ENDIAN
unsigned rsvd1 : 2; /**< Reserved bits */
unsigned reserved1 : 2; /**< Reserved bits */
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
#else

View file

@ -118,7 +118,8 @@ static void * SendToIPPort(void *arg)
msg->version = MSG_VERSION;
msg->type = MSG_TYPE_DATA;
msg->rsvd1 = 0;
msg->reserved1 = 0;
msg->reserved2 = 0;
msg->id = SendID;
msg->length = cnt;
msg->sequence = Sequence++;

View file

@ -63,7 +63,7 @@ int msg_verify(struct msg *m)
return -1;
else if (m->type != MSG_TYPE_DATA)
return -2;
else if (m->rsvd1 != 0)
else if (m->reserved1 != 0)
return -3;
else
return 0;

View file

@ -23,108 +23,122 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <string.h>
#include <iostream>
#include <atomic>
#include <villas/node/config.h>
#include <villas/log.hpp>
#include <villas/node/exceptions.hpp>
#include <villas/node.h>
#include <villas/pool.h>
#include <villas/sample.h>
#include <villas/shmem.h>
#include <villas/colors.hpp>
#include <villas/tool.hpp>
#include <villas/log.hpp>
#include <villas/utils.hpp>
#include <villas/copyright.hpp>
#include <villas/node/exceptions.hpp>
using namespace villas;
namespace villas {
namespace node {
namespace tools {
static std::atomic<bool> stop(false);
class Shmem : public Tool {
static void usage()
{
std::cout << "Usage: villas-test-shmem WNAME VECTORIZE" << std::endl
<< " WNAME name of the shared memory object for the output queue" << std::endl
<< " RNAME name of the shared memory object for the input queue" << std::endl
<< " VECTORIZE maximum number of samples to read/write at a time" << std::endl;
public:
Shmem(int argc, char *argv[]) :
Tool(argc, argv, "shmem"),
stop(false)
{ }
print_copyright();
}
protected:
std::atomic<bool> stop;
void quit(int, siginfo_t*, void*)
{
stop = true;
}
void usage()
{
std::cout << "Usage: villas-test-shmem WNAME VECTORIZE" << std::endl
<< " WNAME name of the shared memory object for the output queue" << std::endl
<< " RNAME name of the shared memory object for the input queue" << std::endl
<< " VECTORIZE maximum number of samples to read/write at a time" << std::endl;
int main(int argc, char* argv[])
{
int ret, readcnt, writecnt, avail;
Logger logger = logging.get("test-shmem");
struct shmem_int shm;
struct shmem_conf conf = {
.polling = 0,
.queuelen = DEFAULT_SHMEM_QUEUELEN,
.samplelen = DEFAULT_SHMEM_SAMPLELEN
};
if (argc != 4) {
usage();
return 1;
printCopyright();
}
ret = utils::signals_init(quit);
if (ret)
throw RuntimeError("Failed to initialize signals");
char *wname = argv[1];
char *rname = argv[2];
int vectorize = atoi(argv[3]);
ret = shmem_int_open(wname, rname, &shm, &conf);
if (ret < 0)
throw RuntimeError("Failed to open shared-memory interface");
struct sample *insmps[vectorize], *outsmps[vectorize];
while (!stop) {
readcnt = shmem_int_read(&shm, insmps, vectorize);
if (readcnt == -1) {
logger->info("Node stopped, exiting");
break;
}
avail = shmem_int_alloc(&shm, outsmps, readcnt);
if (avail < readcnt)
logger->warn("Pool underrun: %d / %d\n", avail, readcnt);
for (int i = 0; i < avail; i++) {
outsmps[i]->sequence = insmps[i]->sequence;
outsmps[i]->ts = insmps[i]->ts;
int len = MIN(insmps[i]->length, outsmps[i]->capacity);
memcpy(outsmps[i]->data, insmps[i]->data, SAMPLE_DATA_LENGTH(len));
outsmps[i]->length = len;
}
for (int i = 0; i < readcnt; i++)
sample_decref(insmps[i]);
writecnt = shmem_int_write(&shm, outsmps, avail);
if (writecnt < avail)
logger->warn("Short write");
logger->info("Read / Write: {}/{}", readcnt, writecnt);
void handler(int, siginfo_t *, void *)
{
stop = true;
}
ret = shmem_int_close(&shm);
if (ret)
throw RuntimeError("Failed to close shared-memory interface");
int main()
{
int ret, readcnt, writecnt, avail;
logger->info(CLR_GRN("Goodbye!"));
struct shmem_int shm;
struct shmem_conf conf = {
.polling = 0,
.queuelen = DEFAULT_SHMEM_QUEUELEN,
.samplelen = DEFAULT_SHMEM_SAMPLELEN
};
return 0;
if (argc != 4) {
usage();
return 1;
}
std::string wname = argv[1];
std::string rname = argv[2];
int vectorize = atoi(argv[3]);
ret = shmem_int_open(wname.c_str(), rname.c_str(), &shm, &conf);
if (ret < 0)
throw RuntimeError("Failed to open shared-memory interface");
struct sample *insmps[vectorize], *outsmps[vectorize];
while (!stop) {
readcnt = shmem_int_read(&shm, insmps, vectorize);
if (readcnt == -1) {
logger->info("Node stopped, exiting");
break;
}
avail = shmem_int_alloc(&shm, outsmps, readcnt);
if (avail < readcnt)
logger->warn("Pool underrun: %d / %d\n", avail, readcnt);
for (int i = 0; i < avail; i++) {
outsmps[i]->sequence = insmps[i]->sequence;
outsmps[i]->ts = insmps[i]->ts;
int len = MIN(insmps[i]->length, outsmps[i]->capacity);
memcpy(outsmps[i]->data, insmps[i]->data, SAMPLE_DATA_LENGTH(len));
outsmps[i]->length = len;
}
for (int i = 0; i < readcnt; i++)
sample_decref(insmps[i]);
writecnt = shmem_int_write(&shm, outsmps, avail);
if (writecnt < avail)
logger->warn("Short write");
logger->info("Read / Write: {}/{}", readcnt, writecnt);
}
ret = shmem_int_close(&shm);
if (ret)
throw RuntimeError("Failed to close shared-memory interface");
return 0;
}
};
} // namespace tools
} // namespace node
} // namespace villas
int main(int argc, char *argv[])
{
villas::node::tools::Shmem t(argc, argv);
return t.run();
}

View file

@ -0,0 +1,15 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(TRIPLET "aarch64-linux-gnu")
# specify the cross compiler
SET(CMAKE_C_COMPILER "/usr/bin/${TRIPLET}-gcc")
SET(CMAKE_CXX_COMPILER "/usr/bin/${TRIPLET}-g++")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "Buildroot CFLAGS")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}" CACHE STRING "Buildroot CXXFLAGS")
set(CMAKE_EXE_LINKER_FLAGS " ${CMAKE_EXE_LINKER_FLAGS}" CACHE STRING "Buildroot LDFLAGS")
set(CMAKE_LIBRARY_PATH "/usr/lib/${TRIPLET}")

View file

@ -0,0 +1,15 @@
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR armv7l)
set(TRIPLET "arm-linux-gnueabihf")
# specify the cross compiler
SET(CMAKE_C_COMPILER "/usr/bin/${TRIPLET}-gcc")
SET(CMAKE_CXX_COMPILER "/usr/bin/${TRIPLET}-g++")
set(CMAKE_C_FLAGS "-mfloat-abi=hard ${CMAKE_C_FLAGS}" CACHE STRING "Buildroot CFLAGS")
set(CMAKE_CXX_FLAGS "-mfloat-abi=hard ${CMAKE_CXX_FLAGS}" CACHE STRING "Buildroot CXXFLAGS")
set(CMAKE_EXE_LINKER_FLAGS " ${CMAKE_EXE_LINKER_FLAGS}" CACHE STRING "Buildroot LDFLAGS")
set(CMAKE_LIBRARY_PATH "/usr/lib/${TRIPLET}")

2
common

@ -1 +1 @@
Subproject commit 907e81d81b466126c09a91e3cd2b93d138cb6b96
Subproject commit 43fd33c9c77db22b93f65c92a1acb25c141d42a3

View file

@ -0,0 +1,22 @@
@include "hook-nodes.conf"
paths = (
{
in = "signal_node"
out = "file_node"
hooks = (
{
type = "gate"
signal = "square"
mode = "above"
threshold = 0.5
# Once triggered, keep active for:
duration = 5 # in seconds
samples = 100 # in number of samples
}
)
}
)

View file

@ -1,18 +0,0 @@
@include "hook-nodes.conf"
paths = (
{
in = "signal_node"
out = "file_node"
hooks = (
{
type = "scale"
signal = "sine"
scale = 5.5
offset = 1.2
}
)
}
)

View file

@ -0,0 +1,13 @@
nodes = {
exec_node = {
type = "exec"
format = "villas.human"
flush = true
exec = "tee test"
shell = true
working_directory = "/tmp"
environment = {
MYVAR = "TESTVAL"
}
}
}

View file

@ -54,7 +54,7 @@ class Api {
protected:
Logger logger;
enum state state;
enum State state;
std::thread thread;
std::atomic<bool> running; /**< Atomic flag for signalizing thread termination. */

View file

@ -51,7 +51,7 @@ class Socket;
class Server {
protected:
enum state state;
enum State state;
Api *api;
Logger logger;

View file

@ -23,7 +23,6 @@
#pragma once
#include <stdbool.h>
#include <jansson.h>
#include <villas/queue.h>

View file

@ -23,7 +23,7 @@
#pragma once
#include <stdio.h>
#include <cstdio>
/* Forward declarations */
struct sample;

View file

@ -23,7 +23,7 @@
#pragma once
#include <stdlib.h>
#include <cstdlib>
/* Forward declarations. */
struct io;

View file

@ -23,7 +23,7 @@
#pragma once
#include <stdint.h>
#include <cstdint>
/** The current version number for the message format */
#define MSG_VERSION 2
@ -43,10 +43,9 @@
#define MSG_DATA_OFFSET(msg) ((char *) (msg) + offsetof(struct msg, data))
/** The timestamp of a message in struct timespec format */
#define MSG_TS(msg) (struct timespec) { \
.tv_sec = (msg)->ts.sec, \
.tv_nsec = (msg)->ts.nsec \
}
#define MSG_TS(msg, i) \
i.tv_sec = (msg)->ts.sec; \
i.tv_nsec = (msg)->ts.nsec;
/** This message format is used by all clients
*
@ -57,16 +56,16 @@ struct msg
#if BYTE_ORDER == BIG_ENDIAN
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
unsigned rsvd1 : 2; /**< Reserved bits */
unsigned reserved1 : 2; /**< Reserved bits */
#elif BYTE_ORDER == LITTLE_ENDIAN
unsigned rsvd1 : 2; /**< Reserved bits */
unsigned reserved1 : 2; /**< Reserved bits */
unsigned type : 2; /**< Data or control message (see MSG_TYPE_*) */
unsigned version: 4; /**< Specifies the format of the remaining message (see MGS_VERSION) */
#else
#error Invalid byte-order
#endif
uint8_t resv2; /**< An id which identifies the source of this sample. */
uint8_t reserved2; /**< An id which identifies the source of this sample. */
uint16_t length; /**< The number of values in msg::data[]. */
uint32_t sequence; /**< The sequence number is incremented by one for consecutive messages. */

View file

@ -23,7 +23,7 @@
#pragma once
#include <stdlib.h>
#include <cstdlib>
/* Forward declarations */
struct sample;

View file

@ -23,7 +23,7 @@
#pragma once
#include <stdlib.h>
#include <cstdlib>
/* float128 is currently not yet supported as htole128() functions a missing */
#if 0 && defined(__GNUC__) && defined(__linux__)

View file

@ -23,7 +23,7 @@
#pragma once
#include <stdlib.h>
#include <cstdlib>
/* Forward declarations. */
struct sample;

View file

@ -23,7 +23,7 @@
#pragma once
#include <stdio.h>
#include <cstdio>
/* Forward declarations */
struct io;

View file

@ -1,48 +0,0 @@
/** Hook functions
*
* Every node or path can register hook functions which is called for every
* processed sample. This can be used to debug the data flow, get statistics
* or alter the sample contents.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* @addtogroup hooks User-defined hook functions
* @ingroup path
* @{
*********************************************************************************/
#pragma once
enum hook_flags {
HOOK_BUILTIN = (1 << 0), /**< Should we add this hook by default to every path?. */
HOOK_PATH = (1 << 1), /**< This hook type is used by paths. */
HOOK_NODE_READ = (1 << 2), /**< This hook type is used by nodes. */
HOOK_NODE_WRITE = (1 << 3) /**< This hook type is used by nodes. */
};
enum hook_reason {
HOOK_OK,
HOOK_ERROR,
HOOK_SKIP_SAMPLE,
HOOK_STOP_PROCESSING
};

View file

@ -27,7 +27,6 @@
#pragma once
#include <villas/hook.h>
#include <villas/list.h>
#include <villas/signal.h>
#include <villas/log.hpp>
@ -44,21 +43,36 @@ namespace node {
class Hook {
public:
enum class Flags {
BUILTIN = (1 << 0), /**< Should we add this hook by default to every path?. */
PATH = (1 << 1), /**< This hook type is used by paths. */
NODE_READ = (1 << 2), /**< This hook type is used by nodes. */
NODE_WRITE = (1 << 3) /**< This hook type is used by nodes. */
};
enum class Reason {
OK,
ERROR,
SKIP_SAMPLE,
STOP_PROCESSING
};
protected:
Logger logger;
enum state state;
enum State state;
int flags;
int priority; /**< A priority to change the order of execution within one type of hook. */
int enabled; /**< Is this hook active? */
int priority; /**< A priority to change the order of execution within one type of hook. */
int enabled; /**< Is this hook active? */
struct path *path;
struct node *node;
vlist signals;
json_t *cfg; /**< A JSON object containing the configuration of the hook. */
json_t *cfg; /**< A JSON object containing the configuration of the hook. */
public:
Hook(struct path *p, struct node *n, int fl, int prio, bool en = true);
@ -81,42 +95,42 @@ public:
/** Called whenever a hook is started; before threads are created. */
virtual void start()
{
assert(state == STATE_PREPARED);
assert(state == State::PREPARED);
state = STATE_STARTED;
state = State::STARTED;
}
/** Called whenever a hook is stopped; after threads are destoyed. */
virtual void stop()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
state = STATE_STOPPED;
state = State::STOPPED;
}
virtual void check()
{
assert(state == STATE_PARSED);
assert(state == State::PARSED);
state = STATE_CHECKED;
state = State::CHECKED;
}
/** Called periodically. Period is set by global 'stats' option in the configuration file. */
virtual void periodic()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
}
/** Called whenever a new simulation case is started. This is detected by a sequence no equal to zero. */
virtual void restart()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
}
/** Called whenever a sample is processed. */
virtual int process(sample *smp)
virtual Reason process(sample *smp)
{
return HOOK_OK;
return Reason::OK;
};
int getPriority() const
@ -129,7 +143,7 @@ public:
return flags;
}
struct vlist * getSignals()
struct vlist *getSignals()
{
return &signals;
}
@ -149,9 +163,9 @@ public:
void parse()
{
assert(state == STATE_INITIALIZED);
assert(state == State::INITIALIZED);
state = STATE_PARSED;
state = State::PARSED;
}
void init()
@ -170,13 +184,12 @@ protected:
int priority;
public:
HookFactory(const std::string &name, const std::string &desc, int fl, int prio) :
Plugin(name, desc),
flags(fl),
priority(prio)
HookFactory(const std::string &name, const std::string &desc, int fl, int prio) : Plugin(name, desc),
flags(fl),
priority(prio)
{ }
virtual Hook * make(struct path *p, struct node *n) = 0;
virtual Hook *make(struct path *p, struct node *n) = 0;
int getFlags()
{
@ -184,16 +197,17 @@ public:
}
};
template<typename T>
template <typename T>
class HookPlugin : public HookFactory {
public:
using HookFactory::HookFactory;
virtual Hook * make(struct path *p, struct node *n) {
virtual Hook *make(struct path *p, struct node *n)
{
return new T(p, n, flags, priority);
};
};
} // node
} // villas
} // namespace node
} // namespace villas

View file

@ -57,9 +57,9 @@ int hook_list_destroy(struct vlist *hs);
* hooks = [ "print" ]
* }
*/
int hook_list_parse(struct vlist *hs, json_t *cfg, int mask, struct path *p, struct node *n);
void hook_list_parse(struct vlist *hs, json_t *cfg, int mask, struct path *p, struct node *n);
int hook_list_prepare(struct vlist *hs, struct vlist *sigs, int mask, struct path *p, struct node *n);
void hook_list_prepare(struct vlist *hs, struct vlist *sigs, int mask, struct path *p, struct node *n);
int hook_list_prepare_signals(struct vlist *hs, struct vlist *signals);
@ -67,10 +67,10 @@ int hook_list_add(struct vlist *hs, int mask, struct path *p, struct node *n);
int hook_list_process(struct vlist *hs, struct sample *smps[], unsigned cnt);
int hook_list_periodic(struct vlist *hs);
void hook_list_periodic(struct vlist *hs);
int hook_list_start(struct vlist *hs);
void hook_list_start(struct vlist *hs);
int hook_list_stop(struct vlist *hs);
void hook_list_stop(struct vlist *hs);
struct vlist * hook_list_get_signals(struct vlist *hs);

View file

@ -60,7 +60,7 @@ public:
virtual void parse(json_t *cfg);
virtual int process(sample *smp);
virtual Hook::Reason process(sample *smp);
};
} /* namespace node */

View file

@ -58,7 +58,7 @@ public:
virtual void parse(json_t *cfg);
virtual int process(sample *smp);
virtual Hook::Reason process(sample *smp);
};

View file

@ -32,23 +32,23 @@
struct sample;
struct format_type;
enum io_flags {
enum class IOFlags {
/* Bits 0-7 are reserved for for flags defined by enum sample_flags */
IO_FLUSH = (1 << 8), /**< Flush the output stream after each chunk of samples. */
IO_NONBLOCK = (1 << 9), /**< Dont block io_read() while waiting for new samples. */
IO_NEWLINES = (1 << 10), /**< The samples of this format are newline delimited. */
IO_DESTROY_SIGNALS = (1 << 11), /**< Signal descriptors are managed by this IO instance. Destroy them in io_destoy() */
IO_HAS_BINARY_PAYLOAD = (1 << 12) /**< This IO instance en/decodes binary payloads. */
FLUSH = (1 << 8), /**< Flush the output stream after each chunk of samples. */
NONBLOCK = (1 << 9), /**< Dont block io_read() while waiting for new samples. */
NEWLINES = (1 << 10), /**< The samples of this format are newline delimited. */
DESTROY_SIGNALS = (1 << 11), /**< Signal descriptors are managed by this IO instance. Destroy them in io_destoy() */
HAS_BINARY_PAYLOAD = (1 << 12) /**< This IO instance en/decodes binary payloads. */
};
enum io_mode {
IO_MODE_STDIO,
IO_MODE_ADVIO,
IO_MODE_CUSTOM
enum class IOMode {
STDIO,
ADVIO,
CUSTOM
};
struct io {
enum state state;
enum State state;
int flags;
char delimiter; /**< Newline delimiter. */
char separator; /**< Column separator (used by csv and villas.human formats only) */
@ -70,7 +70,7 @@ struct io {
struct vlist *signals; /**< Signal meta data for parsed samples by io_scan() */
bool header_printed;
enum io_mode mode;
enum IOMode mode;
void *_vd;
const struct format_type *_vt;
@ -138,7 +138,7 @@ int io_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, struct
*
* @param buf[out] The buffer which should be filled with serialized data.
* @param len[in] The length of the buffer \p buf.
* @param rbytes[out] The number of bytes which have been written to \p buf. Ignored if NULL.
* @param rbytes[out] The number of bytes which have been written to \p buf. Ignored if nullptr.
* @param smps[in] The array of pointers to samples.
* @param cnt[in] The number of pointers in the array \p smps.
*

View file

@ -32,7 +32,7 @@
#pragma once
#include <stdint.h>
#include <cstdint>
#include <netlink/route/qdisc.h>
#include <netlink/route/classifier.h>

View file

@ -32,7 +32,7 @@
#pragma once
#include <stdint.h>
#include <cstdint>
#include <netlink/route/qdisc.h>
#include <netlink/route/classifier.h>

View file

@ -25,7 +25,7 @@
#include <jansson.h>
#include <villas/stats.h>
#include <villas/stats.hpp>
#include <villas/common.h>
/* Forward declarations */
@ -34,27 +34,27 @@ struct sample;
struct signal;
struct vlist;
enum mapping_type {
MAPPING_TYPE_DATA,
MAPPING_TYPE_STATS,
MAPPING_TYPE_HEADER,
MAPPING_TYPE_TIMESTAMP
enum class MappingType {
DATA,
STATS,
HEADER,
TIMESTAMP
};
enum mapping_header_type {
MAPPING_HEADER_TYPE_LENGTH,
MAPPING_HEADER_TYPE_SEQUENCE
enum class MappingHeaderType {
LENGTH,
SEQUENCE
};
enum mapping_timestamp_type {
MAPPING_TIMESTAMP_TYPE_ORIGIN,
MAPPING_TIMESTAMP_TYPE_RECEIVED
enum class MappingTimestampType {
ORIGIN,
RECEIVED
};
struct mapping_entry {
struct node *node; /**< The node to which this mapping refers. */
enum mapping_type type; /**< The mapping type. Selects one of the union fields below. */
enum MappingType type; /**< The mapping type. Selects one of the union fields below. */
/** The number of values which is covered by this mapping entry.
*
@ -70,16 +70,16 @@ struct mapping_entry {
} data;
struct {
enum stats_metric metric;
enum stats_type type;
enum villas::Stats::Metric metric;
enum villas::Stats::Type type;
} stats;
struct {
enum mapping_header_type type;
enum MappingHeaderType type;
} header;
struct {
enum mapping_timestamp_type type;
enum MappingTimestampType type;
} timestamp;
};
};

View file

@ -23,9 +23,8 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <cstddef>
#include <cstdint>
#include <villas/node/config.h>
#include <villas/memory_type.h>
@ -71,7 +70,7 @@ int memory_lock(size_t lock);
/** Allocate \p len bytes memory of type \p m.
*
* @retval NULL If allocation failed.
* @retval nullptr If allocation failed.
* @retval <>0 If allocation was successful.
*/
void * memory_alloc(struct memory_type *m, size_t len);

View file

@ -23,8 +23,8 @@
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <cstddef>
#include <cstdint>
/* Forward declarations */
struct memory_type;
@ -33,11 +33,11 @@ struct node;
typedef struct memory_allocation * (*memory_allocator_t)(struct memory_type *mem, size_t len, size_t alignment);
typedef int (*memory_deallocator_t)(struct memory_type *mem, struct memory_allocation * ma);
enum memory_type_flags {
MEMORY_MMAP = (1 << 0),
MEMORY_DMA = (1 << 1),
MEMORY_HUGEPAGE = (1 << 2),
MEMORY_HEAP = (1 << 3)
enum class MemoryFlags {
MMAP = (1 << 0),
DMA = (1 << 1),
HUGEPAGE = (1 << 2),
HEAP = (1 << 3)
};
struct memory_type {
@ -60,5 +60,5 @@ struct memory_type * memory_managed(void *ptr, size_t len);
int memory_hugepage_init(int hugepages);
struct memory_type * memory_type_lookup(enum memory_type_flags flags);
struct memory_type * memory_type_lookup(enum MemoryFlags flags);

View file

@ -38,6 +38,7 @@
#include <villas/list.h>
#include <villas/queue.h>
#include <villas/common.h>
#include <villas/stats.hpp>
#if defined(LIBNL3_ROUTE_FOUND) && defined(__linux__)
#define WITH_NETEM
@ -58,7 +59,7 @@ struct node {
char *name; /**< A short identifier of the node, only used for configuration and logging */
int enabled;
enum state state;
enum State state;
char *_name; /**< Singleton: A string used to print to screen. */
char *_name_long; /**< Singleton: A string used to print to screen. */
@ -67,7 +68,7 @@ struct node {
uint64_t sequence; /**< This is a counter of received samples, in case the node-type does not generate sequence numbers itself. */
struct stats *stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */
std::shared_ptr<villas::Stats> stats; /**< Statistic counters. This is a pointer to the statistic hooks private data. */
struct node_direction in, out;
@ -198,6 +199,6 @@ bool node_is_valid_name(const char *name);
bool node_is_enabled(const struct node *n);
struct vlist * node_get_signals(struct node *n, enum node_dir dir);
struct vlist * node_get_signals(struct node *n, enum NodeDir dir);
/** @} */

View file

@ -36,14 +36,14 @@
/* Forward declarations */
struct node;
enum node_dir {
NODE_DIR_IN, /**< VILLASnode is receiving/reading */
NODE_DIR_OUT /**< VILLASnode is sending/writing */
enum class NodeDir {
IN, /**< VILLASnode is receiving/reading */
OUT /**< VILLASnode is sending/writing */
};
struct node_direction {
enum state state;
enum node_dir direction;
enum State state;
enum NodeDir direction;
int enabled;
int builtin; /**< This node should use built-in hooks by default. */
@ -55,7 +55,7 @@ struct node_direction {
json_t *cfg; /**< A JSON object containing the configuration of the node. */
};
int node_direction_init(struct node_direction *nd, enum node_dir dir, struct node *n);
int node_direction_init(struct node_direction *nd, enum NodeDir dir, struct node *n);
int node_direction_parse(struct node_direction *nd, struct node *n, json_t *cfg);

View file

@ -37,8 +37,8 @@
struct node;
struct sample;
enum node_type_flags {
NODE_TYPE_PROVIDES_SIGNALS = (1 << 0)
enum class NodeFlags {
PROVIDES_SIGNALS = (1 << 0)
};
/** C++ like vtable construct for node_types */
@ -46,7 +46,7 @@ struct node_type {
unsigned vectorize; /**< Maximal vector length supported by this node type. Zero is unlimited. */
int flags;
enum state state; /**< State of this node-type. */
enum State state; /**< State of this node-type. */
struct vlist instances; /**< A list of all existing nodes of this type. */

View file

@ -0,0 +1,74 @@
/** Node-type for exec node-types.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/**
* @ingroup node
* @addtogroup exec Execute node-type as a sub-process
* @{
*/
#pragma once
#include <villas/popen.hpp>
#include <villas/io.h>
/* Forward declarations */
struct node;
struct sample;
struct format_type;
/** Node-type for signal generation.
* @see node_type
*/
struct exec {
std::unique_ptr<villas::utils::Popen> proc;
bool flush;
bool shell;
std::string working_dir;
std::string command;
villas::utils::Popen::arg_list arguments;
villas::utils::Popen::env_map environment;
struct format_type *format;
struct io io;
};
/** @see node_type::print */
char * exec_print(struct node *n);
/** @see node_type::parse */
int exec_parse(struct node *n, json_t *cfg);
/** @see node_type::open */
int exec_open(struct node *n);
/** @see node_type::close */
int exec_close(struct node *n);
/** @see node_type::read */
int exec_read(struct node *n, struct sample *smps[], unsigned cnt, unsigned *release);
/** @see node_type::write */
int exec_write(struct node *n, struct sample *smps[], unsigned cnt, unsigned *release);
/** @} */

View file

@ -49,7 +49,7 @@ struct file {
size_t buffer_size_out; /**< Defines size of output stream buffer. No buffer is created if value is set to zero. */
size_t buffer_size_in; /**< Defines size of input stream buffer. No buffer is created if value is set to zero. */
enum epoch {
enum class EpochMode {
DIRECT,
WAIT,
RELATIVE,
@ -57,7 +57,7 @@ struct file {
ORIGINAL
} epoch_mode; /**< Specifies how file::offset is calculated. */
enum eof {
enum class EOFBehaviour {
STOP, /**< Terminate when EOF is reached. */
REWIND, /**< Rewind the file when EOF is reached. */
SUSPEND /**< Blocking wait when EOF is reached. */

View file

@ -29,7 +29,7 @@
#pragma once
#include <stdint.h>
#include <cstdint>
#ifdef __APPLE__
#include <net/ethernet.h>
@ -45,7 +45,7 @@
#include <villas/list.h>
#include <villas/signal.h>
enum iec61850_type {
enum class IEC61850Type {
/* According to IEC 61850-7-2 */
BOOLEAN,
INT8,
@ -73,8 +73,8 @@ enum iec61850_type {
struct iec61850_type_descriptor {
const char *name;
enum iec61850_type iec_type;
enum signal_type type;
enum IEC61850Type iec_type;
enum SignalType type;
unsigned size;
bool publisher;
bool subscriber;
@ -85,7 +85,7 @@ struct iec61850_receiver {
EthernetSocket socket;
enum type {
enum class Type {
GOOSE,
SAMPLED_VALUES
} type;
@ -106,9 +106,9 @@ const struct iec61850_type_descriptor * iec61850_lookup_type(const char *name);
int iec61850_parse_signals(json_t *json_signals, struct vlist *signals, struct vlist *node_signals);
struct iec61850_receiver * iec61850_receiver_lookup(enum iec61850_receiver::type t, const char *intf);
struct iec61850_receiver * iec61850_receiver_lookup(enum iec61850_receiver::Type t, const char *intf);
struct iec61850_receiver * iec61850_receiver_create(enum iec61850_receiver::type t, const char *intf);
struct iec61850_receiver * iec61850_receiver_create(enum iec61850_receiver::Type t, const char *intf);
int iec61850_receiver_start(struct iec61850_receiver *r);

View file

@ -29,7 +29,7 @@
#pragma once
#include <stdint.h>
#include <cstdint>
#include <libiec61850/sv_publisher.h>
#include <libiec61850/sv_subscriber.h>

View file

@ -41,7 +41,7 @@ struct sample;
*/
struct loopback {
int queuelen;
int queueflags;
enum QueueSignalledMode mode;
struct queue_signalled queue;
struct pool pool;
};

View file

@ -55,10 +55,10 @@ struct format_type;
#define RTP_INITIAL_BUFFER_LEN 1500
#define RTP_PACKET_TYPE 21
enum rtp_hook_type {
RTCP_HOOK_DISABLED,
RTCP_HOOK_DECIMATE,
RTCP_HOOK_LIMIT_RATE
enum class RTPHookType {
DISABLED,
DECIMATE,
LIMIT_RATE
};
struct rtp {
@ -84,7 +84,7 @@ struct rtp {
double a;
double b;
enum rtp_hook_type rate_hook_type;
enum RTPHookType rate_hook_type;
villas::node::LimitHook *rate_hook;
villas::dsp::PID rate_pid;

View file

@ -43,7 +43,7 @@ struct signal_generator {
struct task task; /**< Timer for periodic events. */
int rt; /**< Real-time mode? */
enum type {
enum class SignalType {
RANDOM,
SINE,
SQUARE,
@ -51,8 +51,7 @@ struct signal_generator {
RAMP,
COUNTER,
CONSTANT,
MIXED,
INVALID
MIXED
} type; /**< Signal type */
double rate; /**< Sampling rate. */

View file

@ -44,7 +44,7 @@ struct socket {
int sd; /**< The socket descriptor */
int verify_source; /**< Verify the source address of incoming packets against socket::remote. */
enum socket_layer layer; /**< The OSI / IP layer which should be used for this socket */
enum SocketLayer layer; /**< The OSI / IP layer which should be used for this socket */
struct format_type *format;
struct io io;

View file

@ -32,7 +32,7 @@
#include <jansson.h>
#include <villas/node.h>
#include <villas/stats.h>
#include <villas/stats.hpp>
#include <villas/task.h>
#include <villas/list.h>
@ -40,8 +40,8 @@ struct stats_node_signal {
struct node *node;
char *node_str;
enum stats_metric metric;
enum stats_type type;
enum villas::Stats::Metric metric;
enum villas::Stats::Type type;
};
struct stats_node {

View file

@ -53,7 +53,7 @@ struct websocket {
/* Internal datastructures */
struct websocket_connection {
enum state {
enum State {
DESTROYED,
INITIALIZED,
CONNECTING,
@ -63,7 +63,7 @@ struct websocket_connection {
ERROR
} state; /**< The current status of this connection. */
enum mode {
enum class Mode {
CLIENT,
SERVER,
} mode;

View file

@ -29,7 +29,7 @@
#pragma once
#include <stdint.h>
#include <cstdint>
#include <jansson.h>
#include <villas/list.h>
@ -59,7 +59,7 @@ struct zeromq {
} server, client;
} curve;
enum pattern {
enum class Pattern {
PUBSUB,
#ifdef ZMQ_BUILD_DISH
RADIODISH

View file

@ -48,16 +48,16 @@ struct stats;
struct node;
/** The register mode determines under which condition the path is triggered. */
enum path_mode {
PATH_MODE_ANY, /**< The path is triggered whenever one of the sources receives samples. */
PATH_MODE_ALL /**< The path is triggered only after all sources have received at least 1 sample. */
enum class PathMode {
ANY, /**< The path is triggered whenever one of the sources receives samples. */
ALL /**< The path is triggered only after all sources have received at least 1 sample. */
};
/** The datastructure for a path. */
struct path {
enum state state; /**< Path state. */
enum State state; /**< Path state. */
enum path_mode mode; /**< Determines when this path is triggered. */
enum PathMode mode; /**< Determines when this path is triggered. */
struct {
int nfds;
@ -70,6 +70,7 @@ struct path {
struct vlist sources; /**< List of all incoming nodes (struct path_source). */
struct vlist destinations; /**< List of all outgoing nodes (struct path_destination). */
struct vlist mappings; /**< List of all input mappings (struct mapping_entry). */
struct vlist hooks; /**< List of processing hooks (struct hook). */
struct vlist signals; /**< List of signals which this path creates (struct signal). */

View file

@ -30,16 +30,16 @@
extern struct vlist plugins;
enum plugin_type {
PLUGIN_TYPE_NODE,
PLUGIN_TYPE_FORMAT,
enum PluginType {
NODE,
FORMAT,
};
struct plugin {
const char *name;
const char *description;
enum plugin_type type;
enum PluginType type;
union {
struct format_type format;
@ -53,7 +53,7 @@ struct plugin {
#define plugin_name(vt) plugin(vt)->name
#define plugin_description(vt) plugin(vt)->description
void plugin_dump(enum plugin_type type);
void plugin_dump(enum PluginType type);
/** Find registered and loaded plugin with given name and type. */
struct plugin * plugin_lookup(enum plugin_type type, const char *name);
struct plugin * plugin_lookup(enum PluginType type, const char *name);

View file

@ -25,7 +25,7 @@
#pragma once
#include <stddef.h>
#include <cstddef>
#include <sys/types.h>
#include <villas/queue.h>
@ -34,7 +34,7 @@
/** A thread-safe memory pool */
struct pool {
enum state state;
enum State state;
off_t buffer_off; /**< Offset from the struct address to the underlying memory area */
@ -83,7 +83,7 @@ INLINE ssize_t pool_put_many(struct pool *p, void *blocks[], size_t cnt)
INLINE void * pool_get(struct pool *p)
{
void *ptr;
return queue_pull(&p->queue, &ptr) == 1 ? ptr : NULL;
return queue_pull(&p->queue, &ptr) == 1 ? ptr : nullptr;
}
/** Release a memory block back to the pool. */

View file

@ -35,8 +35,8 @@
#include <atomic>
#include <stddef.h>
#include <stdint.h>
#include <cstddef>
#include <cstdint>
#include <unistd.h>
#include <villas/common.h>
@ -54,7 +54,7 @@ struct queue_cell {
/** A lock-free multiple-producer, multiple-consumer (MPMC) queue. */
struct queue {
std::atomic<enum state> state;
std::atomic<enum State> state;
cacheline_pad_t _pad0; /**< Shared area: all threads read */

View file

@ -27,27 +27,27 @@
#include <villas/queue.h>
enum queue_signalled_flags {
/* Mode */
QUEUE_SIGNALLED_AUTO = (0 << 0), /**< We will choose the best method available on the platform */
QUEUE_SIGNALLED_PTHREAD = (1 << 0),
QUEUE_SIGNALLED_POLLING = (2 << 0),
enum class QueueSignalledMode {
AUTO, /**< We will choose the best method available on the platform */
PTHREAD,
POLLING,
#ifdef HAS_EVENTFD
QUEUE_SIGNALLED_EVENTFD = (3 << 0),
EVENTFD,
#elif defined(__APPLE__)
QUEUE_SIGNALLED_PIPE = (3 << 0),
PIPE,
#endif
QUEUE_SIGNALLED_MASK = 0xf,
};
/* Other flags */
QUEUE_SIGNALLED_PROCESS_SHARED = (1 << 4)
enum class QueueSignalledFlags {
PROCESS_SHARED = (1 << 4)
};
/** Wrapper around queue that uses POSIX CV's for signalling writes. */
struct queue_signalled {
struct queue queue; /**< Actual underlying queue. */
enum queue_signalled_flags mode;
enum QueueSignalledMode mode;
enum QueueSignalledFlags flags;
union {
struct {
@ -64,7 +64,7 @@ struct queue_signalled {
#define queue_signalled_available(q) queue_available(&((q)->queue))
int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memory_type *mem, int flags);
int queue_signalled_init(struct queue_signalled *qs, size_t size, struct memory_type *mem, enum QueueSignalledMode mode = QueueSignalledMode::AUTO, int flags = 0);
int queue_signalled_destroy(struct queue_signalled *qs);

View file

@ -25,10 +25,10 @@
#include <atomic>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <villas/signal.h>
@ -48,16 +48,16 @@ struct pool;
#define SAMPLE_DATA_OFFSET(smp) ((char *) (smp) + offsetof(struct sample, data))
/** Parts of a sample that can be serialized / de-serialized by the IO formats */
enum sample_flags {
SAMPLE_HAS_TS_ORIGIN = (1 << 0), /**< Include origin timestamp in output. */
SAMPLE_HAS_TS_RECEIVED = (1 << 1), /**< Include receive timestamp in output. */
SAMPLE_HAS_OFFSET = (1 << 2), /**< Include offset (received - origin timestamp) in output. */
SAMPLE_HAS_SEQUENCE = (1 << 3), /**< Include sequence number in output. */
SAMPLE_HAS_DATA = (1 << 4), /**< Include values in output. */
SAMPLE_HAS_ALL = (1 << 5) - 1, /**< Enable all output options. */
enum class SampleFlags {
HAS_TS_ORIGIN = (1 << 0), /**< Include origin timestamp in output. */
HAS_TS_RECEIVED = (1 << 1), /**< Include receive timestamp in output. */
HAS_OFFSET = (1 << 2), /**< Include offset (received - origin timestamp) in output. */
HAS_SEQUENCE = (1 << 3), /**< Include sequence number in output. */
HAS_DATA = (1 << 4), /**< Include values in output. */
HAS_ALL = (1 << 5) - 1, /**< Enable all output options. */
SAMPLE_IS_FIRST = (1 << 16), /**< This sample is the first of a new simulation case */
SAMPLE_IS_LAST = (1 << 17) /**< This sample is the last of a running simulation case */
IS_FIRST = (1 << 16), /**< This sample is the first of a new simulation case */
IS_LAST = (1 << 17) /**< This sample is the last of a running simulation case */
};
struct sample {
@ -93,7 +93,7 @@ struct sample {
#define SAMPLE_NON_POOL PTRDIFF_MIN
/** Get the address of the pool to which the sample belongs. */
#define sample_pool(s) ((s)->pool_off == SAMPLE_NON_POOL ? NULL : (struct pool *) ((char *) (s) + (s)->pool_off))
#define sample_pool(s) ((s)->pool_off == SAMPLE_NON_POOL ? nullptr : (struct pool *) ((char *) (s) + (s)->pool_off))
struct sample * sample_alloc(struct pool *p);
@ -130,7 +130,7 @@ int sample_copy_many(struct sample *dsts[], struct sample *srcs[], int cnt);
int sample_incref_many(struct sample *smps[], int cnt);
int sample_decref_many(struct sample *smps[], int cnt);
enum signal_type sample_format(const struct sample *s, unsigned idx);
enum SignalType sample_format(const struct sample *s, unsigned idx);
void sample_data_insert(struct sample *smp, const union signal_data *src, size_t offset, size_t len);

View file

@ -23,12 +23,13 @@
#pragma once
#include <atomic>
#include <jansson.h>
#include <complex.h>
#include <stdint.h>
#include <stdbool.h>
#include <limits>
#include <atomic>
#include <complex>
#include <cstdint>
/* "I" defined by complex.h collides with a define in OpenSSL */
#undef I
@ -43,18 +44,30 @@ struct mapping_entry;
* Data is in host endianess!
*/
union signal_data {
double f; /**< Floating point values. */
int64_t i; /**< Integer values. */
bool b; /**< Boolean values. */
float _Complex z; /**< Complex values. */
double f; /**< Floating point values. */
int64_t i; /**< Integer values. */
bool b; /**< Boolean values. */
std::complex<float> z; /**< Complex values. */
signal_data()
{ }
static union signal_data nan()
{
union signal_data d;
d.f = std::numeric_limits<double>::quiet_NaN();
return d;
}
};
enum signal_type {
SIGNAL_TYPE_INVALID = 0, /**< Signal type is invalid. */
SIGNAL_TYPE_FLOAT = 1, /**< See signal_data::f */
SIGNAL_TYPE_INTEGER = 2, /**< See signal_data::i */
SIGNAL_TYPE_BOOLEAN = 3, /**< See signal_data::b */
SIGNAL_TYPE_COMPLEX = 4 /**< See signal_data::z */
enum class SignalType {
INVALID = 0, /**< Signal type is invalid. */
FLOAT = 1, /**< See signal_data::f */
INTEGER = 2, /**< See signal_data::i */
BOOLEAN = 3, /**< See signal_data::b */
COMPLEX = 4 /**< See signal_data::z */
};
/** Signal descriptor.
@ -71,7 +84,7 @@ struct signal {
std::atomic<int> refcnt; /**< Reference counter. */
enum signal_type type;
enum SignalType type;
};
/** Initialize a signal with default values. */
@ -81,7 +94,7 @@ int signal_init(struct signal *s);
int signal_destroy(struct signal *s);
/** Allocate memory for a new signal, and initialize it with provided values. */
struct signal * signal_create(const char *name, const char *unit, enum signal_type fmt);
struct signal * signal_create(const char *name, const char *unit, enum SignalType fmt);
/** Destroy and release memory of signal. */
int signal_free(struct signal *s);
@ -104,28 +117,27 @@ int signal_init_from_mapping(struct signal *s, const struct mapping_entry *me, u
int signal_list_init(struct vlist *list);
int signal_list_destroy(struct vlist *list);
int signal_list_parse(struct vlist *list, json_t *cfg);
int signal_list_generate(struct vlist *list, unsigned len, enum signal_type fmt);
int signal_list_generate(struct vlist *list, unsigned len, enum SignalType fmt);
int signal_list_generate2(struct vlist *list, const char *dt);
void signal_list_dump(const struct vlist *list, const union signal_data *data, unsigned len);
int signal_list_copy(struct vlist *dst, const struct vlist *src);
enum signal_type signal_type_from_str(const char *str);
enum SignalType signal_type_from_str(const char *str);
enum signal_type signal_type_from_fmtstr(char c);
enum SignalType signal_type_from_fmtstr(char c);
const char * signal_type_to_str(enum signal_type fmt);
const char * signal_type_to_str(enum SignalType fmt);
enum signal_type signal_type_detect(const char *val);
enum SignalType signal_type_detect(const char *val);
/** Convert signal data from one description/format to another. */
void signal_data_cast(union signal_data *data, const struct signal *from, const struct signal *to);
/** Print value of a signal to a character buffer. */
int signal_data_snprint(const union signal_data *data, const struct signal *sig, char *buf, size_t len);
int signal_data_print_str(const union signal_data *data, const struct signal *sig, char *buf, size_t len);
int signal_data_parse_str(union signal_data *data, const struct signal *sig, const char *ptr, char **end);
int signal_data_parse_json(union signal_data *data, const struct signal *sig, json_t *cfg);
void signal_data_set(union signal_data *data, const struct signal *sig, double val);

View file

@ -37,11 +37,11 @@
#include <netinet/ether.h>
#endif /* LIBNL3_ROUTE_FOUND */
enum socket_layer {
SOCKET_LAYER_ETH,
SOCKET_LAYER_IP,
SOCKET_LAYER_UDP,
SOCKET_LAYER_UNIX
enum class SocketLayer {
ETH,
IP,
UDP,
UNIX
};
union sockaddr_union {
@ -79,6 +79,6 @@ char * socket_print_addr(struct sockaddr *saddr);
* @retval 0 Success. Everything went well.
* @retval <0 Error. Something went wrong.
*/
int socket_parse_address(const char *str, struct sockaddr *sa, enum socket_layer layer, int flags);
int socket_parse_address(const char *str, struct sockaddr *sa, enum SocketLayer layer, int flags);
int socket_compare_addr(struct sockaddr *x, struct sockaddr *y);

View file

@ -1,120 +0,0 @@
/** Statistic collection.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
#include <stdint.h>
#include <jansson.h>
#include <villas/common.h>
#include <villas/hist.hpp>
#include <villas/signal.h>
/* Forward declarations */
struct sample;
struct node;
enum stats_format {
STATS_FORMAT_HUMAN,
STATS_FORMAT_JSON,
STATS_FORMAT_MATLAB
};
enum stats_metric {
STATS_METRIC_INVALID = -1,
STATS_METRIC_SMPS_SKIPPED, /**< Counter for skipped samples due to hooks. */
STATS_METRIC_SMPS_REORDERED, /**< Counter for reordered samples. */
/* Timings */
STATS_METRIC_GAP_SAMPLE, /**< Histogram for inter sample timestamps (as sent by remote). */
STATS_METRIC_GAP_RECEIVED, /**< Histogram for inter sample arrival time (as seen by this instance). */
STATS_METRIC_OWD, /**< Histogram for one-way-delay (OWD) of received samples. */
STATS_METRIC_AGE, /**< Processing time of packets within VILLASnode. */
/* RTP metrics */
STATS_METRIC_RTP_LOSS_FRACTION, /**< Fraction lost since last RTP SR/RR. */
STATS_METRIC_RTP_PKTS_LOST, /**< Cumul. no. pkts lost. */
STATS_METRIC_RTP_JITTER, /**< Interarrival jitter. */
/* Always last */
STATS_METRIC_COUNT /**< Just here to have an updated number of statistics. */
};
enum stats_type {
STATS_TYPE_INVALID = -1,
STATS_TYPE_LAST,
STATS_TYPE_HIGHEST,
STATS_TYPE_LOWEST,
STATS_TYPE_MEAN,
STATS_TYPE_VAR,
STATS_TYPE_STDDEV,
STATS_TYPE_TOTAL,
STATS_TYPE_COUNT
};
struct stats_metric_description {
const char *name;
enum stats_metric metric;
const char *unit;
const char *desc;
};
struct stats_type_description {
const char *name;
enum stats_type type;
enum signal_type signal_type;
};
struct stats {
enum state state;
struct hist histograms[STATS_METRIC_COUNT];
};
extern struct stats_metric_description stats_metrics[];
extern struct stats_type_description stats_types[];
int stats_lookup_format(const char *str);
enum stats_metric stats_lookup_metric(const char *str);
enum stats_type stats_lookup_type(const char *str);
int stats_init(struct stats *s, int buckets, int warmup);
int stats_destroy(struct stats *s);
void stats_update(struct stats *s, enum stats_metric id, double val);
json_t * stats_json(struct stats *s);
void stats_reset(struct stats *s);
void stats_print_header(enum stats_format fmt);
void stats_print_periodic(struct stats *s, FILE *f, enum stats_format fmt, struct node *p);
void stats_print(struct stats *s, FILE *f, enum stats_format fmt, int verbose);
union signal_data stats_get_value(const struct stats *s, enum stats_metric sm, enum stats_type st);

132
include/villas/stats.hpp Normal file
View file

@ -0,0 +1,132 @@
/** Statistic collection.
*
* @file
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#pragma once
#include <cstdint>
#include <jansson.h>
#include <unordered_map>
#include <memory>
#include <string>
#include <villas/common.h>
#include <villas/hist.hpp>
#include <villas/table.hpp>
#include <villas/signal.h>
/* Forward declarations */
struct sample;
struct node;
namespace villas {
class Stats {
public:
enum class Format {
HUMAN,
JSON,
MATLAB
};
enum class Metric {
SMPS_SKIPPED, /**< Counter for skipped samples due to hooks. */
SMPS_REORDERED, /**< Counter for reordered samples. */
/* Timings */
GAP_SAMPLE, /**< Histogram for inter sample timestamps (as sent by remote). */
GAP_RECEIVED, /**< Histogram for inter sample arrival time (as seen by this instance). */
OWD, /**< Histogram for one-way-delay (OWD) of received samples. */
AGE, /**< Processing time of packets within VILLASnode. */
/* RTP metrics */
RTP_LOSS_FRACTION, /**< Fraction lost since last RTP SR/RR. */
RTP_PKTS_LOST, /**< Cumul. no. pkts lost. */
RTP_JITTER /**< Interarrival jitter. */
};
enum class Type {
LAST,
HIGHEST,
LOWEST,
MEAN,
VAR,
STDDEV,
TOTAL
};
protected:
std::unordered_map<Metric, villas::Hist> histograms;
struct MetricDescription {
const char *name;
const char *unit;
const char *desc;
};
struct TypeDescription {
const char *name;
enum SignalType signal_type;
};
static std::shared_ptr<Table> table;
static void setupTable();
public:
Stats(int buckets, int warmup);
static
enum Format lookupFormat(const std::string &str);
static
enum Metric lookupMetric(const std::string &str);
static
enum Type lookupType(const std::string &str);
void update(enum Metric id, double val);
void reset();
json_t * toJson() const;
static
void printHeader(enum Format fmt);
void printPeriodic(FILE *f, enum Format fmt, struct node *p) const;
void print(FILE *f, enum Format fmt, int verbose) const;
union signal_data getValue(enum Metric sm, enum Type st) const;
const villas::Hist & getHistogram(enum Metric sm) const;
static std::unordered_map<Metric, MetricDescription> metrics;
static std::unordered_map<Type, TypeDescription> types;
static std::vector<TableColumn> columns;
};
} /* namespace villas */

View file

@ -42,7 +42,7 @@ namespace node {
class SuperNode {
protected:
enum state state;
enum State state;
int idleStop;
@ -111,7 +111,7 @@ public:
/** Run periodic hooks of this super node. */
int periodic();
void setState(enum state st)
void setState(enum State st)
{
state = st;
}
@ -134,7 +134,7 @@ public:
return &interfaces;
}
enum state getState() {
enum State getState() {
return state;
}

View file

@ -41,7 +41,7 @@ class Api;
class Web {
protected:
enum state state;
enum State state;
Logger logger;
@ -93,7 +93,7 @@ public:
return vhost;
}
enum state getState() const
enum State getState() const
{
return state;
}

View file

@ -67,6 +67,15 @@ set(LIB_SRC
format_type.cpp
)
if(WITH_WEB)
list(APPEND LIB_SRC
web.cpp
)
list(APPEND INCLUDE_DIRS ${LIBWEBSOCKETS_INCLUDE_DIRS})
list(APPEND LIBRARIES PkgConfig::LIBWEBSOCKETS ${LIBWEBSOCKETS_LDFLAGS})
endif()
if(WITH_NODE_INFINIBAND)
list(APPEND LIB_SRC memory/ib.cpp)
endif()
@ -92,15 +101,6 @@ if(WITH_HOOKS)
list(APPEND WHOLE_ARCHIVES hooks)
endif()
if(WITH_WEB)
list(APPEND LIB_SRC
web.cpp
)
list(APPEND INCLUDE_DIRS ${LIBWEBSOCKETS_INCLUDE_DIRS})
list(APPEND LIBRARIES PkgConfig::LIBWEBSOCKETS)
endif()
if(WITH_API)
list(APPEND LIB_SRC
api.cpp

View file

@ -33,7 +33,7 @@ using namespace villas::node;
using namespace villas::node::api;
Api::Api(SuperNode *sn) :
state(STATE_INITIALIZED),
state(State::INITIALIZED),
super_node(sn),
server(this)
{
@ -42,12 +42,12 @@ Api::Api(SuperNode *sn) :
Api::~Api()
{
assert(state != STATE_STARTED);
assert(state != State::STARTED);
}
void Api::start()
{
assert(state != STATE_STARTED);
assert(state != State::STARTED);
logger->info("Starting sub-system");
@ -56,12 +56,12 @@ void Api::start()
running = true;
thread = std::thread(&Api::worker, this);
state = STATE_STARTED;
state = State::STARTED;
}
void Api::stop()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
logger->info("Stopping sub-system");
@ -79,7 +79,7 @@ void Api::stop()
server.stop();
state = STATE_STOPPED;
state = State::STOPPED;
}
void Api::run()

View file

@ -25,7 +25,7 @@
#include <villas/super_node.hpp>
#include <villas/node.h>
#include <villas/utils.hpp>
#include <villas/stats.h>
#include <villas/stats.hpp>
#include <villas/api/action.hpp>
#include <villas/api/session.hpp>
@ -58,7 +58,7 @@ public:
);
if (n->stats)
json_object_set_new(json_node, "stats", stats_json(n->stats));
json_object_set_new(json_node, "stats", n->stats->toJson());
/* Add all additional fields of node here.
* This can be used for metadata */

View file

@ -99,7 +99,7 @@ public:
return ret;
/* Properly terminate current instance */
killme(SIGTERM);
utils::killme(SIGTERM);
return 0;
}

View file

@ -36,7 +36,7 @@ public:
virtual int execute(json_t *args, json_t **resp)
{
killme(SIGTERM);
utils::killme(SIGTERM);
return 0;
}

View file

@ -24,7 +24,7 @@
#include <villas/log.h>
#include <villas/node.h>
#include <villas/stats.h>
#include <villas/stats.hpp>
#include <villas/super_node.hpp>
#include <villas/utils.hpp>
#include <villas/api/session.hpp>
@ -58,7 +58,7 @@ public:
if (n->stats) {
if (reset) {
stats_reset(n->stats);
n->stats->reset();
info("Stats resetted for node %s", node_name(n));
}
}

View file

@ -50,7 +50,7 @@ using namespace villas::node::api;
#endif
Server::Server(Api *a) :
state(STATE_INITIALIZED),
state(State::INITIALIZED),
api(a)
{
logger = logging.get("api:server");
@ -58,14 +58,14 @@ Server::Server(Api *a) :
Server::~Server()
{
assert(state != STATE_STARTED);
assert(state != State::STARTED);
}
void Server::start()
{
int ret;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
sd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sd < 0)
@ -90,7 +90,7 @@ void Server::start()
logger->info("Listening on UNIX socket: {}", sun.sun_path);
state = STATE_STARTED;
state = State::STARTED;
}
struct sockaddr_un Server::getSocketAddress()
@ -129,20 +129,20 @@ void Server::stop()
{
int ret;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
ret = close(sd);
if (ret)
throw SystemError("Failed to close API socket");;
state = STATE_STOPPED;
state = State::STOPPED;
}
void Server::run(int timeout)
{
int ret;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
auto len = pfds.size();

View file

@ -23,7 +23,7 @@
#include <iostream>
#include <fstream>
#include <string.h>
#include <cstring>
#include <villas/node/config.h>
#include <villas/config_helper.hpp>

View file

@ -20,8 +20,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <cstdlib>
#include <cstdio>
#include <villas/plugin.h>
#include <villas/format_type.h>
@ -30,7 +30,7 @@ struct format_type * format_type_lookup(const char *name)
{
struct plugin *p;
p = plugin_lookup(PLUGIN_TYPE_FORMAT, name);
p = plugin_lookup(PluginType::FORMAT, name);
if (!p)
return nullptr;

View file

@ -20,9 +20,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <ctype.h>
#include <inttypes.h>
#include <string.h>
#include <cctype>
#include <cinttypes>
#include <cstring>
#include <villas/io.h>
#include <villas/formats/csv.h>
@ -31,40 +31,42 @@
#include <villas/signal.h>
#include <villas/timing.h>
using namespace villas::utils;
static size_t csv_sprint_single(struct io *io, char *buf, size_t len, const struct sample *smp)
{
size_t off = 0;
struct signal *sig;
if (io->flags & SAMPLE_HAS_TS_ORIGIN) {
if (io->flags & SAMPLE_HAS_TS_ORIGIN)
if (io->flags & (int) SampleFlags::HAS_TS_ORIGIN) {
if (io->flags & (int) SampleFlags::HAS_TS_ORIGIN)
off += snprintf(buf + off, len - off, "%ld%c%09ld", smp->ts.origin.tv_sec, io->separator, smp->ts.origin.tv_nsec);
else
off += snprintf(buf + off, len - off, "nan%cnan", io->separator);
}
if (io->flags & SAMPLE_HAS_OFFSET) {
if ((smp->flags & SAMPLE_HAS_TS_RECEIVED) && (smp->flags & SAMPLE_HAS_TS_RECEIVED))
if (io->flags & (int) SampleFlags::HAS_OFFSET) {
if ((smp->flags & (int) SampleFlags::HAS_TS_RECEIVED) && (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED))
off += snprintf(buf + off, len - off, "%c%.09f", io->separator, time_delta(&smp->ts.origin, &smp->ts.received));
else
off += snprintf(buf + off, len - off, "%cnan", io->separator);
}
if (io->flags & SAMPLE_HAS_SEQUENCE) {
if (smp->flags & SAMPLE_HAS_SEQUENCE)
if (io->flags & (int) SampleFlags::HAS_SEQUENCE) {
if (smp->flags & (int) SampleFlags::HAS_SEQUENCE)
off += snprintf(buf + off, len - off, "%c%" PRIu64, io->separator, smp->sequence);
else
off += snprintf(buf + off, len - off, "%cnan", io->separator);
}
if (io->flags & SAMPLE_HAS_DATA) {
if (io->flags & (int) SampleFlags::HAS_DATA) {
for (unsigned i = 0; i < smp->length; i++) {
sig = (struct signal *) vlist_at_safe(smp->signals, i);
if (!sig)
break;
off += snprintf(buf + off, len - off, "%c", io->separator);
off += signal_data_snprint(&smp->data[i], sig, buf + off, len - off);
off += signal_data_print_str(&smp->data[i], sig, buf + off, len - off);
}
}
@ -97,7 +99,7 @@ static size_t csv_sscan_single(struct io *io, const char *buf, size_t len, struc
ptr = end + 1;
smp->flags |= SAMPLE_HAS_TS_ORIGIN;
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN;
offset = strtof(ptr, &end);
if (end == ptr || *end == io->delimiter)
@ -109,7 +111,7 @@ static size_t csv_sscan_single(struct io *io, const char *buf, size_t len, struc
if (end == ptr || *end == io->delimiter)
goto out;
smp->flags |= SAMPLE_HAS_SEQUENCE;
smp->flags |= (int) SampleFlags::HAS_SEQUENCE;
for (ptr = end + 1, i = 0; i < smp->capacity; ptr = end + 1, i++) {
@ -130,7 +132,7 @@ out: if (*end == io->delimiter)
smp->length = i;
if (smp->length > 0)
smp->flags |= SAMPLE_HAS_DATA;
smp->flags |= (int) SampleFlags::HAS_DATA;
return end - buf;
}
@ -168,16 +170,16 @@ void csv_header(struct io *io, const struct sample *smp)
FILE *f = io_stream_output(io);
fprintf(f, "# ");
if (io->flags & SAMPLE_HAS_TS_ORIGIN)
if (io->flags & (int) SampleFlags::HAS_TS_ORIGIN)
fprintf(f, "secs%cnsecs%c", io->separator, io->separator);
if (io->flags & SAMPLE_HAS_OFFSET)
if (io->flags & (int) SampleFlags::HAS_OFFSET)
fprintf(f, "offset%c", io->separator);
if (io->flags & SAMPLE_HAS_SEQUENCE)
if (io->flags & (int) SampleFlags::HAS_SEQUENCE)
fprintf(f, "sequence%c", io->separator);
if (io->flags & SAMPLE_HAS_DATA) {
if (io->flags & (int) SampleFlags::HAS_DATA) {
for (unsigned i = 0; i < smp->length; i++) {
struct signal *sig = (struct signal *) vlist_at(smp->signals, i);
@ -199,48 +201,48 @@ void csv_header(struct io *io, const struct sample *smp)
static struct plugin p1;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p1.name = "tsv";
p1.description = "Tabulator-separated values";
p1.type = PLUGIN_TYPE_FORMAT;
p1.type = PluginType::FORMAT;
p1.format.header = csv_header;
p1.format.sprint = csv_sprint;
p1.format.sscan = csv_sscan;
p1.format.size = 0;
p1.format.flags = IO_NEWLINES |
SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
p1.format.flags = (int) IOFlags::NEWLINES |
(int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
p1.format.separator = '\t';
vlist_push(&plugins, &p1);
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
vlist_remove_all(&plugins, &p1);
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p1);
}
static struct plugin p2;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
vlist_init(&plugins);
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p2.name = "csv";
p2.description = "Comma-separated values";
p2.type = PLUGIN_TYPE_FORMAT;
p2.type = PluginType::FORMAT;
p2.format.header = csv_header;
p2.format.sprint = csv_sprint;
p2.format.sscan = csv_sscan;
p2.format.size = 0;
p2.format.flags = IO_NEWLINES |
SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
p2.format.flags = (int) IOFlags::NEWLINES |
(int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
p2.format.separator = ',';
vlist_push(&plugins, &p2);
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
vlist_remove_all(&plugins, &p2);
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p2);
}

View file

@ -27,26 +27,26 @@
#include <villas/io.h>
#include <villas/formats/json.h>
static enum signal_type json_detect_format(json_t *val)
static enum SignalType json_detect_format(json_t *val)
{
int type = json_typeof(val);
switch (type) {
case JSON_REAL:
return SIGNAL_TYPE_FLOAT;
return SignalType::FLOAT;
case JSON_INTEGER:
return SIGNAL_TYPE_INTEGER;
return SignalType::INTEGER;
case JSON_TRUE:
case JSON_FALSE:
return SIGNAL_TYPE_BOOLEAN;
return SignalType::BOOLEAN;
case JSON_OBJECT:
return SIGNAL_TYPE_COMPLEX; /* must be a complex number */
return SignalType::COMPLEX; /* must be a complex number */
default:
return SIGNAL_TYPE_INVALID;
return SignalType::INVALID;
}
}
@ -60,13 +60,13 @@ static json_t * json_pack_timestamps(struct io *io, struct sample *smp)
const char *fmt = "[ I, I ]";
#endif
if (io->flags & SAMPLE_HAS_TS_ORIGIN) {
if (smp->flags & SAMPLE_HAS_TS_ORIGIN)
if (io->flags & (int) SampleFlags::HAS_TS_ORIGIN) {
if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN)
json_object_set(json_ts, "origin", json_pack(fmt, smp->ts.origin.tv_sec, smp->ts.origin.tv_nsec));
}
if (io->flags & SAMPLE_HAS_TS_RECEIVED) {
if (smp->flags & SAMPLE_HAS_TS_RECEIVED)
if (io->flags & (int) SampleFlags::HAS_TS_RECEIVED) {
if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)
json_object_set(json_ts, "received", json_pack(fmt, smp->ts.received.tv_sec, smp->ts.received.tv_nsec));
}
@ -77,8 +77,8 @@ static int json_unpack_timestamps(json_t *json_ts, struct sample *smp)
{
int ret;
json_error_t err;
json_t *json_ts_origin = NULL;
json_t *json_ts_received = NULL;
json_t *json_ts_origin = nullptr;
json_t *json_ts_received = nullptr;
json_unpack_ex(json_ts, &err, 0, "{ s?: o, s?: o }",
"origin", &json_ts_origin,
@ -90,7 +90,7 @@ static int json_unpack_timestamps(json_t *json_ts, struct sample *smp)
if (ret)
return ret;
smp->flags |= SAMPLE_HAS_TS_ORIGIN;
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN;
}
if (json_ts_received) {
@ -98,7 +98,7 @@ static int json_unpack_timestamps(json_t *json_ts, struct sample *smp)
if (ret)
return ret;
smp->flags |= SAMPLE_HAS_TS_RECEIVED;
smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED;
}
return 0;
@ -111,42 +111,42 @@ static int json_pack_sample(struct io *io, json_t **j, struct sample *smp)
json_smp = json_pack_ex(&err, 0, "{ s: o }", "ts", json_pack_timestamps(io, smp));
if (io->flags & SAMPLE_HAS_SEQUENCE) {
if (smp->flags & SAMPLE_HAS_SEQUENCE) {
if (io->flags & (int) SampleFlags::HAS_SEQUENCE) {
if (smp->flags & (int) SampleFlags::HAS_SEQUENCE) {
json_t *json_sequence = json_integer(smp->sequence);
json_object_set(json_smp, "sequence", json_sequence);
}
}
if (io->flags & SAMPLE_HAS_DATA) {
if (io->flags & (int) SampleFlags::HAS_DATA) {
json_t *json_data = json_array();
for (unsigned i = 0; i < smp->length; i++) {
enum signal_type fmt = sample_format(smp, i);
enum SignalType fmt = sample_format(smp, i);
json_t *json_value;
switch (fmt) {
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
json_value = json_integer(smp->data[i].i);
break;
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
json_value = json_real(smp->data[i].f);
break;
case SIGNAL_TYPE_BOOLEAN:
case SignalType::BOOLEAN:
json_value = json_boolean(smp->data[i].b);
break;
case SIGNAL_TYPE_COMPLEX:
case SignalType::COMPLEX:
json_value = json_pack("{ s: f, s: f }",
"real", creal(smp->data[i].z),
"imag", cimag(smp->data[i].z)
"real", std::real(smp->data[i].z),
"imag", std::imag(smp->data[i].z)
);
break;
case SIGNAL_TYPE_INVALID:
case SignalType::INVALID:
return -1;
}
@ -185,7 +185,7 @@ static int json_unpack_sample(struct io *io, json_t *json_smp, struct sample *sm
{
int ret;
json_error_t err;
json_t *json_data, *json_value, *json_ts = NULL;
json_t *json_data, *json_value, *json_ts = nullptr;
size_t i;
int64_t sequence = -1;
@ -212,7 +212,7 @@ static int json_unpack_sample(struct io *io, json_t *json_smp, struct sample *sm
if (sequence >= 0) {
smp->sequence = sequence;
smp->flags |= SAMPLE_HAS_SEQUENCE;
smp->flags |= (int) SampleFlags::HAS_SEQUENCE;
}
json_array_foreach(json_data, i, json_value) {
@ -223,7 +223,7 @@ static int json_unpack_sample(struct io *io, json_t *json_smp, struct sample *sm
if (!sig)
return -1;
enum signal_type fmt = json_detect_format(json_value);
enum SignalType fmt = json_detect_format(json_value);
if (sig->type != fmt) {
error("Received invalid data type in JSON payload: Received %s, expected %s for signal %s (index %zu).",
signal_type_to_str(fmt), signal_type_to_str(sig->type), sig->name, i);
@ -238,7 +238,7 @@ static int json_unpack_sample(struct io *io, json_t *json_smp, struct sample *sm
}
if (smp->length > 0)
smp->flags |= SAMPLE_HAS_DATA;
smp->flags |= (int) SampleFlags::HAS_DATA;
return 0;
}
@ -362,24 +362,24 @@ skip: json = json_loadf(f, JSON_DISABLE_EOF_CHECK, &err);
static struct plugin p;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p.name = "json";
p.description = "Javascript Object Notation";
p.type = PLUGIN_TYPE_FORMAT;
p.type = PluginType::FORMAT;
p.format.print = json_print;
p.format.scan = json_scan;
p.format.sprint = json_sprint;
p.format.sscan = json_sscan;
p.format.size = 0;
p.format.flags = SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
p.format.flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
p.format.delimiter = '\n';
vlist_push(&plugins, &p);
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p);
}

View file

@ -20,7 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <string.h>
#include <cstring>
#include <villas/plugin.h>
#include <villas/sample.h>
@ -29,7 +29,7 @@
#include <villas/compat.h>
#include <villas/timing.h>
#include <villas/io.h>
#include <villas/formats/json.h>
#include <villas/formats/json_reserve.h>
#define JSON_RESERVE_INTEGER_TARGET 1
@ -37,13 +37,13 @@ static int json_reserve_pack_sample(struct io *io, json_t **j, struct sample *sm
{
json_error_t err;
json_t *json_data, *json_name, *json_unit, *json_value;
json_t *json_created = NULL;
json_t *json_sequence = NULL;
json_t *json_created = nullptr;
json_t *json_sequence = nullptr;
if (smp->flags & SAMPLE_HAS_TS_ORIGIN)
if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN)
json_created = json_integer(time_to_double(&smp->ts.origin) * 1e3);
if (smp->flags & SAMPLE_HAS_SEQUENCE)
if (smp->flags & (int) SampleFlags::HAS_SEQUENCE)
json_sequence = json_integer(smp->sequence);
json_data = json_array();
@ -67,7 +67,7 @@ static int json_reserve_pack_sample(struct io *io, json_t **j, struct sample *sm
if (sig->unit)
json_unit = json_string(sig->unit);
else
json_unit = NULL;
json_unit = nullptr;
json_value = json_pack_ex(&err, 0, "{ s: o, s: f }",
"name", json_name,
@ -94,7 +94,7 @@ static int json_reserve_pack_sample(struct io *io, json_t **j, struct sample *sm
*j = json_pack_ex(&err, 0, "{ s: o }",
"measurements", json_data
);
if (*j == NULL)
if (*j == nullptr)
return -1;
#if 0
#ifdef JSON_RESERVE_INTEGER_TARGET
@ -124,8 +124,8 @@ static int json_reserve_unpack_sample(struct io *io, json_t *json_smp, struct sa
int ret, idx;
double created = -1;
json_error_t err;
json_t *json_value, *json_data = NULL;
json_t *json_origin = NULL, *json_target = NULL;
json_t *json_value, *json_data = nullptr;
json_t *json_origin = nullptr, *json_target = nullptr;
size_t i;
ret = json_unpack_ex(json_smp, &err, 0, "{ s?: o, s?: o, s?: o, s?: o }",
@ -173,7 +173,7 @@ static int json_reserve_unpack_sample(struct io *io, json_t *json_smp, struct sa
smp->length = 0;
json_array_foreach(json_data, i, json_value) {
const char *name, *unit = NULL;
const char *name, *unit = nullptr;
double value;
ret = json_unpack_ex(json_value, &err, 0, "{ s: s, s?: s, s: F, s?: F }",
@ -212,11 +212,11 @@ static int json_reserve_unpack_sample(struct io *io, json_t *json_smp, struct sa
}
if (smp->length > 0)
smp->flags |= SAMPLE_HAS_DATA;
smp->flags |= (int) SampleFlags::HAS_DATA;
if (created > 0) {
smp->ts.origin = time_from_double(created * 1e-3);
smp->flags |= SAMPLE_HAS_TS_ORIGIN;
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN;
}
return smp->length > 0 ? 1 : 0;
@ -326,22 +326,22 @@ skip: json = json_loadf(f, JSON_DISABLE_EOF_CHECK, &err);
static struct plugin p;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p.name = "json.reserve";
p.description = "RESERVE JSON format";
p.type = PLUGIN_TYPE_FORMAT;
p.type = PluginType::FORMAT;
p.format.print = json_reserve_print;
p.format.scan = json_reserve_scan;
p.format.sprint = json_reserve_sprint;
p.format.sscan = json_reserve_sscan;
p.format.size = 0;
vlist_push(&plugins, &p);
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p);
}

View file

@ -67,7 +67,7 @@ int msg_verify(struct msg *m)
return -1;
else if (m->type != MSG_TYPE_DATA)
return -2;
else if (m->rsvd1 != 0)
else if (m->reserved1 != 0)
return -3;
else
return 0;
@ -81,20 +81,20 @@ int msg_to_sample(struct msg *msg, struct sample *smp, struct vlist *signals)
if (ret)
return -1;
smp->flags = SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
smp->flags = (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
smp->length = MIN(msg->length, smp->capacity);
smp->sequence = msg->sequence;
smp->ts.origin = MSG_TS(msg);
MSG_TS(msg, smp->ts.origin);
for (unsigned i = 0; i < MIN(smp->length, vlist_length(signals)); i++) {
struct signal *sig = (struct signal *) vlist_at(signals, i);
switch (sig->type) {
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
smp->data[i].f = msg->data[i].f;
break;
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
smp->data[i].i = msg->data[i].i;
break;
@ -110,6 +110,8 @@ int msg_from_sample(struct msg *msg_in, struct sample *smp, struct vlist *signal
{
msg_in->type = MSG_TYPE_DATA;
msg_in->version = MSG_VERSION;
msg_in->reserved1 = 0;
msg_in->reserved2 = 0;
msg_in->length = (uint16_t) smp->length;
msg_in->sequence = (uint32_t) smp->sequence;
msg_in->ts.sec = smp->ts.origin.tv_sec;
@ -119,11 +121,11 @@ int msg_from_sample(struct msg *msg_in, struct sample *smp, struct vlist *signal
struct signal *sig = (struct signal *) vlist_at(signals, i);
switch (sig->type) {
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
msg_in->data[i].f = smp->data[i].f;
break;
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
msg_in->data[i].i = smp->data[i].i;
break;

View file

@ -29,24 +29,26 @@
#include <villas/plugin.h>
#include <villas/formats/protobuf.h>
static enum signal_type protobuf_detect_format(Villas__Node__Value *val)
using namespace villas::utils;
static enum SignalType protobuf_detect_format(Villas__Node__Value *val)
{
switch (val->value_case) {
case VILLAS__NODE__VALUE__VALUE_F:
return SIGNAL_TYPE_FLOAT;
return SignalType::FLOAT;
case VILLAS__NODE__VALUE__VALUE_I:
return SIGNAL_TYPE_INTEGER;
return SignalType::INTEGER;
case VILLAS__NODE__VALUE__VALUE_B:
return SIGNAL_TYPE_BOOLEAN;
return SignalType::BOOLEAN;
case VILLAS__NODE__VALUE__VALUE_Z:
return SIGNAL_TYPE_COMPLEX;
return SignalType::COMPLEX;
case VILLAS__NODE__VALUE__VALUE__NOT_SET:
default:
return SIGNAL_TYPE_INVALID;
return SignalType::INVALID;
}
}
@ -68,12 +70,12 @@ int protobuf_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct
pb_smp->type = VILLAS__NODE__SAMPLE__TYPE__DATA;
if (io->flags & smp->flags & SAMPLE_HAS_SEQUENCE) {
if (io->flags & smp->flags & (int) SampleFlags::HAS_SEQUENCE) {
pb_smp->has_sequence = 1;
pb_smp->sequence = smp->sequence;
}
if (io->flags & smp->flags & SAMPLE_HAS_TS_ORIGIN) {
if (io->flags & smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) {
pb_smp->timestamp = (Villas__Node__Timestamp *) alloc(sizeof(Villas__Node__Timestamp));
villas__node__timestamp__init(pb_smp->timestamp);
@ -88,34 +90,34 @@ int protobuf_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct
Villas__Node__Value *pb_val = pb_smp->values[j] = (Villas__Node__Value *) alloc(sizeof(Villas__Node__Value));
villas__node__value__init(pb_val);
enum signal_type fmt = sample_format(smp, j);
enum SignalType fmt = sample_format(smp, j);
switch (fmt) {
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
pb_val->value_case = VILLAS__NODE__VALUE__VALUE_F;
pb_val->f = smp->data[j].f;
break;
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
pb_val->value_case = VILLAS__NODE__VALUE__VALUE_I;
pb_val->i = smp->data[j].i;
break;
case SIGNAL_TYPE_BOOLEAN:
case SignalType::BOOLEAN:
pb_val->value_case = VILLAS__NODE__VALUE__VALUE_B;
pb_val->b = smp->data[j].b;
break;
case SIGNAL_TYPE_COMPLEX:
case SignalType::COMPLEX:
pb_val->value_case = VILLAS__NODE__VALUE__VALUE_Z;
pb_val->z = (Villas__Node__Complex *) alloc(sizeof(Villas__Node__Complex));
villas__node__complex__init(pb_val->z);
pb_val->z->real = creal(smp->data[j].z);
pb_val->z->imag = cimag(smp->data[j].z);
pb_val->z->real = std::real(smp->data[j].z);
pb_val->z->imag = std::imag(smp->data[j].z);
break;
case SIGNAL_TYPE_INVALID:
case SignalType::INVALID:
pb_val->value_case = VILLAS__NODE__VALUE__VALUE__NOT_SET;
break;
}
@ -128,14 +130,14 @@ int protobuf_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct
goto out;
villas__node__message__pack(pb_msg, (uint8_t *) buf);
villas__node__message__free_unpacked(pb_msg, NULL);
villas__node__message__free_unpacked(pb_msg, nullptr);
*wbytes = psz;
return cnt;
out:
villas__node__message__free_unpacked(pb_msg, NULL);
villas__node__message__free_unpacked(pb_msg, nullptr);
return -1;
}
@ -145,7 +147,7 @@ int protobuf_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, s
unsigned i, j;
Villas__Node__Message *pb_msg;
pb_msg = villas__node__message__unpack(NULL, len, (uint8_t *) buf);
pb_msg = villas__node__message__unpack(nullptr, len, (uint8_t *) buf);
if (!pb_msg)
return -1;
@ -161,12 +163,12 @@ int protobuf_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, s
}
if (pb_smp->has_sequence) {
smp->flags |= SAMPLE_HAS_SEQUENCE;
smp->flags |= (int) SampleFlags::HAS_SEQUENCE;
smp->sequence = pb_smp->sequence;
}
if (pb_smp->timestamp) {
smp->flags |= SAMPLE_HAS_TS_ORIGIN;
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN;
smp->ts.origin.tv_sec = pb_smp->timestamp->sec;
smp->ts.origin.tv_nsec = pb_smp->timestamp->nsec;
}
@ -174,7 +176,7 @@ int protobuf_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, s
for (j = 0; j < MIN(pb_smp->n_values, smp->capacity); j++) {
Villas__Node__Value *pb_val = pb_smp->values[j];
enum signal_type fmt = protobuf_detect_format(pb_val);
enum SignalType fmt = protobuf_detect_format(pb_val);
struct signal *sig = (struct signal *) vlist_at_safe(smp->signals, j);
if (!sig)
@ -187,20 +189,20 @@ int protobuf_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, s
}
switch (sig->type) {
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
smp->data[j].f = pb_val->f;
break;
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
smp->data[j].i = pb_val->i;
break;
case SIGNAL_TYPE_BOOLEAN:
case SignalType::BOOLEAN:
smp->data[j].b = pb_val->b;
break;
case SIGNAL_TYPE_COMPLEX:
smp->data[j].z = pb_val->z->real + _Complex_I * pb_val->z->imag;
case SignalType::COMPLEX:
smp->data[j].z = std::complex<float>(pb_val->z->real, pb_val->z->imag);
break;
default: { }
@ -208,7 +210,7 @@ int protobuf_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, s
}
if (pb_smp->n_values > 0)
smp->flags |= SAMPLE_HAS_DATA;
smp->flags |= (int) SampleFlags::HAS_DATA;
smp->length = j;
}
@ -216,7 +218,7 @@ int protobuf_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, s
if (rbytes)
*rbytes = villas__node__message__get_packed_size(pb_msg);
villas__node__message__free_unpacked(pb_msg, NULL);
villas__node__message__free_unpacked(pb_msg, nullptr);
return i;
}
@ -224,22 +226,22 @@ int protobuf_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, s
static struct plugin p;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p.name = "protobuf";
p.description = "Google Protobuf";
p.type = PLUGIN_TYPE_FORMAT;
p.type = PluginType::FORMAT;
p.format.sprint = protobuf_sprint;
p.format.sscan = protobuf_sscan;
p.format.flags = IO_HAS_BINARY_PAYLOAD |
SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
p.format.flags = (int) IOFlags::HAS_BINARY_PAYLOAD |
(int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
vlist_push(&plugins, &p);
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p);
}

View file

@ -118,16 +118,16 @@ int raw_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp
}
for (unsigned j = 0; j < smp->length; j++) {
enum signal_type fmt = sample_format(smp, j);
enum SignalType fmt = sample_format(smp, j);
union signal_data *data = &smp->data[j];
/* Check length */
nlen = (o + fmt == SIGNAL_TYPE_COMPLEX ? 2 : 1) * (bits / 8);
nlen = (o + (fmt == SignalType::COMPLEX ? 2 : 1)) * (bits / 8);
if (nlen >= len)
goto out;
switch (fmt) {
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
switch (bits) {
case 8:
i8 [o++] = -1;
@ -151,7 +151,7 @@ int raw_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp
}
break;
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
switch (bits) {
case 8:
i8 [o++] = data->i;
@ -177,7 +177,7 @@ int raw_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp
}
break;
case SIGNAL_TYPE_BOOLEAN:
case SignalType::BOOLEAN:
switch (bits) {
case 8:
i8 [o++] = data->b ? 1 : 0;
@ -203,7 +203,7 @@ int raw_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp
}
break;
case SIGNAL_TYPE_COMPLEX:
case SignalType::COMPLEX:
switch (bits) {
case 8:
i8 [o++] = -1; /* Not supported */
@ -216,24 +216,24 @@ int raw_sprint(struct io *io, char *buf, size_t len, size_t *wbytes, struct samp
break;
case 32:
f32[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 32, (float) creal(data->z));
f32[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 32, (float ) cimag(data->z));
f32[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 32, (float) std::real(data->z));
f32[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 32, (float) std::imag(data->z));
break;
case 64:
f64[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 64, creal(data->z));
f64[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 64, cimag(data->z));
f64[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 64, std::real(data->z));
f64[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 64, std::imag(data->z));
break;
#ifdef HAS_128BIT
case 128:
f128[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 128, creal(data->z);
f128[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 128, cimag(data->z);
f128[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 128, std::real(data->z);
f128[o++] = SWAP_FLOAT_HTOX(io->flags & RAW_BIG_ENDIAN, 128, std::imag(data->z);
break;
#endif
}
break;
case SIGNAL_TYPE_INVALID:
case SignalType::INVALID:
return -1;
}
}
@ -313,7 +313,7 @@ int raw_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, struct
#endif
}
smp->flags = SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_TS_ORIGIN;
smp->flags = (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_TS_ORIGIN;
}
else {
smp->flags = 0;
@ -326,11 +326,11 @@ int raw_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, struct
unsigned i;
for (i = 0; i < smp->capacity && o < nlen; i++) {
enum signal_type fmt = sample_format(smp, i);
enum SignalType fmt = sample_format(smp, i);
union signal_data *data = &smp->data[i];
switch (fmt) {
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
switch (bits) {
case 8: data->f = -1; o++; break; /* Not supported */
case 16: data->f = -1; o++; break; /* Not supported */
@ -343,7 +343,7 @@ int raw_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, struct
}
break;
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
switch (bits) {
case 8: data->i = (int8_t) i8[o++]; break;
case 16: data->i = (int16_t) SWAP_INT_XTOH(io->flags & RAW_BIG_ENDIAN, 16, i16[o++]); break;
@ -355,7 +355,7 @@ int raw_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, struct
}
break;
case SIGNAL_TYPE_BOOLEAN:
case SignalType::BOOLEAN:
switch (bits) {
case 8: data->b = (bool) i8[o++]; break;
case 16: data->b = (bool) SWAP_INT_XTOH(io->flags & RAW_BIG_ENDIAN, 16, i16[o++]); break;
@ -367,29 +367,32 @@ int raw_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, struct
}
break;
case SIGNAL_TYPE_COMPLEX:
case SignalType::COMPLEX:
switch (bits) {
case 8: data->z = -1 + _Complex_I * -1; o += 2; break; /* Not supported */
case 16: data->z = -1 + _Complex_I * -1; o += 2; break; /* Not supported */
case 8: data->z = std::complex<float>(-1, -1); o += 2; break; /* Not supported */
case 16: data->z = std::complex<float>(-1, -1); o += 2; break; /* Not supported */
case 32: data->z = SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 32, f32[o++])
+ _Complex_I * SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 32, f32[o++]);
case 32: data->z = std::complex<float>(
SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 32, f32[o++]),
SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 32, f32[o++]));
break;
case 64: data->z = SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 64, f64[o++])
+ _Complex_I * SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 64, f64[o++]);
case 64: data->z = std::complex<float>(
SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 64, f64[o++]),
SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 64, f64[o++]));
break;
#if HAS_128BIT
case 128: data->z = SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 128, f128[o++])
+ _Complex_I * SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 128, f128[o++]);
case 128: data->z = std::complex<float>(
SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 128, f128[o++]),
SWAP_FLOAT_XTOH(io->flags & RAW_BIG_ENDIAN, 128, f128[o++]));
break;
#endif
}
break;
case SIGNAL_TYPE_INVALID:
case SignalType::INVALID:
warning("Unsupported format in RAW payload");
return -1;
}
@ -411,22 +414,22 @@ int raw_sscan(struct io *io, const char *buf, size_t len, size_t *rbytes, struct
#define REGISTER_FORMAT_RAW(i, n, d, f) \
static struct plugin i; \
__attribute__((constructor(110))) static void UNIQUE(__ctor)() { \
if (plugins.state == STATE_DESTROYED) \
if (plugins.state == State::DESTROYED) \
vlist_init(&plugins); \
\
i.name = n; \
i.description = d; \
i.type = PLUGIN_TYPE_FORMAT; \
i.type = PluginType::FORMAT; \
i.format.sprint = raw_sprint; \
i.format.sscan = raw_sscan; \
i.format.flags = f | IO_HAS_BINARY_PAYLOAD | \
SAMPLE_HAS_DATA; \
i.format.flags = f | (int) IOFlags::HAS_BINARY_PAYLOAD | \
(int) SampleFlags::HAS_DATA; \
\
vlist_push(&plugins, &i); \
} \
\
__attribute__((destructor(110))) static void UNIQUE(__dtor)() { \
if (plugins.state != STATE_DESTROYED) \
if (plugins.state != State::DESTROYED) \
vlist_remove_all(&plugins, &i); \
}
/* Feel free to add additional format identifiers here to suit your needs */

View file

@ -20,7 +20,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <string.h>
#include <cstring>
#include <villas/io.h>
#include <villas/formats/villas_binary.h>
@ -121,23 +121,23 @@ int villas_binary_sscan(struct io *io, const char *buf, size_t len, size_t *rbyt
static struct plugin p1;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p1.name = "villas.binary";
p1.description = "VILLAS binary network format";
p1.type = PLUGIN_TYPE_FORMAT;
p1.type = PluginType::FORMAT;
p1.format.sprint = villas_binary_sprint;
p1.format.sscan = villas_binary_sscan;
p1.format.size = 0;
p1.format.flags = IO_HAS_BINARY_PAYLOAD |
SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
p1.format.flags = (int) IOFlags::HAS_BINARY_PAYLOAD |
(int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
vlist_push(&plugins, &p1);
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p1);
}
/** The WebSocket node-type usually uses little endian byte order intead of network byte order */
@ -145,22 +145,22 @@ static struct plugin p2;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p2.name = "villas.web";
p2.description = "VILLAS binary network format for WebSockets";
p2.type = PLUGIN_TYPE_FORMAT;
p2.type = PluginType::FORMAT;
p2.format.sprint = villas_binary_sprint;
p2.format.sscan = villas_binary_sscan;
p2.format.size = 0;
p2.format.flags = IO_HAS_BINARY_PAYLOAD | VILLAS_BINARY_WEB |
SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
p2.format.flags = (int) IOFlags::HAS_BINARY_PAYLOAD | VILLAS_BINARY_WEB |
(int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
vlist_push(&plugins, &p2);
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p2);
}

View file

@ -20,9 +20,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <stdbool.h>
#include <inttypes.h>
#include <string.h>
#include <cinttypes>
#include <cstring>
#include <villas/io.h>
#include <villas/plugin.h>
@ -37,8 +36,8 @@ static size_t villas_human_sprint_single(struct io *io, char *buf, size_t len, c
size_t off = 0;
struct signal *sig;
if (io->flags & SAMPLE_HAS_TS_ORIGIN) {
if (smp->flags & SAMPLE_HAS_TS_ORIGIN) {
if (io->flags & (int) SampleFlags::HAS_TS_ORIGIN) {
if (smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) {
off += snprintf(buf + off, len - off, "%llu", (unsigned long long) smp->ts.origin.tv_sec);
off += snprintf(buf + off, len - off, ".%09llu", (unsigned long long) smp->ts.origin.tv_nsec);
}
@ -46,24 +45,24 @@ static size_t villas_human_sprint_single(struct io *io, char *buf, size_t len, c
off += snprintf(buf + off, len - off, "nan.nan");
}
if (io->flags & SAMPLE_HAS_OFFSET) {
if (smp->flags & SAMPLE_HAS_TS_RECEIVED)
if (io->flags & (int) SampleFlags::HAS_OFFSET) {
if (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)
off += snprintf(buf + off, len - off, "%+e", time_delta(&smp->ts.origin, &smp->ts.received));
}
if (io->flags & SAMPLE_HAS_SEQUENCE) {
if (io->flags & SAMPLE_HAS_SEQUENCE)
if (io->flags & (int) SampleFlags::HAS_SEQUENCE) {
if (io->flags & (int) SampleFlags::HAS_SEQUENCE)
off += snprintf(buf + off, len - off, "(%" PRIu64 ")", smp->sequence);
}
if (io->flags & SAMPLE_HAS_DATA) {
if (io->flags & (int) SampleFlags::HAS_DATA) {
for (unsigned i = 0; i < smp->length; i++) {
sig = (struct signal *) vlist_at_safe(smp->signals, i);
if (!sig)
break;
off += snprintf(buf + off, len - off, "%c", io->separator);
off += signal_data_snprint(&smp->data[i], sig, buf + off, len - off);
off += signal_data_print_str(&smp->data[i], sig, buf + off, len - off);
}
}
@ -94,7 +93,7 @@ static size_t villas_human_sscan_single(struct io *io, const char *buf, size_t l
if (ptr == end || *end == io->delimiter)
return -1;
smp->flags |= SAMPLE_HAS_TS_ORIGIN;
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN;
/* Optional: nano seconds */
if (*end == '.') {
@ -113,7 +112,7 @@ static size_t villas_human_sscan_single(struct io *io, const char *buf, size_t l
offset = strtof(ptr, &end); /* offset is ignored for now */
if (ptr != end)
smp->flags |= SAMPLE_HAS_OFFSET;
smp->flags |= (int) SampleFlags::HAS_OFFSET;
else
return -4;
}
@ -124,7 +123,7 @@ static size_t villas_human_sscan_single(struct io *io, const char *buf, size_t l
smp->sequence = strtoul(ptr, &end, 10);
if (ptr != end)
smp->flags |= SAMPLE_HAS_SEQUENCE;
smp->flags |= (int) SampleFlags::HAS_SEQUENCE;
else
return -5;
@ -152,13 +151,13 @@ out: if (*end == io->delimiter)
smp->length = i;
if (smp->length > 0)
smp->flags |= SAMPLE_HAS_DATA;
smp->flags |= (int) SampleFlags::HAS_DATA;
if (smp->flags & SAMPLE_HAS_OFFSET) {
if (smp->flags & (int) SampleFlags::HAS_OFFSET) {
struct timespec off = time_from_double(offset);
smp->ts.received = time_add(&smp->ts.origin, &off);
smp->flags |= SAMPLE_HAS_TS_RECEIVED;
smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED;
}
return end - buf;
@ -198,16 +197,16 @@ void villas_human_header(struct io *io, const struct sample *smp)
fprintf(f, "# ");
if (io->flags & SAMPLE_HAS_TS_ORIGIN)
if (io->flags & (int) SampleFlags::HAS_TS_ORIGIN)
fprintf(f, "seconds.nanoseconds");
if (io->flags & SAMPLE_HAS_OFFSET)
if (io->flags & (int) SampleFlags::HAS_OFFSET)
fprintf(f, "+offset");
if (io->flags & SAMPLE_HAS_SEQUENCE)
if (io->flags & (int) SampleFlags::HAS_SEQUENCE)
fprintf(f, "(sequence)");
if (io->flags & SAMPLE_HAS_DATA) {
if (io->flags & (int) SampleFlags::HAS_DATA) {
for (unsigned i = 0; i < MIN(smp->length, vlist_length(smp->signals)); i++) {
struct signal *sig = (struct signal *) vlist_at(smp->signals, i);
@ -226,17 +225,17 @@ void villas_human_header(struct io *io, const struct sample *smp)
static struct plugin p;
__attribute__((constructor(110))) static void UNIQUE(__ctor)() {
if (plugins.state == STATE_DESTROYED)
if (plugins.state == State::DESTROYED)
vlist_init(&plugins);
p.name = "villas.human";
p.description = "VILLAS human readable format";
p.type = PLUGIN_TYPE_FORMAT;
p.type = PluginType::FORMAT;
p.format.header = villas_human_header;
p.format.sprint = villas_human_sprint;
p.format.sscan = villas_human_sscan;
p.format.size = 0;
p.format.flags = IO_NEWLINES | SAMPLE_HAS_TS_ORIGIN | SAMPLE_HAS_SEQUENCE | SAMPLE_HAS_DATA;
p.format.flags = (int) IOFlags::NEWLINES | (int) SampleFlags::HAS_TS_ORIGIN | (int) SampleFlags::HAS_SEQUENCE | (int) SampleFlags::HAS_DATA;
p.format.delimiter = '\n';
p.format.separator = '\t';
@ -244,6 +243,6 @@ __attribute__((constructor(110))) static void UNIQUE(__ctor)() {
}
__attribute__((destructor(110))) static void UNIQUE(__dtor)() {
if (plugins.state != STATE_DESTROYED)
if (plugins.state != State::DESTROYED)
vlist_remove_all(&plugins, &p);
}

View file

@ -20,8 +20,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <string.h>
#include <math.h>
#include <cstring>
#include <cmath>
#include <villas/timing.h>
#include <villas/node/config.h>
@ -39,7 +39,7 @@ using namespace villas;
using namespace villas::node;
Hook::Hook(struct path *p, struct node *n, int fl, int prio, bool en) :
state(STATE_INITIALIZED),
state(State::INITIALIZED),
flags(fl),
priority(prio),
enabled(en),
@ -50,14 +50,14 @@ Hook::Hook(struct path *p, struct node *n, int fl, int prio, bool en) :
logger = logging.get("hook");
signals.state = STATE_DESTROYED;
signals.state = State::DESTROYED;
ret = signal_list_init(&signals);
if (ret)
throw RuntimeError("Failed to initialize signal list");
/* We dont need to parse builtin hooks. */
state = flags & HOOK_BUILTIN ? STATE_CHECKED : STATE_INITIALIZED;
state = flags & (int) Hook::Flags::BUILTIN ? State::CHECKED : State::INITIALIZED;
}
Hook::~Hook()
@ -67,9 +67,9 @@ Hook::~Hook()
void Hook::prepare()
{
assert(state == STATE_CHECKED);
assert(state == State::CHECKED);
state = STATE_PREPARED;
state = State::PREPARED;
}
void Hook::parse(json_t *c)
@ -77,7 +77,7 @@ void Hook::parse(json_t *c)
int ret;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
ret = json_unpack_ex(c, &err, 0, "{ s?: i, s?: b }",
"priority", &priority,
@ -88,5 +88,5 @@ void Hook::parse(json_t *c)
cfg = c;
state = STATE_PARSED;
state = State::PARSED;
}

View file

@ -58,11 +58,10 @@ int hook_list_destroy(vlist *hs)
return 0;
}
int hook_list_parse(vlist *hs, json_t *cfg, int mask, struct path *o, struct node *n)
void hook_list_parse(vlist *hs, json_t *cfg, int mask, struct path *o, struct node *n)
{
if (!json_is_array(cfg))
//throw ConfigError(cfg, "node-config-hook", "Hooks must be configured as a list of hook objects");
return -1;
throw ConfigError(cfg, "node-config-hook", "Hooks must be configured as a list of hook objects");
size_t i;
json_t *json_hook;
@ -83,19 +82,12 @@ int hook_list_parse(vlist *hs, json_t *cfg, int mask, struct path *o, struct nod
if (!(hf->getFlags() & mask))
throw ConfigError(json_hook, "node-config-hook", "Hook '{}' not allowed here", type);
try {
h = hf->make(o, n);
h->parse(json_hook);
h->check();
}
catch (...) {
return -1;
}
h = hf->make(o, n);
h->parse(json_hook);
h->check();
vlist_push(hs, h);
}
return 0;
}
static int hook_cmp_priority(const Hook *a, const Hook *b)
@ -108,9 +100,9 @@ static int hook_is_enabled(const Hook *h)
return h->isEnabled() ? 0 : -1;
}
int hook_list_prepare(vlist *hs, vlist *sigs, int m, struct path *p, struct node *n)
void hook_list_prepare(vlist *hs, vlist *sigs, int m, struct path *p, struct node *n)
{
assert(hs->state == STATE_INITIALIZED);
assert(hs->state == State::INITIALIZED);
if (!m)
goto skip_add;
@ -134,21 +126,15 @@ skip_add:
for (size_t i = 0; i < vlist_length(hs); i++) {
Hook *h = (Hook *) vlist_at(hs, i);
try {
h->prepare(sigs);
} catch (...) {
return -1;
}
h->prepare(sigs);
sigs = h->getSignals();
}
return 0;
}
int hook_list_process(vlist *hs, sample *smps[], unsigned cnt)
{
unsigned ret, current, processed = 0;
unsigned current, processed = 0;
if (vlist_length(hs) == 0)
return cnt;
@ -159,18 +145,18 @@ int hook_list_process(vlist *hs, sample *smps[], unsigned cnt)
for (size_t i = 0; i < vlist_length(hs); i++) {
Hook *h = (Hook *) vlist_at(hs, i);
ret = h->process(smp);
auto ret = h->process(smp);
switch (ret) {
case HOOK_ERROR:
case Hook::Reason::ERROR:
return -1;
case HOOK_OK:
case Hook::Reason::OK:
continue;
case HOOK_SKIP_SAMPLE:
case Hook::Reason::SKIP_SAMPLE:
goto skip;
case HOOK_STOP_PROCESSING:
case Hook::Reason::STOP_PROCESSING:
goto stop;
}
}
@ -182,49 +168,31 @@ skip: {}
stop: return processed;
}
int hook_list_periodic(vlist *hs)
void hook_list_periodic(vlist *hs)
{
for (size_t j = 0; j < vlist_length(hs); j++) {
Hook *h = (Hook *) vlist_at(hs, j);
try {
h->periodic();
} catch (...) {
return -1;
}
h->periodic();
}
return 0;
}
int hook_list_start(vlist *hs)
void hook_list_start(vlist *hs)
{
for (size_t i = 0; i < vlist_length(hs); i++) {
Hook *h = (Hook *) vlist_at(hs, i);
try {
h->start();
} catch (...) {
return -1;
}
h->start();
}
return 0;
}
int hook_list_stop(vlist *hs)
void hook_list_stop(vlist *hs)
{
for (size_t i = 0; i < vlist_length(hs); i++) {
Hook *h = (Hook *) vlist_at(hs, i);
try {
h->stop();
} catch (...) {
return -1;
}
h->stop();
}
return 0;
}
vlist * hook_list_get_signals(vlist *hs)

View file

@ -24,11 +24,12 @@ set(HOOK_SRC
average.cpp
cast.cpp
decimate.cpp
dp.cpp
#dp.cpp
drop.cpp
dump.cpp
ebm.cpp
fix.cpp
gate.cpp
jitter_calc.cpp
limit_rate.cpp
restart.cpp
@ -38,6 +39,7 @@ set(HOOK_SRC
skip_first.cpp
stats.cpp
ts.cpp
pps_ts.cpp
print.cpp
)

View file

@ -26,7 +26,7 @@
#include <bitset>
#include <string.h>
#include <cstring>
#include <villas/hook.hpp>
#include <villas/node/exceptions.hpp>
@ -54,7 +54,7 @@ public:
if (ret)
throw RuntimeError("Failed to intialize list");
state = STATE_INITIALIZED;
state = State::INITIALIZED;
}
virtual ~AverageHook()
@ -67,7 +67,7 @@ public:
int ret;
struct signal *avg_sig;
assert(state == STATE_CHECKED);
assert(state == State::CHECKED);
/* Setup mask */
for (size_t i = 0; i < vlist_length(&signal_names); i++) {
@ -84,7 +84,7 @@ public:
throw RuntimeError("Invalid signal mask");
/* Add averaged signal */
avg_sig = signal_create("average", nullptr, SIGNAL_TYPE_FLOAT);
avg_sig = signal_create("average", nullptr, SignalType::FLOAT);
if (!avg_sig)
throw RuntimeError("Failed to create new signal");
@ -92,7 +92,7 @@ public:
if (ret)
throw RuntimeError("Failed to intialize list");
state = STATE_PREPARED;
state = State::PREPARED;
}
virtual void parse(json_t *cfg)
@ -102,7 +102,7 @@ public:
json_error_t err;
json_t *json_signals, *json_signal;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
Hook::parse(cfg);
@ -131,33 +131,33 @@ public:
}
}
state = STATE_PARSED;
state = State::PARSED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
double avg, sum = 0;
int n = 0;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
for (unsigned k = 0; k < smp->length; k++) {
if (!mask.test(k))
continue;
switch (sample_format(smp, k)) {
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
sum += smp->data[k].i;
break;
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
sum += smp->data[k].f;
break;
case SIGNAL_TYPE_INVALID:
case SIGNAL_TYPE_COMPLEX:
case SIGNAL_TYPE_BOOLEAN:
return HOOK_ERROR; /* not supported */
case SignalType::INVALID:
case SignalType::COMPLEX:
case SignalType::BOOLEAN:
return Hook::Reason::ERROR; /* not supported */
}
n++;
@ -167,7 +167,7 @@ public:
sample_data_insert(smp, (union signal_data *) &avg, offset, 1);
smp->signals = &signals;
return HOOK_OK;
return Reason::OK;
}
};
@ -175,7 +175,7 @@ public:
static HookPlugin<AverageHook> p(
"average",
"Calculate average over some signals",
HOOK_PATH | HOOK_NODE_READ | HOOK_NODE_WRITE,
(int) Hook::Flags::PATH | (int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE,
99
);

View file

@ -25,7 +25,7 @@
* @{
*/
#include <string.h>
#include <cstring>
#include <villas/hook.hpp>
#include <villas/sample.h>
@ -39,7 +39,7 @@ protected:
unsigned signal_index;
char *signal_name;
enum signal_type new_type;
enum SignalType new_type;
char *new_name;
char *new_unit;
@ -48,7 +48,7 @@ public:
Hook(p, n, fl, prio, en),
signal_index(-1),
signal_name(nullptr),
new_type(SIGNAL_TYPE_INVALID),
new_type(SignalType::INVALID),
new_name(nullptr),
new_unit(nullptr)
{ }
@ -69,7 +69,7 @@ public:
{
struct signal *orig_sig, *new_sig;
assert(state == STATE_CHECKED);
assert(state == State::CHECKED);
if (signal_name) {
signal_index = vlist_lookup_index(&signals, signal_name);
@ -78,11 +78,13 @@ public:
}
char *name, *unit;
enum signal_type type;
enum SignalType type;
orig_sig = (struct signal *) vlist_at_safe(&signals, signal_index);
if (!orig_sig)
throw RuntimeError("Failed to find signal: {}", signal_name);
type = new_type != SIGNAL_TYPE_INVALID ? new_type : orig_sig->type;
type = new_type != SignalType::INVALID ? new_type : orig_sig->type;
name = new_name ? new_name : orig_sig->name;
unit = new_unit ? new_unit : orig_sig->unit;
@ -91,7 +93,7 @@ public:
vlist_set(&signals, signal_index, new_sig);
signal_decref(orig_sig);
state = STATE_PREPARED;
state = State::PREPARED;
}
virtual void parse(json_t *cfg)
@ -101,7 +103,7 @@ public:
json_error_t err;
json_t *json_signal;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
const char *name = nullptr;
const char *unit = nullptr;
@ -132,12 +134,12 @@ public:
if (type) {
new_type = signal_type_from_str(type);
if (new_type == SIGNAL_TYPE_INVALID)
if (new_type == SignalType::INVALID)
throw RuntimeError("Invalid signal type: {}", type);
}
else
/* We use this constant to indicate that we dont want to change the type. */
new_type = SIGNAL_TYPE_INVALID;
new_type = SignalType::INVALID;
if (name)
new_name = strdup(name);
@ -145,12 +147,12 @@ public:
if (unit)
new_unit = strdup(unit);
state = STATE_PARSED;
state = State::PARSED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
struct signal *orig_sig = (struct signal *) vlist_at(smp->signals, signal_index);
struct signal *new_sig = (struct signal *) vlist_at(&signals, signal_index);
@ -160,7 +162,7 @@ public:
/* Replace signal descriptors of sample */
smp->signals = &signals;
return HOOK_OK;
return Reason::OK;
}
};
@ -168,7 +170,7 @@ public:
static HookPlugin<CastHook> p(
"cast",
"Cast signals types",
HOOK_NODE_READ | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::PATH,
99
);

View file

@ -31,11 +31,11 @@ namespace node {
void DecimateHook::start()
{
assert(state == STATE_PREPARED);
assert(state == State::PREPARED);
counter = 0;
state = STATE_STARTED;
state = State::STARTED;
}
void DecimateHook::parse(json_t *cfg)
@ -43,7 +43,7 @@ void DecimateHook::parse(json_t *cfg)
int ret;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s: i }",
"ratio", &ratio
@ -51,24 +51,24 @@ void DecimateHook::parse(json_t *cfg)
if (ret)
throw ConfigError(cfg, err, "node-config-hook-decimate");
state = STATE_PARSED;
state = State::PARSED;
}
int DecimateHook::process(sample *smp)
Hook::Reason DecimateHook::process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (ratio && counter++ % ratio != 0)
return HOOK_SKIP_SAMPLE;
return Hook::Reason::SKIP_SAMPLE;
return HOOK_OK;
return Reason::OK;
}
/* Register hook */
static HookPlugin<DecimateHook> p(
"decimate",
"Downsamping by integer factor",
HOOK_NODE_READ | HOOK_NODE_WRITE | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE | (int) Hook::Flags::PATH,
99
);

View file

@ -24,8 +24,8 @@
* @{
*/
#include <math.h>
#include <string.h>
#include <cmath>
#include <cstring>
#include <complex>
@ -35,6 +35,7 @@
#include <villas/utils.hpp>
using namespace std::complex_literals;
using namespace villas::utils;
namespace villas {
namespace node {
@ -135,7 +136,7 @@ public:
virtual void start()
{
assert(state == STATE_PREPARED);
assert(state == State::PREPARED);
time = 0;
steps = 0;
@ -145,7 +146,7 @@ public:
window = dsp::Window<double>((1.0 / f0) / timestep, 0.0);
state = STATE_STARTED;
state = State::STARTED;
}
virtual void parse(json_t *cfg)
@ -205,19 +206,19 @@ public:
fharmonics[i] = json_integer_value(json_harmonic);
}
state = STATE_PARSED;
state = State::PARSED;
}
virtual void prepare()
{
int ret;
assert(state == STATE_CHECKED);
assert(state == State::CHECKED);
char *new_sig_name;
struct signal *orig_sig, *new_sig;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
if (signal_name) {
signal_index = vlist_lookup_index(&signals, signal_name);
@ -232,7 +233,7 @@ public:
if (!orig_sig)
throw RuntimeError("Failed to find signal");;
if (orig_sig->type != SIGNAL_TYPE_COMPLEX)
if (orig_sig->type != SignalType::COMPLEX)
throw RuntimeError("Signal is not complex");;
ret = vlist_remove(&signals, signal_index + i);
@ -243,7 +244,7 @@ public:
}
/* Add new real-valued reconstructed signals */
new_sig = signal_create("dp", "idp", SIGNAL_TYPE_FLOAT);
new_sig = signal_create("dp", "idp", SignalType::FLOAT);
if (!new_sig)
throw RuntimeError("Failed to create signal");;
@ -256,7 +257,7 @@ public:
if (!orig_sig)
throw RuntimeError("Failed to find signal");;
if (orig_sig->type != SIGNAL_TYPE_FLOAT)
if (orig_sig->type != SignalType::FLOAT)
throw RuntimeError("Signal is not float");;
ret = vlist_remove(&signals, signal_index);
@ -266,7 +267,7 @@ public:
for (int i = 0; i < fharmonics_len; i++) {
new_sig_name = strf("%s_harm%d", orig_sig->name, i);
new_sig = signal_create(new_sig_name, orig_sig->unit, SIGNAL_TYPE_COMPLEX);
new_sig = signal_create(new_sig_name, orig_sig->unit, SignalType::COMPLEX);
if (!new_sig)
throw RuntimeError("Failed to create new signal");;
@ -278,13 +279,13 @@ public:
signal_decref(orig_sig);
}
state = STATE_PREPARED;
state = State::PREPARED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
if (signal_index > smp->length)
return HOOK_ERROR;
return Hook::Reason::ERROR;
if (inverse) {
double signal;
@ -310,7 +311,7 @@ public:
time += timestep;
steps++;
return HOOK_OK;
return Reason::OK;
}
};
@ -318,7 +319,7 @@ public:
static HookPlugin<DPHook> p(
"dp",
"Transform to/from dynamic phasor domain",
HOOK_PATH | HOOK_NODE_READ | HOOK_NODE_WRITE,
(int) Hook::Flags::PATH | (int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE,
99
);

View file

@ -24,7 +24,7 @@
* @{
*/
#include <inttypes.h>
#include <cinttypes>
#include <villas/hook.hpp>
#include <villas/node.h>
@ -43,35 +43,35 @@ public:
virtual void start()
{
assert(state == STATE_PREPARED || state == STATE_STOPPED);
assert(state == State::PREPARED || state == State::STOPPED);
prev = nullptr;
state = STATE_STARTED;
state = State::STARTED;
}
virtual void stop()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (prev)
sample_decref(prev);
state = STATE_STOPPED;
state = State::STOPPED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
int dist;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (prev) {
dist = smp->sequence - (int64_t) prev->sequence;
if (dist <= 0) {
logger->debug("Dropping reordered sample: sequence={}, distance={}", smp->sequence, dist);
return HOOK_SKIP_SAMPLE;
return Hook::Reason::SKIP_SAMPLE;
}
}
@ -81,12 +81,12 @@ public:
prev = smp;
return HOOK_OK;
return Reason::OK;
}
virtual void restart()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (prev) {
sample_decref(prev);
@ -99,7 +99,7 @@ public:
static HookPlugin<DropHook> p(
"drop",
"Drop messages with reordered sequence numbers",
HOOK_BUILTIN | HOOK_NODE_READ,
(int) Hook::Flags::BUILTIN | (int) Hook::Flags::NODE_READ,
3
);

View file

@ -37,13 +37,13 @@ class DumpHook : public Hook {
public:
using Hook::Hook;
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
sample_dump(smp);
return HOOK_OK;
return Reason::OK;
}
};
@ -51,7 +51,7 @@ public:
static HookPlugin<DumpHook> p(
"dump",
"Dump data to stdout",
HOOK_NODE_READ | HOOK_NODE_WRITE | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE | (int) Hook::Flags::PATH,
1
);

View file

@ -75,31 +75,31 @@ public:
phases.emplace_back(voltage, current);
}
state = STATE_PARSED;
state = State::PARSED;
}
virtual void start()
{
assert(state == STATE_PREPARED);
assert(state == State::PREPARED);
energy = 0;
last = nullptr;
state = STATE_STARTED;
state = State::STARTED;
}
virtual void periodic()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
info("Energy: %f", energy);
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
double P, P_last, dt;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (last) {
for (auto phase : phases) {
@ -118,14 +118,14 @@ public:
sample_incref(smp);
last = smp;
return HOOK_OK;
return Reason::OK;
}
};
static HookPlugin<EBMHook> p(
"ebm",
"Energy-based Metric",
HOOK_PATH | HOOK_NODE_READ | HOOK_NODE_WRITE,
(int) Hook::Flags::PATH | (int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE,
99
);

View file

@ -25,7 +25,7 @@
* @{
*/
#include <inttypes.h>
#include <cinttypes>
#include <villas/hook.hpp>
#include <villas/node.h>
@ -40,28 +40,28 @@ class FixHook : public Hook {
public:
using Hook::Hook;
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
timespec now = time_now();
if (!(smp->flags & SAMPLE_HAS_SEQUENCE) && node) {
if (!(smp->flags & (int) SampleFlags::HAS_SEQUENCE) && node) {
smp->sequence = node->sequence++;
smp->flags |= SAMPLE_HAS_SEQUENCE;
smp->flags |= (int) SampleFlags::HAS_SEQUENCE;
}
if (!(smp->flags & SAMPLE_HAS_TS_RECEIVED)) {
if (!(smp->flags & (int) SampleFlags::HAS_TS_RECEIVED)) {
smp->ts.received = now;
smp->flags |= SAMPLE_HAS_TS_RECEIVED;
smp->flags |= (int) SampleFlags::HAS_TS_RECEIVED;
}
if (!(smp->flags & SAMPLE_HAS_TS_ORIGIN)) {
if (!(smp->flags & (int) SampleFlags::HAS_TS_ORIGIN)) {
smp->ts.origin = smp->ts.received;
smp->flags |= SAMPLE_HAS_TS_ORIGIN;
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN;
}
return HOOK_OK;
return Reason::OK;
}
};
@ -69,7 +69,7 @@ public:
static HookPlugin<FixHook> p(
"fix",
"Fix received data by adding missing fields",
HOOK_BUILTIN | HOOK_NODE_READ,
(int) Hook::Flags::BUILTIN | (int) Hook::Flags::NODE_READ,
1
);

206
lib/hooks/gate.cpp Normal file
View file

@ -0,0 +1,206 @@
/** Gate hook.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup hooks Hook functions
* @{
*/
#include <cmath>
#include <string>
#include <limits>
#include <villas/hook.hpp>
#include <villas/node.h>
#include <villas/sample.h>
#include <villas/timing.h>
namespace villas {
namespace node {
class GateHook : public Hook {
protected:
enum class Mode {
ABOVE,
BELOW,
RISING_EDGE,
FALLING_EDGE
} mode;
std::string signalName;
int signalIndex;
double threshold;
double duration;
int samples;
double previousValue;
bool active;
uint64_t startSequence;
timespec startTime;
public:
GateHook(struct path *p, struct node *n, int fl, int prio, bool en = true) :
Hook(p, n, fl, prio, en),
mode(Mode::RISING_EDGE),
threshold(0.5),
duration(-1),
samples(-1),
previousValue(std::numeric_limits<double>::quiet_NaN()),
active(false)
{ }
virtual void parse(json_t *cfg)
{
int ret;
json_error_t err;
json_t *json_signal;
const char *mode_str;
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s: o, s?: F, s?: F, s?: i, s?: s }",
"signal", &json_signal,
"threshold", &threshold,
"duration", &duration,
"samples", &samples,
"mode", &mode_str
);
if (ret)
throw ConfigError(cfg, err, "node-config-hook-gate");
if (mode_str) {
if (!strcmp(mode_str, "above"))
mode = Mode::ABOVE;
else if (!strcmp(mode_str, "below"))
mode = Mode::BELOW;
else if (!strcmp(mode_str, "rising_edge"))
mode = Mode::RISING_EDGE;
else if (!strcmp(mode_str, "falling_edge"))
mode = Mode::FALLING_EDGE;
}
switch (json_typeof(json_signal)) {
case JSON_STRING:
signalName = json_string_value(json_signal);
break;
case JSON_INTEGER:
signalName.clear();
signalIndex = json_integer_value(json_signal);
break;
default:
throw ConfigError(json_signal, "node-config-hook-cast-signals", "Invalid value for setting 'signal'");
}
state = State::PARSED;
}
virtual void prepare()
{
assert(state == State::CHECKED);
if (!signalName.empty()) {
signalIndex = vlist_lookup_index(&signals, signalName.c_str());
if (signalIndex < 0)
throw RuntimeError("Failed to find signal: {}", signalName);
}
/* Check if signal type is float */
auto sig = (struct signal *) vlist_at(&signals, signalIndex);
if (!sig)
throw RuntimeError("Invalid signal index: {}", signalIndex);
if (sig->type != SignalType::FLOAT)
throw RuntimeError("Gate signal must be of type float");
state = State::PREPARED;
}
virtual Hook::Reason process(sample *smp)
{
assert(state == State::STARTED);
Hook::Reason reason;
double value = smp->data[signalIndex].f;
if (active) {
if (duration > 0 && time_delta(&smp->ts.origin, &startTime) < duration)
reason = Reason::OK;
else if (samples > 0 && smp->sequence - startSequence < (uint64_t) samples)
reason = Reason::OK;
else {
reason = Reason::SKIP_SAMPLE;
active = false;
}
}
if (!active) {
switch (mode) {
case Mode::ABOVE:
reason = value > threshold ? Reason::OK : Reason::SKIP_SAMPLE;
break;
case Mode::BELOW:
reason = value < threshold ? Reason::OK : Reason::SKIP_SAMPLE;
break;
case Mode::RISING_EDGE:
reason = (!std::isnan(previousValue) && value > previousValue) ? Reason::OK : Reason::SKIP_SAMPLE;
break;
case Mode::FALLING_EDGE:
reason = (!std::isnan(previousValue) && value < previousValue) ? Reason::OK : Reason::SKIP_SAMPLE;
break;
default:
reason = Reason::ERROR;
}
if (reason == Reason::OK) {
startTime = smp->ts.origin;
startSequence = smp->sequence;
active = true;
}
}
previousValue = value;
return reason;
}
};
/* Register hook */
static HookPlugin<GateHook> p(
"gate",
"Skip samples only if an enable signal is under a specified threshold",
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::PATH,
99
);
} /* namespace node */
} /* namespace villas */
/** @} */

View file

@ -24,8 +24,8 @@
* @{
*/
#include <inttypes.h>
#include <string.h>
#include <cinttypes>
#include <cstring>
#include <villas/hook.hpp>
#include <villas/timing.h>
@ -86,9 +86,9 @@ public:
* is high (i.e. several mins depending on GPS_NTP_DELAY_WIN_SIZE),
* the variance value will overrun the 64bit value.
*/
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
timespec now = time_now();
int64_t delay_sec, delay_nsec, curr_delay_us;
@ -119,7 +119,7 @@ public:
if (curr_count >= GPS_NTP_DELAY_WIN_SIZE)
curr_count = 0;
return HOOK_OK;
return Reason::OK;
}
};
@ -127,7 +127,7 @@ public:
static HookPlugin<JitterCalcHook> p(
"jitter_calc",
"Calc jitter, mean and variance of GPS vs NTP TS",
HOOK_NODE_READ | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::PATH,
0
);

View file

@ -24,7 +24,7 @@
* @{
*/
#include <string.h>
#include <cstring>
#include <villas/timing.h>
#include <villas/sample.h>
@ -38,7 +38,7 @@ void LimitRateHook::parse(json_t *cfg)
int ret;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
double rate;
const char *m = nullptr;
@ -63,12 +63,12 @@ void LimitRateHook::parse(json_t *cfg)
deadtime = 1.0 / rate;
state = STATE_PARSED;
state = State::PARSED;
}
int LimitRateHook::process(sample *smp)
Hook::Reason LimitRateHook::process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
timespec next;
switch (mode) {
@ -86,18 +86,18 @@ int LimitRateHook::process(sample *smp)
}
if (time_delta(&last, &next) < deadtime)
return HOOK_SKIP_SAMPLE;
return Hook::Reason::SKIP_SAMPLE;
last = next;
return HOOK_OK;
return Reason::OK;
}
/* Register hook */
static HookPlugin<LimitRateHook> p(
"limit_rate",
"Limit sending rate",
HOOK_NODE_READ | HOOK_NODE_WRITE | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE | (int) Hook::Flags::PATH,
99
);

142
lib/hooks/pps_ts.cpp Normal file
View file

@ -0,0 +1,142 @@
/** Timestamp hook.
*
* @author Steffen Vogel <stvogel@eonerc.rwth-aachen.de>
* @copyright 2014-2019, Institute for Automation of Complex Power Systems, EONERC
* @license GNU General Public License (version 3)
*
* VILLASnode
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
/** @addtogroup hooks Hook functions
* @{
*/
#include <villas/hook.hpp>
#include <villas/timing.h>
#include <villas/sample.h>
#include <villas/log.h>
namespace villas {
namespace node {
class PpsTsHook : public Hook {
protected:
double lastValue;
double thresh;
double realSmpRate;
unsigned idx;
int lastSeqNr;
unsigned edgeCounter;
timespec realTime;
public:
PpsTsHook(struct path *p, struct node *n, int fl, int prio, bool en = true) :
Hook(p, n, fl, prio, en),
lastValue(0),
thresh(1.5),
realSmpRate(0),
idx(0),
lastSeqNr(0),
edgeCounter(0),
realTime({ 0, 0 })
{
}
virtual void parse(json_t *cfg)
{
int ret;
json_error_t err;
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s: i, s?: f }",
"signal_index", &idx,
"threshold", &thresh
);
if (ret)
throw ConfigError(cfg, err, "node-config-hook-pps_ts");
info("parsed config thresh=%f signal_index=%d", thresh, idx);
state = State::PARSED;
}
virtual villas::node::Hook::Reason process(sample *smp)
{
assert(state == State::STARTED);
/* Get value of PPS signal */
float value = smp->data[idx].f; // TODO check if it is really float
int seqNr = smp->sequence;
/* Detect Edge */
bool isEdge = lastValue < thresh && value > thresh;
if (isEdge) {
if (edgeCounter >= 1)
realSmpRate = seqNr - lastSeqNr;
if (edgeCounter == 1) {
auto now = time_now();
if (now.tv_nsec >= 0.5e9)
realTime.tv_sec = now.tv_sec + 1;
else
realTime.tv_sec = now.tv_sec;
}
lastSeqNr = seqNr;
info("Edge detected: seq=%u, realTime.sec=%ld, realTime.nsec=%ld, smpRate=%f", seqNr, realTime.tv_sec, realTime.tv_nsec, realSmpRate);
edgeCounter++;
}
lastValue = value;
if (edgeCounter < 2)
return Hook::Reason::SKIP_SAMPLE;
else if (edgeCounter == 2 && isEdge)
realTime.tv_nsec = 0;
else
realTime.tv_nsec += 1e9 / realSmpRate;
if (realTime.tv_nsec >= 1000000000) {
realTime.tv_sec++;
realTime.tv_nsec -= 1000000000;
}
/* Update timestamp */
smp->ts.origin = realTime;
smp->flags |= (int) SampleFlags::HAS_TS_ORIGIN;
return Hook::Reason::OK;
}
};
/* Register hook */
static HookPlugin<PpsTsHook> p(
"pps_ts",
"Timestamp samples based GPS PPS signal",
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE | (int) Hook::Flags::PATH,
99
);
} /* namespace node */
} /* namespace villas */
/** @} */

View file

@ -24,7 +24,7 @@
* @{
*/
#include <string.h>
#include <cstring>
#include <villas/hook.hpp>
#include <villas/path.h>
@ -50,7 +50,7 @@ public:
prefix(nullptr),
uri(nullptr)
{
io.state = STATE_DESTROYED;
io.state = State::DESTROYED;
format = format_type_lookup("villas.human");
}
@ -59,9 +59,9 @@ public:
{
int ret;
assert(state == STATE_PREPARED || state == STATE_STOPPED);
assert(state == State::PREPARED || state == State::STOPPED);
ret = io_init(&io, format, &signals, SAMPLE_HAS_ALL);
ret = io_init(&io, format, &signals, (int) SampleFlags::HAS_ALL);
if (ret)
throw RuntimeError("Failed to initialze IO");
@ -73,14 +73,14 @@ public:
if (ret)
throw RuntimeError("Failed to open IO");
state = STATE_STARTED;
state = State::STARTED;
}
virtual void stop()
{
int ret;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
ret = io_close(&io);
if (ret)
@ -90,7 +90,7 @@ public:
if (ret)
throw RuntimeError("Failed to destroy IO");
state = STATE_STOPPED;
state = State::STOPPED;
}
virtual void parse(json_t *cfg)
@ -99,7 +99,7 @@ public:
int ret;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s?: s, s?: s, s?: s }",
"output", &u,
@ -121,12 +121,12 @@ public:
throw ConfigError(cfg, "node-config-hook-print-format", "Invalid IO format '{}'", f);
}
state = STATE_PARSED;
state = State::PARSED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (prefix)
printf("%s", prefix);
@ -137,7 +137,7 @@ public:
io_print(&io, &smp, 1);
return HOOK_OK;
return Reason::OK;
}
virtual ~PrintHook()
@ -154,7 +154,7 @@ public:
static HookPlugin<PrintHook> p(
"print",
"Print the message to stdout",
HOOK_NODE_READ | HOOK_NODE_WRITE | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE | (int) Hook::Flags::PATH,
99
);

View file

@ -24,7 +24,7 @@
* @{
*/
#include <inttypes.h>
#include <cinttypes>
#include <villas/hook.hpp>
#include <villas/node.h>
@ -43,26 +43,26 @@ public:
virtual void start()
{
assert(state == STATE_PREPARED);
assert(state == State::PREPARED);
prev = nullptr;
state = STATE_STARTED;
state = State::STARTED;
}
virtual void stop()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (prev)
sample_decref(prev);
state = STATE_STOPPED;
state = State::STOPPED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (prev) {
/* A wrap around of the sequence no should not be treated as a simulation restart */
@ -70,7 +70,7 @@ public:
logger->warn("Simulation from node {} restarted (previous->sequence={}, current->sequence={})",
node_name(node), prev->sequence, smp->sequence);
smp->flags |= SAMPLE_IS_FIRST;
smp->flags |= (int) SampleFlags::IS_FIRST;
/* Restart hooks */
for (size_t i = 0; i < vlist_length(&node->in.hooks); i++) {
@ -93,7 +93,7 @@ public:
prev = smp;
return HOOK_OK;
return Reason::OK;
}
};
@ -101,7 +101,7 @@ public:
static HookPlugin<RestartHook> p(
"restart",
"Call restart hooks for current node",
HOOK_BUILTIN | HOOK_NODE_READ,
(int) Hook::Flags::BUILTIN | (int) Hook::Flags::NODE_READ,
1
);

View file

@ -24,7 +24,7 @@
* @{
*/
#include <string.h>
#include <cstring>
#include <villas/hook.hpp>
#include <villas/sample.h>
@ -50,7 +50,7 @@ public:
virtual void prepare()
{
assert(state != STATE_STARTED);
assert(state != State::STARTED);
if (signal_name) {
signal_index = vlist_lookup_index(&signals, signal_name);
@ -58,7 +58,7 @@ public:
throw RuntimeError("Failed to find signal: {}", signal_name);
}
state = STATE_PREPARED;
state = State::PREPARED;
}
virtual ~ScaleHook()
@ -73,7 +73,7 @@ public:
json_t *json_signal;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s?: F, s?: F, s: o }",
"scale", &scale,
@ -97,36 +97,36 @@ public:
throw ConfigError(json_signal, "node-config-hook-scale-signal", "Invalid value for setting 'signal'");
}
state = STATE_PARSED;
state = State::PARSED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
int k = signal_index;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
switch (sample_format(smp, k)) {
case SIGNAL_TYPE_INTEGER:
case SignalType::INTEGER:
smp->data[k].i = smp->data[k].i * scale + offset;
break;
case SIGNAL_TYPE_FLOAT:
case SignalType::FLOAT:
smp->data[k].f = smp->data[k].f * scale + offset;
break;
case SIGNAL_TYPE_COMPLEX:
smp->data[k].z = smp->data[k].z * scale + offset;
case SignalType::COMPLEX:
smp->data[k].z = smp->data[k].z * (float) scale + (float) offset;
break;
case SIGNAL_TYPE_BOOLEAN:
smp->data[k].b = smp->data[k].b * scale + offset;
case SignalType::BOOLEAN:
smp->data[k].b = smp->data[k].b * (float) scale + (float) offset;
break;
default: { }
}
return HOOK_OK;
return Reason::OK;
}
};
@ -134,7 +134,7 @@ public:
static HookPlugin<ScaleHook> p(
"scale",
"Scale signals by a factor and add offset",
HOOK_PATH | HOOK_NODE_READ | HOOK_NODE_WRITE,
(int) Hook::Flags::PATH | (int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE,
99
);

View file

@ -44,7 +44,7 @@ public:
json_error_t err;
int ret;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s: i }",
"offset", &offset
@ -52,16 +52,16 @@ public:
if (ret)
throw ConfigError(cfg, err, "node-config-hook-shift_seq");
state = STATE_PARSED;
state = State::PARSED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
smp->sequence += offset;
return HOOK_OK;
return Reason::OK;
}
};
@ -69,7 +69,7 @@ public:
static HookPlugin<ShiftSequenceHook> p(
"shift_seq",
"Shift sequence number of samples",
HOOK_NODE_READ | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::PATH,
99
);

View file

@ -24,7 +24,7 @@
* @{
*/
#include <string.h>
#include <cstring>
#include <villas/hook.hpp>
#include <villas/timing.h>
@ -55,7 +55,7 @@ public:
int ret;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s?: s, s: F }",
"mode", &m,
@ -75,14 +75,14 @@ public:
offset = time_from_double(o);
state = STATE_PARSED;
state = State::PARSED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
timespec *ts;
assert(state == STATE_STARTED);
assert(state == State::STARTED);
switch (mode) {
case SHIFT_ORIGIN:
@ -94,12 +94,12 @@ public:
break;
default:
return HOOK_ERROR;
return Hook::Reason::ERROR;
}
*ts = time_add(ts, &offset);;
return HOOK_OK;
return Reason::OK;
}
};
@ -107,7 +107,7 @@ public:
static HookPlugin<ShiftTimestampHook> p(
"shift_ts",
"Shift timestamps of samples",
HOOK_NODE_READ | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::PATH,
99
);

View file

@ -34,15 +34,15 @@ namespace node {
class SkipFirstHook : public Hook {
protected:
enum {
HOOK_SKIP_FIRST_STATE_STARTED, /**< Path just started. First sample not received yet. */
HOOK_SKIP_FIRST_STATE_SKIPPING, /**< First sample received. Skipping samples now. */
HOOK_SKIP_FIRST_STATE_NORMAL /**< All samples skipped. Normal operation. */
enum class SkipState {
STARTED, /**< Path just started. First sample not received yet. */
SKIPPING, /**< First sample received. Skipping samples now. */
NORMAL /**< All samples skipped. Normal operation. */
} skip_state;
enum {
HOOK_SKIP_MODE_SECONDS,
HOOK_SKIP_MODE_SAMPLES
enum class Mode {
SECONDS,
SAMPLES
} mode;
union {
@ -67,22 +67,22 @@ public:
int ret;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
ret = json_unpack_ex(cfg, &err, 0, "{ s: F }", "seconds", &s);
if (!ret) {
seconds.wait = time_from_double(s);
mode = HOOK_SKIP_MODE_SECONDS;
mode = Mode::SECONDS;
state = STATE_PARSED;
state = State::PARSED;
return;
}
ret = json_unpack_ex(cfg, &err, 0, "{ s: i }", "samples", &samples.wait);
if (!ret) {
mode = HOOK_SKIP_MODE_SAMPLES;
mode = Mode::SAMPLES;
state = STATE_PARSED;
state = State::PARSED;
return;
}
@ -91,44 +91,44 @@ public:
virtual void restart()
{
skip_state = HOOK_SKIP_FIRST_STATE_STARTED;
skip_state = SkipState::STARTED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
/* Remember sequence no or timestamp of first sample. */
if (skip_state == HOOK_SKIP_FIRST_STATE_STARTED) {
if (skip_state == SkipState::STARTED) {
switch (mode) {
case HOOK_SKIP_MODE_SAMPLES:
case Mode::SAMPLES:
samples.until = smp->sequence + samples.wait;
break;
case HOOK_SKIP_MODE_SECONDS:
case Mode::SECONDS:
seconds.until = time_add(&smp->ts.origin, &seconds.wait);
break;
}
skip_state = HOOK_SKIP_FIRST_STATE_SKIPPING;
skip_state = SkipState::SKIPPING;
}
switch (mode) {
case HOOK_SKIP_MODE_SAMPLES:
case Mode::SAMPLES:
if (samples.until > smp->sequence)
return HOOK_SKIP_SAMPLE;
return Hook::Reason::SKIP_SAMPLE;
break;
case HOOK_SKIP_MODE_SECONDS:
case Mode::SECONDS:
if (time_delta(&seconds.until, &smp->ts.origin) < 0)
return HOOK_SKIP_SAMPLE;
return Hook::Reason::SKIP_SAMPLE;
break;
default:
break;
}
return HOOK_OK;
return Reason::OK;
}
};
@ -136,7 +136,7 @@ public:
static HookPlugin<SkipFirstHook> p(
"skip_first",
"Skip the first samples",
HOOK_NODE_READ | HOOK_NODE_WRITE | HOOK_PATH,
(int) Hook::Flags::NODE_READ | (int) Hook::Flags::NODE_WRITE | (int) Hook::Flags::PATH,
99
);

View file

@ -24,13 +24,13 @@
* @{
*/
#include <string.h>
#include <memory>
#include <villas/common.h>
#include <villas/advio.h>
#include <villas/hook.hpp>
#include <villas/node/exceptions.hpp>
#include <villas/stats.h>
#include <villas/stats.hpp>
#include <villas/node.h>
#include <villas/timing.h>
@ -48,18 +48,16 @@ public:
StatsWriteHook(struct path *p, struct node *n, int fl, int prio, bool en = true) :
Hook(p, n, fl, prio, en)
{
state = STATE_CHECKED;
state = State::CHECKED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
stats *s = node->stats;
timespec now = time_now();
stats_update(s, STATS_METRIC_AGE, time_delta(&smp->ts.received, &now));
node->stats->update(Stats::Metric::AGE, time_delta(&smp->ts.received, &now));
return HOOK_OK;
return Reason::OK;
}
};
@ -72,46 +70,44 @@ public:
StatsReadHook(struct path *p, struct node *n, int fl, int prio, bool en = true) :
Hook(p, n, fl, prio, en)
{
state = STATE_CHECKED;
state = State::CHECKED;
}
virtual void start()
{
assert(state == STATE_PREPARED);
assert(state == State::PREPARED);
last = nullptr;
state = STATE_STARTED;
state = State::STARTED;
}
virtual void stop()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
if (last)
sample_decref(last);
state = STATE_STOPPED;
state = State::STOPPED;
}
virtual int process(sample *smp)
virtual Hook::Reason process(sample *smp)
{
stats *s = node->stats;
if (last) {
if (smp->flags & last->flags & SAMPLE_HAS_TS_RECEIVED)
stats_update(s, STATS_METRIC_GAP_RECEIVED, time_delta(&last->ts.received, &smp->ts.received));
if (smp->flags & last->flags & (int) SampleFlags::HAS_TS_RECEIVED)
node->stats->update(Stats::Metric::GAP_RECEIVED, time_delta(&last->ts.received, &smp->ts.received));
if (smp->flags & last->flags & SAMPLE_HAS_TS_ORIGIN)
stats_update(s, STATS_METRIC_GAP_SAMPLE, time_delta(&last->ts.origin, &smp->ts.origin));
if (smp->flags & last->flags & (int) SampleFlags::HAS_TS_ORIGIN)
node->stats->update(Stats::Metric::GAP_SAMPLE, time_delta(&last->ts.origin, &smp->ts.origin));
if ((smp->flags & SAMPLE_HAS_TS_ORIGIN) && (smp->flags & SAMPLE_HAS_TS_RECEIVED))
stats_update(s, STATS_METRIC_OWD, time_delta(&smp->ts.origin, &smp->ts.received));
if ((smp->flags & (int) SampleFlags::HAS_TS_ORIGIN) && (smp->flags & (int) SampleFlags::HAS_TS_RECEIVED))
node->stats->update(Stats::Metric::OWD, time_delta(&smp->ts.origin, &smp->ts.received));
if (smp->flags & last->flags & SAMPLE_HAS_SEQUENCE) {
if (smp->flags & last->flags & (int) SampleFlags::HAS_SEQUENCE) {
int dist = smp->sequence - (int32_t) last->sequence;
if (dist != 1)
stats_update(s, STATS_METRIC_SMPS_REORDERED, dist);
node->stats->update(Stats::Metric::SMPS_REORDERED, dist);
}
}
@ -122,49 +118,37 @@ public:
last = smp;
return HOOK_OK;
return Reason::OK;
}
};
class StatsHook : public Hook {
protected:
struct stats stats;
StatsReadHook *readHook;
StatsWriteHook *writeHook;
enum stats_format format;
enum Stats::Format format;
int verbose;
int warmup;
int buckets;
std::shared_ptr<Stats> stats;
AFILE *output;
char *uri;
std::string uri;
public:
StatsHook(struct path *p, struct node *n, int fl, int prio, bool en = true) :
Hook(p, n, fl, prio, en),
format(STATS_FORMAT_HUMAN),
format(Stats::Format::HUMAN),
verbose(0),
warmup(500),
buckets(20),
output(nullptr),
uri(nullptr)
uri()
{
int ret;
stats.state = STATE_DESTROYED;
ret = stats_init(&stats, buckets, warmup);
if (ret)
throw RuntimeError("Failed to initialize stats");
/* Register statistic object to path.
*
* This allows the path code to update statistics. */
node->stats = &stats;
/* Add child hooks */
readHook = new StatsReadHook(p, n, fl, prio, en);
writeHook = new StatsWriteHook(p, n, fl, prio, en);
@ -173,60 +157,51 @@ public:
vlist_push(&node->out.hooks, (void *) writeHook);
}
~StatsHook()
{
if (uri)
free(uri);
if (stats.state != STATE_DESTROYED)
stats_destroy(&stats);
}
virtual void start()
{
assert(state == STATE_PREPARED);
assert(state == State::PREPARED);
if (uri) {
output = afopen(uri, "w+");
if (!uri.empty()) {
output = afopen(uri.c_str(), "w+");
if (!output)
throw RuntimeError("Failed to open file '{}' for writing", uri);
}
state = STATE_STARTED;
state = State::STARTED;
}
virtual void stop()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
stats_print(&stats, uri ? output->file : stdout, format, verbose);
stats->print(uri.empty() ? stdout : output->file, format, verbose);
if (uri)
if (!uri.empty())
afclose(output);
state = STATE_STOPPED;
state = State::STOPPED;
}
virtual void restart()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
stats_reset(&stats);
stats->reset();
}
virtual void periodic()
{
assert(state == STATE_STARTED);
assert(state == State::STARTED);
stats_print_periodic(&stats, uri ? output->file : stdout, format, node);
stats->printPeriodic(uri.empty() ? stdout : output->file, format, node);
}
virtual void parse(json_t *cfg)
{
int ret, fmt;
int ret;
json_error_t err;
assert(state != STATE_STARTED);
assert(state != State::STARTED);
const char *f = nullptr;
const char *u = nullptr;
@ -242,17 +217,31 @@ public:
throw ConfigError(cfg, err, "node-config-hook-stats");
if (f) {
fmt = stats_lookup_format(f);
if (fmt < 0)
try {
format = Stats::lookupFormat(f);
} catch (std::invalid_argument &e) {
throw ConfigError(cfg, "node-config-hook-stats", "Invalid statistic output format: {}", f);
format = static_cast<stats_format>(fmt);
}
}
if (u)
uri = strdup(u);
uri = u;
state = STATE_PARSED;
state = State::PARSED;
}
virtual void prepare()
{
assert(state == State::CHECKED);
stats = std::make_shared<villas::Stats>(buckets, warmup);
/* Register statistic object to path.
*
* This allows the path code to update statistics. */
node->stats = stats;
state = State::PREPARED;
}
};
@ -260,7 +249,7 @@ public:
static HookPlugin<StatsHook> p(
"stats",
"Collect statistics for the current path",
HOOK_NODE_READ,
(int) Hook::Flags::NODE_READ,
99
);

Some files were not shown because too many files have changed in this diff Show more