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:
commit
51527d3403
184 changed files with 4831 additions and 3341 deletions
103
.gitlab-ci.yml
103
.gitlab-ci.yml
|
@ -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+)+$/"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
15
cmake/toolchains/debian-arm64.cmake
Normal file
15
cmake/toolchains/debian-arm64.cmake
Normal 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}")
|
||||
|
15
cmake/toolchains/debian-armhf.cmake
Normal file
15
cmake/toolchains/debian-armhf.cmake
Normal 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
2
common
|
@ -1 +1 @@
|
|||
Subproject commit 907e81d81b466126c09a91e3cd2b93d138cb6b96
|
||||
Subproject commit 43fd33c9c77db22b93f65c92a1acb25c141d42a3
|
22
etc/examples/hooks/gate.conf
Normal file
22
etc/examples/hooks/gate.conf
Normal 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
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
|
@ -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
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
13
etc/examples/nodes/exec.conf
Normal file
13
etc/examples/nodes/exec.conf
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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. */
|
||||
|
|
|
@ -51,7 +51,7 @@ class Socket;
|
|||
class Server {
|
||||
|
||||
protected:
|
||||
enum state state;
|
||||
enum State state;
|
||||
|
||||
Api *api;
|
||||
Logger logger;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <jansson.h>
|
||||
|
||||
#include <villas/queue.h>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
|
||||
/* Forward declarations. */
|
||||
struct io;
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
|
||||
/* Forward declarations */
|
||||
struct sample;
|
||||
|
|
|
@ -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__)
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <cstdlib>
|
||||
|
||||
/* Forward declarations. */
|
||||
struct sample;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <cstdio>
|
||||
|
||||
/* Forward declarations */
|
||||
struct io;
|
||||
|
|
|
@ -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
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -60,7 +60,7 @@ public:
|
|||
|
||||
virtual void parse(json_t *cfg);
|
||||
|
||||
virtual int process(sample *smp);
|
||||
virtual Hook::Reason process(sample *smp);
|
||||
};
|
||||
|
||||
} /* namespace node */
|
||||
|
|
|
@ -58,7 +58,7 @@ public:
|
|||
|
||||
virtual void parse(json_t *cfg);
|
||||
|
||||
virtual int process(sample *smp);
|
||||
virtual Hook::Reason process(sample *smp);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <netlink/route/qdisc.h>
|
||||
#include <netlink/route/classifier.h>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <netlink/route/qdisc.h>
|
||||
#include <netlink/route/classifier.h>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
74
include/villas/nodes/exec.hpp
Normal file
74
include/villas/nodes/exec.hpp
Normal 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);
|
||||
|
||||
/** @} */
|
|
@ -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. */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
|
||||
#include <libiec61850/sv_publisher.h>
|
||||
#include <libiec61850/sv_subscriber.h>
|
||||
|
|
|
@ -41,7 +41,7 @@ struct sample;
|
|||
*/
|
||||
struct loopback {
|
||||
int queuelen;
|
||||
int queueflags;
|
||||
enum QueueSignalledMode mode;
|
||||
struct queue_signalled queue;
|
||||
struct pool pool;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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). */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
132
include/villas/stats.hpp
Normal 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 */
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
12
lib/api.cpp
12
lib/api.cpp
|
@ -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()
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -99,7 +99,7 @@ public:
|
|||
return ret;
|
||||
|
||||
/* Properly terminate current instance */
|
||||
killme(SIGTERM);
|
||||
utils::killme(SIGTERM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
|
||||
virtual int execute(json_t *args, json_t **resp)
|
||||
{
|
||||
killme(SIGTERM);
|
||||
utils::killme(SIGTERM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <string.h>
|
||||
#include <cstring>
|
||||
|
||||
#include <villas/node/config.h>
|
||||
#include <villas/config_helper.hpp>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
18
lib/hook.cpp
18
lib/hook.cpp
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
206
lib/hooks/gate.cpp
Normal 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 */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
142
lib/hooks/pps_ts.cpp
Normal 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 */
|
||||
|
||||
/** @} */
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
|
||||
);
|
||||
|
||||
|
|
|
@ -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
Loading…
Add table
Reference in a new issue